/**
* Open the v1 migration SOURCES in-place, on the daemon's own corestore.
*
* The v1 layout is reconstructible from corestore namespaces alone (no key
* conveyance): prod created these autobases LOCALLY, so reopening with the
* same namespace + bootstrapKey:null re-attaches to the existing local-writer
* cores and replays their persisted ops.
*
* COLLISION-SAFE with the v2 per-org HyperOrgs on the SAME store (verified):
* - v1 single-orgs autobase cores live at namespace path ['orgs']
* (the Room's Autobase local + 'view' cores).
* - v2 HyperOrgs puts its index at ['orgs','orgs-index'] (name 'log') and
* each per-org Room at ['orgs','org/<name>']; it creates NOTHING directly
* at ['orgs'] root. Disjoint cores → old + new coexist in-place.
* - v1 org issue trackers live at namespace ['issues:org:<name>'] — wholly
* separate from 'orgs'.
*
* Reopen-replay is faithful: the orgsSchema / issuesSchema `create-org` /
* `create-issue` apply that built the persisted views is byte-identical
* between v1 (0.2.1) and now — only the autobase TOPOLOGY changed, not the
* view-building apply. So replaying the v1 log through the current schema
* yields the identical view.
*
* Every opener returns an object with `.view` (Hyperbee) + `.close()` that the
* caller MUST close. On a fresh store (no v1 data) the opener returns an empty
* autobase → readOldOrgs/readOldIssues yield nothing → the migration no-ops.
*/
import { Room } from 'hyper-rooms'
import { orgsSchema } from 'hyper-orgs'
import { HyperIssues } from 'hyper-issues'
/**
* Reopen the v1 single-`orgs` autobase (the migration source for orgs).
* @param {Corestore} corestore - the daemon's corestore (NOT pre-namespaced)
* @param {object} [opts]
* @param {string} [opts.namespace='orgs']
* @param {Buffer|string|null} [opts.bootstrapKey=null]
* @returns {Promise<Room>} a Room with `.view` (org:* Hyperbee) + `.close()`
*/
export async function openOldOrgsBase (corestore, opts = {}) {
const room = new Room(corestore, {
schema: orgsSchema,
namespace: opts.namespace || 'orgs',
bootstrapKey: opts.bootstrapKey || null
})
await room.ready()
return room
}
/**
* Build the `openOldOrgTracker(name)` closure the migration calls per org.
* Reopens each org's v1 separate `issues:org:<name>` tracker on the same
* corestore. Tracks opened trackers so the caller can close them all.
*
* @param {Corestore} corestore - the daemon's corestore
* @param {object} [opts]
* @param {(name:string)=>(Buffer|string|null)} [opts.bootstrapKeyFor] - look up
* a known v1 tracker bootstrapKey for an org (for trackers joined from
* elsewhere). Defaults to null (local-writer reopen by namespace) — correct
* for the ORIGIN daemon, where every org tracker was created locally.
* @returns {{ open: (name:string)=>Promise<HyperIssues>, closeAll: ()=>Promise<void> }}
*/
export function makeOpenOldOrgTracker (corestore, opts = {}) {
const bootstrapKeyFor = typeof opts.bootstrapKeyFor === 'function' ? opts.bootstrapKeyFor : () => null
const opened = []
return {
async open (name) {
const tracker = new HyperIssues(corestore, {
namespace: 'issues:org:' + name,
bootstrapKey: bootstrapKeyFor(name) || null
})
await tracker.ready()
opened.push(tracker)
return tracker
},
async closeAll () {
for (const t of opened.splice(0)) {
try { await t.close() } catch {}
}
}
}
}