// favela local-only scope (step 1) — Bare-native unit test (run: `bare test/local-scope.test.mjs`).
// No network: a FAKE peer serves records in both the public (app.bsky.feed.post) and local
// (net.favela.local.post) collections; assert the appview folds BOTH into one timeline, that the
// scope->collection map is correct, and that a local record carries the local $type (so bsky ignores
// it while favela renders it). This is the whole mechanism of step 1 — no hpp/bridge needed to prove it.
import '../lib/bare-globals.js'
import { storeDir } from './_store-dir.mjs'
import Corestore from 'corestore'
import { Appview } from '../lib/appview.js'
import { mkGetRecordStore } from './mk-record-store.mjs'
import { collectionForScope, scopeForCollection, SCOPE_COLLECTION, POST_COLLECTIONS } from '../lib/scopes.js'
const assert = (cond, msg) => { if (!cond) throw new Error('FAIL: ' + msg); console.log(' ok -', msg) }
// --- scope map ---------------------------------------------------------------
assert(collectionForScope('public') === 'app.bsky.feed.post', "public -> app.bsky.feed.post")
assert(collectionForScope('local') === 'net.favela.local.post', "local -> net.favela.local.post")
assert(scopeForCollection('net.favela.local.post') === 'local', 'reverse map: local NSID -> local scope')
assert(POST_COLLECTIONS.length === 2 && POST_COLLECTIONS.includes(SCOPE_COLLECTION.local), 'both collections are folded by the appview')
let threw = false
try { collectionForScope('secret') } catch { threw = true }
assert(threw, "unknown scope throws (no silent public fallback)")
// --- dual-collection fold ----------------------------------------------------
// A fake DidPeer: listRecords(collection) returns whatever we staged for that NSID (uri = "<did>/<coll>/<rkey>").
const DID = 'did:plc:fake'
const mk = (coll, rkey, text, createdAt) => ({ uri: `${DID}/${coll}/${rkey}`, cid: 'bafyfake', value: { $type: coll, text, createdAt } })
const fakePeer = {
did: DID,
_byCollection: {
'app.bsky.feed.post': [mk('app.bsky.feed.post', '1', 'public-post', '2026-07-01T00:00:00.000Z')],
'net.favela.local.post': [mk('net.favela.local.post', '2', 'local-post', '2026-07-05T00:00:00.000Z')]
},
listRecords (collection) { return this._byCollection[collection] || [] }
}
const dir = storeDir('local-scope-test')
const store = new Corestore(dir)
const av = await new Appview(store, { getRecordStore: mkGetRecordStore(dir + '/rec') }).ready()
const n = await av.indexPeer(fakePeer)
assert(n === 2, `indexPeer folded BOTH collections (${n} records)`)
const tl = await av.getTimeline({ limit: 10 })
assert(tl.posts.length === 2, 'timeline shows both the public and the local post')
const local = tl.posts.find(p => p.record.text === 'local-post')
const pub = tl.posts.find(p => p.record.text === 'public-post')
assert(local && pub, 'both posts are present in the timeline')
assert(local.record.$type === SCOPE_COLLECTION.local, "local post carries the net.favela.local.post $type (bsky ignores it; favela renders it)")
assert(pub.record.$type === SCOPE_COLLECTION.public, 'public post carries the app.bsky.feed.post $type (fronted to bsky)')
assert(tl.posts[0].record.text === 'local-post', 'timeline still reverse-chron across both collections (local is newer)')
console.log('\nLOCAL-SCOPE OK (Bare): scope map + appview folds public + net.favela.local.post into one timeline')
await av.close()
try { await store.close() } catch {}