OverviewFilesCommitsIssuesDocsReleasesPeers

favela-web / spike / mobile-pack-probe.mjs

66 lines · javascript ref:
// Mobile spike probe (org #36, spike 1) — does the favela-web closure survive bare-pack and still LOAD?
//
// ⛔ DELIBERATELY NOT bin/favela-web.js. Running the real entry would open the daemon's Corestore, and
// RocksDB holds an exclusive lock — a second process against the live storage is the one thing the
// operating rules say not to do. This imports the same heavy graph (native addons included) and proves
// it resolves, without opening prod state.
//
// The question is narrow and worth keeping narrow: bare-pack produced a bundle, but a bundle that cannot
// resolve its own module graph is a file, not a result. This exercises the parts most likely to break:
// the symlinked sibling packages (celltron hit MODULE_NOT_FOUND from exactly that), and the native
// addons, which under `--preset android` become `linked:` names the host app must supply.
//
// Run packed:  bare-pack --out /tmp/probe.bundle spike/mobile-pack-probe.mjs && bare /tmp/probe.bundle
// Run direct:  bare spike/mobile-pack-probe.mjs

// ⛔ FIRST, AND NOT OPTIONAL. bin/favela-web.js and every test here open with this, and the reason shows
// up immediately without it: the atproto stack reaches for TextEncoder, which Bare does not provide as a
// global, so atproto-repo/-store/-did-peer/-identity and lib/appview.js all fail to import with
// `TextEncoder is not defined`. That is a probe bug, not a packing finding — but it looks exactly like a
// packing finding, which is why it is called out here rather than silently fixed.
import '../lib/bare-globals.js'

const results = []
const check = async (label, fn) => {
  try {
    const v = await fn()
    results.push([true, label, v])
  } catch (e) {
    results.push([false, label, (e && e.message) || String(e)])
  }
}

// The holepunch substrate — every one of these carries a native addon.
await check('sodium-native', async () => { const m = await import('sodium-native'); return typeof m.default.crypto_generichash === 'function' ? 'crypto_generichash present' : 'loaded' })
await check('rocksdb-native', async () => { const m = await import('rocksdb-native'); return m.default ? 'class present' : 'loaded' })
await check('udx-native', async () => { const m = await import('udx-native'); return m.default ? 'class present' : 'loaded' })
await check('quickbit-native', async () => { await import('quickbit-native'); return 'loaded' })
await check('b4a', async () => { const m = await import('b4a'); return m.default.toString(m.default.from('ok')) })

// The atproto stack — these are the SYMLINKED SIBLINGS, the thing most likely to break.
await check('atproto-repo (codec)', async () => { const m = await import('atproto-repo/lib/repo.js'); return typeof m.readCar === 'function' ? 'readCar present' : 'loaded' })
await check('atproto-store (repo-diff)', async () => { const m = await import('atproto-store/lib/repo-diff.js'); return typeof m.repoDiffSince === 'function' ? 'repoDiffSince present' : 'loaded' })
await check('atproto-did-peer', async () => { const m = await import('atproto-did-peer'); return m.DidPeer ? 'DidPeer present' : 'loaded' })
await check('atproto-identity', async () => { await import('atproto-identity'); return 'loaded' })

// favela's own libs, including the ones this session touched.
await check('favela lib/appview.js', async () => { const m = await import('../lib/appview.js'); return 'INGEST_VERSION=' + m.INGEST_VERSION })
await check('favela lib/hosted-dids.js', async () => { const m = await import('../lib/hosted-dids.js'); return m.IGNORED_COLLECTIONS.size + ' ignored collections' })
await check('favela lib/roster.js', async () => { const m = await import('../lib/roster.js'); return typeof m.resolveRoster === 'function' ? 'resolveRoster present' : 'loaded' })

// Storage/networking classes — constructed, not opened. Constructing proves the addon linked; opening
// would create state, which a probe has no business doing.
await check('corestore (class)', async () => { const m = await import('corestore'); return typeof m.default === 'function' ? 'constructor present' : 'loaded' })
await check('hyperswarm (class)', async () => { const m = await import('hyperswarm'); return typeof m.default === 'function' ? 'constructor present' : 'loaded' })
await check('hyperbee (class)', async () => { const m = await import('hyperbee'); return typeof m.default === 'function' ? 'constructor present' : 'loaded' })

let ok = 0
for (const [good, label, detail] of results) {
  console.log(`  ${good ? 'ok  ' : 'FAIL'} - ${label.padEnd(28)} ${detail}`)
  if (good) ok++
}
console.log(`\n${ok}/${results.length} modules resolved and loaded`)
if (ok !== results.length) {
  console.log('\nA failure here is the spike result, not an accident — record which specifier failed.')
}