const PREFIX = 'mhu1_'; export function encode(payload) { if (!payload || typeof payload !== 'object') { throw new Error('encode: payload must be an object'); } const json = JSON.stringify(payload); const b64 = Buffer.from(json, 'utf8').toString('base64url'); return PREFIX + b64; } export function decode(code) { if (typeof code !== 'string') { throw new Error('Invalid code: expected a string'); } const trimmed = code.trim(); if (!trimmed.startsWith(PREFIX)) { throw new Error('Invalid code: missing "mhu1_" prefix'); } const b64 = trimmed.slice(PREFIX.length); if (!b64) { throw new Error('Invalid code: empty payload'); } let json; try { json = Buffer.from(b64, 'base64url').toString('utf8'); } catch { throw new Error('Invalid code: not valid base64url'); } let payload; try { payload = JSON.parse(json); } catch { throw new Error('Invalid code: payload is not valid JSON'); } if (!payload || typeof payload !== 'object') { throw new Error('Invalid code: payload is not an object'); } if (payload.v !== 1) { throw new Error(`Invalid code: unsupported version (expected v=1, got ${payload.v})`); } const host = payload.h !== undefined ? payload.h : payload.host; const port = payload.p !== undefined ? payload.p : payload.port; const token = payload.t !== undefined ? payload.t : payload.token; const label = payload.n !== undefined ? payload.n : payload.label; const scheme = payload.s === 'wss' ? 'wss' : 'ws'; if (host !== undefined && typeof host !== 'string') { throw new Error('Invalid code: "host" must be a string when present'); } if (typeof port !== 'number' || !Number.isFinite(port)) { throw new Error('Invalid code: "port" must be a number'); } if (typeof token !== 'string' || token.length === 0) { throw new Error('Invalid code: "token" must be a non-empty string'); } if (label !== undefined && typeof label !== 'string') { throw new Error('Invalid code: "label" must be a string'); } if (payload.fp !== undefined && typeof payload.fp !== 'string') { throw new Error('Invalid code: "fp" must be a string when present'); } return { v: 1, host: host ? String(host) : undefined, port, token, label: label !== undefined ? String(label) : undefined, fp: payload.fp, scheme }; }