#!/usr/bin/env node import { createHmac } from 'node:crypto' import { existsSync, readFileSync } from 'node:fs' import { dirname, join } from 'node:path' import { fileURLToPath } from 'node:url' const __dirname = dirname(fileURLToPath(import.meta.url)) const ROOT = join(__dirname, '..') function loadEnv() { const envPath = join(ROOT, '.env') if (!existsSync(envPath)) return for (const line of readFileSync(envPath, 'utf8').split('\n')) { const trimmed = line.trim() if (!trimmed || trimmed.startsWith('#')) continue const eq = trimmed.indexOf('=') if (eq <= 0) continue const key = trimmed.slice(0, eq).trim() let value = trimmed.slice(eq + 1).trim() if ( (value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'")) ) { value = value.slice(1, -1) } if (!(key in process.env)) process.env[key] = value } } loadEnv() const args = process.argv.slice(2) function arg(name, fallback) { const idx = args.indexOf(`--${name}`) if (idx >= 0 && args[idx + 1]) return args[idx + 1] return fallback } const deviceId = arg('deviceId', '*') const daysArg = arg('days', null) const secret = process.env.OPSX_LICENSE_HMAC || 'opsxshell-dev-license-hmac-v1-change-in-prod' function b64url(buf) { return Buffer.from(buf) .toString('base64') .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/=+$/g, '') } const now = Math.floor(Date.now() / 1000) const payload = { plan: 'pro', deviceId, iat: now, features: ['*'], } if (daysArg != null) { payload.exp = now + Number(daysArg) * 86400 } const payloadB64 = b64url(JSON.stringify(payload)) const sig = createHmac('sha256', secret).update(payloadB64).digest() const token = `opsx1.${payloadB64}.${b64url(sig)}` console.log(JSON.stringify({ token, payload }, null, 2))