feat: slot system + entries/priority/errorreport + typert generator
This commit is contained in:
@@ -31,6 +31,8 @@ function hostOver(core: SlotCore): SlotRendererHost {
|
||||
subscribe: (key, fn) => core.subscribe(key, fn),
|
||||
getVersion: key => core.getVersion(key),
|
||||
entriesOf: key => core.entries(key),
|
||||
entriesOfSlot: key => core.entriesOfSlot(key),
|
||||
reportEntryError: (key, entry, error, info) => { core.reportEntryError(key, entry, error, info) },
|
||||
specOf: key => core.specDynamic(key),
|
||||
isLive: entry => core.isLive(entry),
|
||||
storeOf: () => undefined,
|
||||
|
||||
@@ -83,6 +83,7 @@ function makeHost() {
|
||||
const versions = new Map<string, number>()
|
||||
const subs = new Map<string, Set<() => void>>()
|
||||
const live = new Set<StoredEntry>()
|
||||
const abdicated = new Set<StoredEntry>()
|
||||
const storeCache = new Map<StoredEntry, Map<string, StoreInstanceLike>>()
|
||||
const list = observable<{ ids: string[] }>({ ids: [] })
|
||||
const workspaces = observable<{ ids: string[] }>({ ids: [] })
|
||||
@@ -105,6 +106,28 @@ function makeHost() {
|
||||
},
|
||||
getVersion: key => versions.get(key) ?? 0,
|
||||
entriesOf: key => entries.get(key) ?? [],
|
||||
entriesOfSlot: (key) => {
|
||||
const all = entries.get(key) ?? []
|
||||
const kind = specs.get(key)?.kind
|
||||
if (kind === 'chain') return all
|
||||
// Mirror the ledger projection: first live (non-abdicated) entry per
|
||||
// cell (single — one cell; keyed — per key; list — per id).
|
||||
const heads: StoredEntry[] = []
|
||||
const seen = new Set<string | undefined>()
|
||||
for (const entry of all) {
|
||||
if (abdicated.has(entry)) continue
|
||||
const cell = kind === 'keyed' ? entry.options.key : kind === 'list' ? entry.options.id : undefined
|
||||
if (seen.has(cell)) continue
|
||||
seen.add(cell)
|
||||
heads.push(entry)
|
||||
}
|
||||
return heads
|
||||
},
|
||||
reportEntryError: (key, entry, _error, info) => {
|
||||
if (!info.abdicate || abdicated.has(entry)) return
|
||||
abdicated.add(entry)
|
||||
bump(key)
|
||||
},
|
||||
specOf: key => specs.get(key),
|
||||
isLive: entry => live.has(entry),
|
||||
storeOf: (entry, scopeKey) => {
|
||||
@@ -147,11 +170,12 @@ function makeHost() {
|
||||
add: (key: string, partial: Omit<StoredEntry, 'options'> & { options?: StoredEntry['options'] }) => {
|
||||
const entry = entryOf(partial)
|
||||
const next = [...(entries.get(key) ?? []), entry]
|
||||
// Mirror the ledger contract: chain entries arrive priority-sorted
|
||||
// (stable, ascending) — outlets iterate entries() order as-is.
|
||||
if (specs.get(key)?.kind === 'chain') {
|
||||
next.sort((a, b) => (a.options.priority ?? 0) - (b.options.priority ?? 0))
|
||||
}
|
||||
// Mirror the ledger contract: entries arrive priority-sorted (stable,
|
||||
// ascending; list refines equal priorities by order) — outlets iterate
|
||||
// entries() order as-is.
|
||||
next.sort(specs.get(key)?.kind === 'list'
|
||||
? (a, b) => ((a.options.priority ?? 0) - (b.options.priority ?? 0)) || ((a.options.order ?? 0) - (b.options.order ?? 0))
|
||||
: (a, b) => (a.options.priority ?? 0) - (b.options.priority ?? 0))
|
||||
entries.set(key, next)
|
||||
live.add(entry)
|
||||
bump(key)
|
||||
|
||||
@@ -46,6 +46,10 @@ function makeHost(bodies: { root: (rp: (key: string, owner: object) => React.Rea
|
||||
subscribe: () => () => {},
|
||||
getVersion: () => 0,
|
||||
entriesOf: key => key === 'root' ? [rootEntry] : sessionEntries,
|
||||
// Single-kind everywhere and no crashes in this suite: the projection is
|
||||
// the raw view and crash reports never fire.
|
||||
entriesOfSlot: key => key === 'root' ? [rootEntry] : sessionEntries,
|
||||
reportEntryError: () => {},
|
||||
specOf: key => key === 'k.session' ? { kind: 'single', scope: 'session' } : undefined,
|
||||
isLive: () => true,
|
||||
storeOf: () => undefined,
|
||||
|
||||
@@ -35,6 +35,10 @@ function makeHost() {
|
||||
},
|
||||
getVersion: key => versions.get(key) ?? 0,
|
||||
entriesOf: key => entries.get(key) ?? [],
|
||||
// Single-kind everywhere and no crashes in this suite: the projection is
|
||||
// the raw view and crash reports never fire.
|
||||
entriesOfSlot: key => entries.get(key) ?? [],
|
||||
reportEntryError: () => {},
|
||||
specOf: () => ({ kind: 'single', scope: 'root' }),
|
||||
isLive: entry => live.has(entry),
|
||||
storeOf: () => undefined,
|
||||
|
||||
@@ -49,6 +49,10 @@ function makeHost() {
|
||||
subscribe: () => () => {},
|
||||
getVersion: () => 0,
|
||||
entriesOf: key => key === 'root' ? [rootEntry] : sessionEntries,
|
||||
// Single-kind everywhere and no crashes in this suite: the projection is
|
||||
// the raw view and crash reports never fire.
|
||||
entriesOfSlot: key => key === 'root' ? [rootEntry] : sessionEntries,
|
||||
reportEntryError: () => {},
|
||||
specOf: key => key === 'k.session' ? { kind: 'single', scope: 'session' } : undefined,
|
||||
isLive: () => true,
|
||||
storeOf: () => undefined,
|
||||
|
||||
Reference in New Issue
Block a user