diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/feature-registry-check.js | 51 | ||||
| -rw-r--r-- | tools/minimal-smoke.js | 7 | ||||
| -rw-r--r-- | tools/nostr-login-test.js | 2 |
3 files changed, 27 insertions, 33 deletions
diff --git a/tools/feature-registry-check.js b/tools/feature-registry-check.js index 9b7ac5e..0931156 100644 --- a/tools/feature-registry-check.js +++ b/tools/feature-registry-check.js @@ -1,40 +1,29 @@ -// Guard: src/features/index.js and build.js's ALL_FEATURES must agree. +// Guard: src/features/index.js and build.js's featureIndexSource must agree. // They drifted once (nwc was added to index.js only, so its i18n strings // shipped but its code never did — the settings card silently never rendered, // because build.js SWAPS OUT features/index.js for a generated module). +// +// The strongest form of agreement is equality: the checked-in module must be +// code-identical (comments and whitespace aside) to what featureIndexSource +// generates for the full feature set — imports, construction order, deferred +// placeholder slots, and the deferred loader all included. // bun tools/feature-registry-check.js import { readFileSync } from 'node:fs'; +import { featureIndexSource, enabledFeatures } from '../build.js'; -const idx = readFileSync(new URL('../src/features/index.js', import.meta.url), 'utf8'); -const build = readFileSync(new URL('../build.js', import.meta.url), 'utf8'); +const strip = (s) => s + .replace(/\/\/[^\n]*/g, '') // line comments + .replace(/\s+/g, ' ') // whitespace runs + .replace(/, /g, ',').replace(/ ,/g, ',') + .trim(); -const inIndex = [...idx.matchAll(/import \{ (\w+Feature) \} from '\.\/([\w-]+)\.js'/g)] - .map((m) => ({ fn: m[1], name: m[2] })); -const registry = build.match(/const ALL_FEATURES = \{([^}]*)\}/s)?.[1] || ''; -const inBuild = [...registry.matchAll(/(\w+):\s*'(\w+Feature)'/g)].map((m) => ({ name: m[1], fn: m[2] })); +const idx = readFileSync(new URL('../src/features/index.js', import.meta.url), 'utf8'); +const gen = featureIndexSource(enabledFeatures(undefined)); -let ok = true; -for (const f of inIndex) { - if (!inBuild.find((b) => b.fn === f.fn)) { - console.log(`x ${f.fn} (${f.name}.js) is in features/index.js but NOT in build.js ALL_FEATURES — it will not ship`); - ok = false; - } -} -for (const b of inBuild) { - if (!inIndex.find((f) => f.fn === b.fn)) { - console.log(`x ${b.fn} is in build.js ALL_FEATURES but not imported in features/index.js`); - ok = false; - } -} -// Compare the ORDER FEATURES ARE CONSTRUCTED IN (hook precedence depends on -// it), not the order they happen to be imported in. -const built = [...(idx.match(/return \[([^\]]*)\]/s)?.[1] || '') - .matchAll(/(\w+Feature)\(ctx\)/g)].map((m) => m[1]); -const orderIdx = built.join(','); -const orderBuild = inBuild.map((b) => b.fn).join(','); -if (ok && orderIdx !== orderBuild) { - console.log(`x feature ORDER differs (hook precedence depends on it)\n index.js: ${orderIdx}\n build.js: ${orderBuild}`); - ok = false; +if (strip(idx) !== strip(gen)) { + console.log('x src/features/index.js does not match build.js featureIndexSource (full set)'); + console.log('\n--- generated (normalized) ---\n' + strip(gen)); + console.log('\n--- checked in (normalized) ---\n' + strip(idx)); + process.exit(1); } -if (ok) console.log(`ok ${inIndex.length} features registered consistently`); -process.exit(ok ? 0 : 1); +console.log(`ok features/index.js matches the generator (${enabledFeatures(undefined).length} features, deferred slots included)`); diff --git a/tools/minimal-smoke.js b/tools/minimal-smoke.js index bd0d588..f3f896c 100644 --- a/tools/minimal-smoke.js +++ b/tools/minimal-smoke.js @@ -29,7 +29,10 @@ check('no ark protocol code', !html.includes('Ark VTXO mailbox authorization')); check('no swap protocol code', !html.includes('swap/reverse')); check('no musig code', !html.includes('MuSig/noncecoef')); check('no silent-payment engine', !html.includes('BIP0352') && !html.includes('__SP_WORKER__')); -check('no nostr sync code', !html.includes('30078') && !html.includes('relay.coinos.io')); +// The sync EVENT KIND must be gone; the coinos relay hostname alone is not a +// sync marker anymore — recipient search (send-to-npub, core UX) carries +// PROFILE_RELAYS for profile lookups even in the minimal build. +check('no nostr sync code', !html.includes('30078')); const server = Bun.serve({ port: 5198, fetch: () => new Response(html, { headers: { 'content-type': 'text/html' } }) }); @@ -62,6 +65,8 @@ try { await sleep(400); console.log('\n[1] import + core wallet'); + await clickText('button', 'Get started'); // the front door gained a step + await sleep(300); await clickText('button', 'Import existing'); await sleep(200); await page.type('textarea', generateMnemonic(wordlist)); diff --git a/tools/nostr-login-test.js b/tools/nostr-login-test.js index 468ffb4..25983a4 100644 --- a/tools/nostr-login-test.js +++ b/tools/nostr-login-test.js @@ -58,7 +58,7 @@ check('another account cannot decrypt it', denied); console.log('\n[NIP-98 auth]'); { - const { nip98Header } = await import('../src/nostr-login.js'); + const { nip98Header } = await import('../src/nip98.js'); const { verifyEvent } = await import('nostr-tools/pure'); const { sha256: sha } = await import('@noble/hashes/sha256'); const body = JSON.stringify({ name: 'x' }); |
