doxum 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -2
- package/dist/{contract-DwNiKioc.d.ts → contract-BsY1XLiG.d.ts} +64 -5
- package/dist/{contract-Otb5W6cQ.d.cts → contract-D8kjdfqT.d.cts} +64 -5
- package/dist/{dependency-BdEMyquf.js → dependency-C5_R1tvQ.js} +24 -263
- package/dist/dependency-C5_R1tvQ.js.map +1 -0
- package/dist/{dependency-DLcCvNKq.cjs → dependency-Dfzs3khk.cjs} +48 -341
- package/dist/dependency-Dfzs3khk.cjs.map +1 -0
- package/dist/driver-CNxqMVFH.cjs +69 -0
- package/dist/driver-CNxqMVFH.cjs.map +1 -0
- package/dist/driver-CbzfW5MR.js +46 -0
- package/dist/driver-CbzfW5MR.js.map +1 -0
- package/dist/index.cjs +428 -133
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -5
- package/dist/index.d.ts +8 -5
- package/dist/index.js +352 -61
- package/dist/index.js.map +1 -1
- package/dist/integration.cjs +1 -1
- package/dist/integration.cjs.map +1 -1
- package/dist/integration.d.cts +2 -2
- package/dist/integration.d.ts +2 -2
- package/dist/integration.js +1 -1
- package/dist/integration.js.map +1 -1
- package/dist/local-sync.cjs +485 -0
- package/dist/local-sync.cjs.map +1 -0
- package/dist/local-sync.d.cts +74 -0
- package/dist/local-sync.d.ts +74 -0
- package/dist/local-sync.js +476 -0
- package/dist/local-sync.js.map +1 -0
- package/dist/ownership-B-VAPcce.js +242 -0
- package/dist/ownership-B-VAPcce.js.map +1 -0
- package/dist/ownership-CU-9DKJQ.cjs +301 -0
- package/dist/ownership-CU-9DKJQ.cjs.map +1 -0
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js.map +1 -1
- package/package.json +14 -8
- package/skills/doxum-runtime/references/guide.en.md +60 -5
- package/skills/doxum-runtime/references/guide.zh-CN.md +48 -2
- package/skills/doxum-runtime/references/invariants.en.md +23 -8
- package/skills/doxum-runtime/references/invariants.zh-CN.md +2 -2
- package/dist/dependency-BdEMyquf.js.map +0 -1
- package/dist/dependency-DLcCvNKq.cjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ownership-CU-9DKJQ.cjs","names":[],"sources":["../core/src/profile.ts","../core/src/value/ownership.ts"],"sourcesContent":["export type CloneReason =\n 'initial' | 'canonical' | 'commit' | 'inverse' | 'reader' | 'replace' | 'journal' | 'snapshot';\n\ntype CloneCounters = {\n calls: number;\n containers: number;\n nodes: Record<CloneReason, number>;\n deepEqual: { calls: number; containers: number };\n documents: { initial: number };\n};\ntype ProfileCounters = {\n clone: CloneCounters;\n mutation: { normalized: number; executed: number; inverseCreated: number };\n batch: {\n operations: number;\n entries: number;\n collectionsResolved: number;\n journalRecords: number;\n rejected: number;\n inverseOperations: number;\n payloadTransferred: number;\n payloadSnapshots: number;\n };\n journal: {\n subjects: number;\n comparisons: number;\n absorbed: number;\n orderSnapshots: number;\n orderItems: number;\n };\n address: {\n schemaSteps: number;\n documentSteps: number;\n prefixComparisons: number;\n segmentsCompared: number;\n arraysCopied: number;\n };\n impact: { affectsChecks: number };\n reader: {\n sessions: number;\n nodeLookups: number;\n collectionIds: number;\n structuralSnapshots: number;\n };\n collectionView: {\n mappedItems: number;\n idsScanned: number;\n arraysCopied: number;\n };\n materialized: {\n updated: number;\n skipped: number;\n rebuilt: number;\n sourceChanges: number;\n notifications: number;\n };\n};\n\nexport type ProfileSnapshot = Readonly<{\n clone: Readonly<{\n calls: number;\n containers: number;\n nodes: Readonly<Record<CloneReason, number>>;\n deepEqual: Readonly<{ calls: number; containers: number }>;\n documents: Readonly<{ initial: number }>;\n }>;\n mutation: Readonly<{\n normalized: number;\n executed: number;\n inverseCreated: number;\n }>;\n batch: Readonly<ProfileCounters['batch']>;\n journal: Readonly<ProfileCounters['journal']>;\n address: Readonly<ProfileCounters['address']>;\n impact: Readonly<ProfileCounters['impact']>;\n reader: Readonly<ProfileCounters['reader']>;\n collectionView: Readonly<ProfileCounters['collectionView']>;\n materialized: Readonly<ProfileCounters['materialized']>;\n}>;\n\nconst cloneReasons = (): Record<CloneReason, number> => ({\n initial: 0,\n canonical: 0,\n commit: 0,\n inverse: 0,\n reader: 0,\n replace: 0,\n journal: 0,\n snapshot: 0,\n});\n\nconst counters = (): ProfileCounters => ({\n clone: {\n calls: 0,\n containers: 0,\n nodes: cloneReasons(),\n deepEqual: { calls: 0, containers: 0 },\n documents: { initial: 0 },\n },\n mutation: { normalized: 0, executed: 0, inverseCreated: 0 },\n batch: {\n operations: 0,\n entries: 0,\n collectionsResolved: 0,\n journalRecords: 0,\n rejected: 0,\n inverseOperations: 0,\n payloadTransferred: 0,\n payloadSnapshots: 0,\n },\n journal: {\n subjects: 0,\n comparisons: 0,\n absorbed: 0,\n orderSnapshots: 0,\n orderItems: 0,\n },\n address: {\n schemaSteps: 0,\n documentSteps: 0,\n prefixComparisons: 0,\n segmentsCompared: 0,\n arraysCopied: 0,\n },\n impact: { affectsChecks: 0 },\n reader: {\n sessions: 0,\n nodeLookups: 0,\n collectionIds: 0,\n structuralSnapshots: 0,\n },\n collectionView: { mappedItems: 0, idsScanned: 0, arraysCopied: 0 },\n materialized: {\n updated: 0,\n skipped: 0,\n rebuilt: 0,\n sourceChanges: 0,\n notifications: 0,\n },\n});\n\n// Recorder calls are stable no-op-capable functions. Only this module owns the\n// mutable session counter tree; domain code never branches on profile state.\nconst active = { current: undefined as ProfileCounters | undefined };\n\n// Snapshot allocation is intentionally delayed until the caller asks for it.\nconst freezeSnapshot = (value: ProfileCounters): ProfileSnapshot =>\n Object.freeze({\n clone: Object.freeze({\n calls: value.clone.calls,\n containers: value.clone.containers,\n nodes: Object.freeze({ ...value.clone.nodes }),\n deepEqual: Object.freeze({ ...value.clone.deepEqual }),\n documents: Object.freeze({ ...value.clone.documents }),\n }),\n mutation: Object.freeze({ ...value.mutation }),\n batch: Object.freeze({ ...value.batch }),\n journal: Object.freeze({ ...value.journal }),\n address: Object.freeze({ ...value.address }),\n impact: Object.freeze({ ...value.impact }),\n reader: Object.freeze({ ...value.reader }),\n collectionView: Object.freeze({ ...value.collectionView }),\n materialized: Object.freeze({ ...value.materialized }),\n });\n\nexport const profile = {\n clone: {\n call: (): void => {\n const value = active.current;\n if (value) value.clone.calls += 1;\n },\n node: (reason: CloneReason): void => {\n const value = active.current;\n if (!value) return;\n value.clone.nodes[reason] += 1;\n },\n container: (): void => {\n const value = active.current;\n if (value) value.clone.containers += 1;\n },\n deepEqual: (): void => {\n const value = active.current;\n if (value) value.clone.deepEqual.calls += 1;\n },\n deepEqualContainer: (): void => {\n const value = active.current;\n if (value) value.clone.deepEqual.containers += 1;\n },\n initialDocument: (): void => {\n const value = active.current;\n if (value) value.clone.documents.initial += 1;\n },\n },\n mutation: {\n normalized: (): void => {\n const value = active.current;\n if (value) value.mutation.normalized += 1;\n },\n executed: (): void => {\n const value = active.current;\n if (value) value.mutation.executed += 1;\n },\n inverse: (): void => {\n const value = active.current;\n if (value) value.mutation.inverseCreated += 1;\n },\n },\n batch: {\n operation: (): void => {\n const value = active.current;\n if (value) value.batch.operations += 1;\n },\n entry: (amount = 1): void => {\n const value = active.current;\n if (value) value.batch.entries += amount;\n },\n collectionResolved: (): void => {\n const value = active.current;\n if (value) value.batch.collectionsResolved += 1;\n },\n journalRecord: (): void => {\n const value = active.current;\n if (value) value.batch.journalRecords += 1;\n },\n rejected: (): void => {\n const value = active.current;\n if (value) value.batch.rejected += 1;\n },\n inverse: (): void => {\n const value = active.current;\n if (value) value.batch.inverseOperations += 1;\n },\n payloadTransferred: (): void => {\n const value = active.current;\n if (value) value.batch.payloadTransferred += 1;\n },\n payloadSnapshot: (): void => {\n const value = active.current;\n if (value) value.batch.payloadSnapshots += 1;\n },\n },\n journal: {\n subject: (): void => {\n const value = active.current;\n if (value) value.journal.subjects += 1;\n },\n comparison: (): void => {\n const value = active.current;\n if (value) value.journal.comparisons += 1;\n },\n absorbed: (): void => {\n const value = active.current;\n if (value) value.journal.absorbed += 1;\n },\n orderSnapshot: (items: number): void => {\n const value = active.current;\n if (!value) return;\n value.journal.orderSnapshots += 1;\n value.journal.orderItems += items;\n },\n },\n address: {\n schemaStep: (): void => {\n const value = active.current;\n if (value) value.address.schemaSteps += 1;\n },\n documentStep: (): void => {\n const value = active.current;\n if (value) value.address.documentSteps += 1;\n },\n arrayCopied: (): void => {\n const value = active.current;\n if (value) value.address.arraysCopied += 1;\n },\n prefixComparison: (): void => {\n const value = active.current;\n if (value) value.address.prefixComparisons += 1;\n },\n segmentCompared: (): void => {\n const value = active.current;\n if (value) value.address.segmentsCompared += 1;\n },\n },\n impact: {\n affects: (): void => {\n const value = active.current;\n if (value) value.impact.affectsChecks += 1;\n },\n },\n reader: {\n session: (): void => {\n const value = active.current;\n if (value) value.reader.sessions += 1;\n },\n lookup: (): void => {\n const value = active.current;\n if (value) value.reader.nodeLookups += 1;\n },\n collectionIds: (amount = 1): void => {\n const value = active.current;\n if (value) value.reader.collectionIds += amount;\n },\n structuralSnapshot: (): void => {\n const value = active.current;\n if (value) value.reader.structuralSnapshots += 1;\n },\n },\n collectionView: {\n mapped: (): void => {\n const value = active.current;\n if (value) value.collectionView.mappedItems += 1;\n },\n idsScanned: (amount = 1): void => {\n const value = active.current;\n if (value) value.collectionView.idsScanned += amount;\n },\n arrayCopied: (): void => {\n const value = active.current;\n if (value) value.collectionView.arraysCopied += 1;\n },\n },\n materialized: {\n updated: (): void => {\n const value = active.current;\n if (value) value.materialized.updated += 1;\n },\n skipped: (): void => {\n const value = active.current;\n if (value) value.materialized.skipped += 1;\n },\n rebuilt: (): void => {\n const value = active.current;\n if (value) value.materialized.rebuilt += 1;\n },\n sourceChanged: (): void => {\n const value = active.current;\n if (value) value.materialized.sourceChanges += 1;\n },\n notification: (): void => {\n const value = active.current;\n if (value) value.materialized.notifications += 1;\n },\n },\n} as const;\n\nexport type ProfileSession = {\n readonly snapshot: () => ProfileSnapshot;\n readonly stop: () => ProfileSnapshot;\n};\n\nexport const startProfile = (): ProfileSession => {\n if (active.current) throw new Error('A document profile session is already active.');\n const value = counters();\n active.current = value;\n let stopped = false;\n const snapshot = (): ProfileSnapshot => freezeSnapshot(value);\n return {\n snapshot,\n stop: (): ProfileSnapshot => {\n if (!stopped) {\n stopped = true;\n active.current = undefined;\n }\n return snapshot();\n },\n };\n};\n\nexport const measureProfile = <T>(\n run: () => T\n): { readonly value: T; readonly profile: ProfileSnapshot } => {\n const session = startProfile();\n try {\n const value = run();\n return { value, profile: session.stop() };\n } catch (error) {\n session.stop();\n throw error;\n }\n};\n","import { profile } from '../profile';\n\nexport type CloneReason =\n 'initial' | 'canonical' | 'commit' | 'inverse' | 'reader' | 'replace' | 'journal' | 'snapshot';\n\nconst stablePayloads = new WeakSet<object>();\n\nconst markStablePayload = <T>(value: T): T => {\n if (Array.isArray(value) || isPlainObject(value)) stablePayloads.add(value as object);\n return value;\n};\n\nexport const isStablePayload = (value: unknown): boolean =>\n (Array.isArray(value) || isPlainObject(value)) && stablePayloads.has(value as object);\n\nexport const isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (value === null || typeof value !== 'object') return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n};\n\nconst countCloneReason = (reason: CloneReason | undefined): void => {\n if (reason) profile.clone.node(reason);\n};\n\nexport const cloneValue = <T>(value: T, reason?: CloneReason): T => {\n profile.clone.call();\n countCloneReason(reason);\n if (Array.isArray(value)) {\n profile.clone.container();\n const result = new Array(value.length);\n for (let index = 0; index < value.length; index += 1)\n result[index] = cloneValue(value[index], reason);\n return (\n reason === 'commit' || reason === 'inverse' || reason === 'snapshot'\n ? markStablePayload(Object.freeze(result))\n : result\n ) as T;\n }\n if (isPlainObject(value)) {\n profile.clone.container();\n const result: Record<string, unknown> = Object.create(Object.getPrototypeOf(value)) as Record<\n string,\n unknown\n >;\n for (const key in value) {\n if (Object.prototype.hasOwnProperty.call(value, key))\n result[key] = cloneValue(value[key], reason);\n }\n return (\n reason === 'commit' || reason === 'inverse' || reason === 'snapshot'\n ? markStablePayload(Object.freeze(result))\n : result\n ) as T;\n }\n return value;\n};\n\n// Structural document values cross an ownership boundary by cloning. Atomic\n// values are shared because their schema contract treats them as immutable.\nexport const ownPayload = <T>(value: T, reason: CloneReason = 'canonical'): T =>\n Array.isArray(value) || isPlainObject(value) ? cloneValue(value, reason) : value;\n\n// The caller transfers structural ownership to the mutable canonical document.\n// Public commit/history boundaries use snapshotPayload instead.\nexport const transferPayload = <T>(value: T): T => {\n profile.batch.payloadTransferred();\n return value;\n};\nexport const snapshotPayload = <T>(value: T, reason: CloneReason = 'commit'): T => (\n profile.batch.payloadSnapshot(),\n ownPayload(value, reason)\n);\n\nexport const deepEqual = (left: unknown, right: unknown): boolean => {\n profile.clone.deepEqual();\n if (Object.is(left, right)) return true;\n if (Array.isArray(left) && Array.isArray(right)) {\n profile.clone.deepEqualContainer();\n if (left.length !== right.length) return false;\n for (let index = 0; index < left.length; index += 1)\n if (!deepEqual(left[index], right[index])) return false;\n return true;\n }\n if (isPlainObject(left) && isPlainObject(right)) {\n profile.clone.deepEqualContainer();\n const leftKeys = Object.keys(left);\n if (leftKeys.length !== Object.keys(right).length) return false;\n for (const key of leftKeys) {\n if (!Object.prototype.hasOwnProperty.call(right, key) || !deepEqual(left[key], right[key]))\n return false;\n }\n return true;\n }\n return false;\n};\n\nexport const sameStructuralValue = (left: unknown, right: unknown): boolean =>\n Object.is(left, right) ||\n ((Array.isArray(left) || isPlainObject(left)) && deepEqual(left, right));\n\nexport const isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n"],"mappings":"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"}
|
package/dist/react.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.cjs","names":["target","track"],"sources":["../react/src/hooks.ts"],"sourcesContent":["import type {\n
|
|
1
|
+
{"version":3,"file":"react.cjs","names":["target","track"],"sources":["../react/src/hooks.ts"],"sourcesContent":["import type {\n DocumentReadable,\n DocumentSchema,\n DocumentSelector,\n HistoryState,\n ImpactTarget,\n LocalHistory,\n OperationResult,\n Readable,\n} from 'doxum';\nimport { target } from 'doxum';\nimport { track } from 'doxum/integration';\nimport { useCallback, useMemo, useRef, useSyncExternalStore } from 'react';\n\nexport type DocumentSelectorOptions<TResult> = {\n readonly isEqual?: (previous: TResult, next: TResult) => boolean;\n readonly server?: () => TResult;\n};\n\ntype SelectorCache<TSchema extends DocumentSchema, TResult> = {\n readonly runtime: DocumentReadable<TSchema>;\n readonly value: TResult;\n readonly targets: readonly ImpactTarget<unknown>[];\n};\n\nconst objectIs = <T>(previous: T, next: T): boolean => Object.is(previous, next);\nconst sameTargets = (\n left: readonly ImpactTarget<unknown>[],\n right: readonly ImpactTarget<unknown>[]\n): boolean => {\n if (left.length !== right.length) return false;\n for (let index = 0; index < left.length; index += 1)\n if (!target.same(left[index], right[index])) return false;\n return true;\n};\n\nexport function useDocumentSelector<TSchema extends DocumentSchema, TResult>(\n runtime: DocumentReadable<TSchema>,\n selector: DocumentSelector<TSchema, TResult>,\n options?: DocumentSelectorOptions<TResult>\n): TResult {\n const equality = options?.isEqual ?? objectIs;\n const cache = useRef<SelectorCache<TSchema, TResult> | undefined>(undefined);\n const serverCache = useRef<\n { readonly source: (() => TResult) | undefined; readonly value: TResult } | undefined\n >(undefined);\n\n const read = useCallback((): TResult => {\n const selection = track(runtime, selector);\n const next = selection.value;\n const previous = cache.current;\n\n // Keep the prior reference for semantic equality on the same runtime. This\n // is what makes inline selectors safe with useSyncExternalStore.\n const targets = selection.targets;\n if (previous && previous.runtime === runtime && equality(previous.value, next)) {\n cache.current = { runtime, value: previous.value, targets };\n return previous.value;\n }\n\n cache.current = { runtime, value: next, targets };\n return next;\n }, [equality, runtime, selector]);\n\n const subscribe = useCallback(\n (listener: () => void) => {\n let targets = cache.current?.targets ?? [];\n let unsubscribe: () => void = () => undefined;\n const install = () => {\n if (targets.length === 0) return () => undefined;\n return runtime.subscribe(\n targets.length === 1\n ? targets[0]\n : (targets as [ImpactTarget<unknown>, ...ImpactTarget<unknown>[]]),\n onCommit\n );\n };\n const onCommit = () => {\n const previous = cache.current;\n const next = read();\n const nextTargets = cache.current?.targets ?? [];\n if (!sameTargets(targets, nextTargets)) {\n unsubscribe();\n targets = nextTargets;\n unsubscribe = install();\n }\n if (previous && previous.value !== next) listener();\n };\n unsubscribe = install();\n return () => unsubscribe();\n },\n [read, runtime]\n );\n\n const server = options?.server;\n const readServer = useCallback((): TResult => {\n const previous = serverCache.current;\n if (previous && previous.source === server) return previous.value;\n const value = server ? server() : read();\n serverCache.current = { source: server, value };\n return value;\n }, [read, server]);\n\n return useSyncExternalStore(subscribe, read, readServer);\n}\n\nexport function useReadable<T>(readable: Readable<T>): T {\n const subscribe = useCallback((listener: () => void) => readable.subscribe(listener), [readable]);\n const read = useCallback(() => readable.current(), [readable]);\n return useSyncExternalStore(subscribe, read, read);\n}\n\nexport function useHistory<TCommit>(history: LocalHistory<TCommit>): HistoryState & {\n undo(): OperationResult<TCommit>;\n redo(): OperationResult<TCommit>;\n} {\n const subscribe = useCallback((listener: () => void) => history.subscribe(listener), [history]);\n const read = useCallback(() => history.current(), [history]);\n const state = useSyncExternalStore(subscribe, read, read);\n const undo = useCallback(() => history.undo(), [history]);\n const redo = useCallback(() => history.redo(), [history]);\n\n return useMemo(() => ({ ...state, undo, redo }), [redo, state, undo]);\n}\n"],"mappings":"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"}
|
package/dist/react.d.cts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DocumentReadable, DocumentSchema, DocumentSelector, HistoryState, LocalHistory, OperationResult, Readable } from "doxum";
|
|
2
2
|
|
|
3
3
|
//#region react/src/hooks.d.ts
|
|
4
4
|
type DocumentSelectorOptions<TResult> = {
|
|
5
5
|
readonly isEqual?: (previous: TResult, next: TResult) => boolean;
|
|
6
6
|
readonly server?: () => TResult;
|
|
7
7
|
};
|
|
8
|
-
declare function useDocumentSelector<TSchema extends DocumentSchema, TResult>(runtime:
|
|
8
|
+
declare function useDocumentSelector<TSchema extends DocumentSchema, TResult>(runtime: DocumentReadable<TSchema>, selector: DocumentSelector<TSchema, TResult>, options?: DocumentSelectorOptions<TResult>): TResult;
|
|
9
9
|
declare function useReadable<T>(readable: Readable<T>): T;
|
|
10
10
|
declare function useHistory<TCommit>(history: LocalHistory<TCommit>): HistoryState & {
|
|
11
11
|
undo(): OperationResult<TCommit>;
|
package/dist/react.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DocumentReadable, DocumentSchema, DocumentSelector, HistoryState, LocalHistory, OperationResult, Readable } from "doxum";
|
|
2
2
|
|
|
3
3
|
//#region react/src/hooks.d.ts
|
|
4
4
|
type DocumentSelectorOptions<TResult> = {
|
|
5
5
|
readonly isEqual?: (previous: TResult, next: TResult) => boolean;
|
|
6
6
|
readonly server?: () => TResult;
|
|
7
7
|
};
|
|
8
|
-
declare function useDocumentSelector<TSchema extends DocumentSchema, TResult>(runtime:
|
|
8
|
+
declare function useDocumentSelector<TSchema extends DocumentSchema, TResult>(runtime: DocumentReadable<TSchema>, selector: DocumentSelector<TSchema, TResult>, options?: DocumentSelectorOptions<TResult>): TResult;
|
|
9
9
|
declare function useReadable<T>(readable: Readable<T>): T;
|
|
10
10
|
declare function useHistory<TCommit>(history: LocalHistory<TCommit>): HistoryState & {
|
|
11
11
|
undo(): OperationResult<TCommit>;
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.js","names":[],"sources":["../react/src/hooks.ts"],"sourcesContent":["import type {\n
|
|
1
|
+
{"version":3,"file":"react.js","names":[],"sources":["../react/src/hooks.ts"],"sourcesContent":["import type {\n DocumentReadable,\n DocumentSchema,\n DocumentSelector,\n HistoryState,\n ImpactTarget,\n LocalHistory,\n OperationResult,\n Readable,\n} from 'doxum';\nimport { target } from 'doxum';\nimport { track } from 'doxum/integration';\nimport { useCallback, useMemo, useRef, useSyncExternalStore } from 'react';\n\nexport type DocumentSelectorOptions<TResult> = {\n readonly isEqual?: (previous: TResult, next: TResult) => boolean;\n readonly server?: () => TResult;\n};\n\ntype SelectorCache<TSchema extends DocumentSchema, TResult> = {\n readonly runtime: DocumentReadable<TSchema>;\n readonly value: TResult;\n readonly targets: readonly ImpactTarget<unknown>[];\n};\n\nconst objectIs = <T>(previous: T, next: T): boolean => Object.is(previous, next);\nconst sameTargets = (\n left: readonly ImpactTarget<unknown>[],\n right: readonly ImpactTarget<unknown>[]\n): boolean => {\n if (left.length !== right.length) return false;\n for (let index = 0; index < left.length; index += 1)\n if (!target.same(left[index], right[index])) return false;\n return true;\n};\n\nexport function useDocumentSelector<TSchema extends DocumentSchema, TResult>(\n runtime: DocumentReadable<TSchema>,\n selector: DocumentSelector<TSchema, TResult>,\n options?: DocumentSelectorOptions<TResult>\n): TResult {\n const equality = options?.isEqual ?? objectIs;\n const cache = useRef<SelectorCache<TSchema, TResult> | undefined>(undefined);\n const serverCache = useRef<\n { readonly source: (() => TResult) | undefined; readonly value: TResult } | undefined\n >(undefined);\n\n const read = useCallback((): TResult => {\n const selection = track(runtime, selector);\n const next = selection.value;\n const previous = cache.current;\n\n // Keep the prior reference for semantic equality on the same runtime. This\n // is what makes inline selectors safe with useSyncExternalStore.\n const targets = selection.targets;\n if (previous && previous.runtime === runtime && equality(previous.value, next)) {\n cache.current = { runtime, value: previous.value, targets };\n return previous.value;\n }\n\n cache.current = { runtime, value: next, targets };\n return next;\n }, [equality, runtime, selector]);\n\n const subscribe = useCallback(\n (listener: () => void) => {\n let targets = cache.current?.targets ?? [];\n let unsubscribe: () => void = () => undefined;\n const install = () => {\n if (targets.length === 0) return () => undefined;\n return runtime.subscribe(\n targets.length === 1\n ? targets[0]\n : (targets as [ImpactTarget<unknown>, ...ImpactTarget<unknown>[]]),\n onCommit\n );\n };\n const onCommit = () => {\n const previous = cache.current;\n const next = read();\n const nextTargets = cache.current?.targets ?? [];\n if (!sameTargets(targets, nextTargets)) {\n unsubscribe();\n targets = nextTargets;\n unsubscribe = install();\n }\n if (previous && previous.value !== next) listener();\n };\n unsubscribe = install();\n return () => unsubscribe();\n },\n [read, runtime]\n );\n\n const server = options?.server;\n const readServer = useCallback((): TResult => {\n const previous = serverCache.current;\n if (previous && previous.source === server) return previous.value;\n const value = server ? server() : read();\n serverCache.current = { source: server, value };\n return value;\n }, [read, server]);\n\n return useSyncExternalStore(subscribe, read, readServer);\n}\n\nexport function useReadable<T>(readable: Readable<T>): T {\n const subscribe = useCallback((listener: () => void) => readable.subscribe(listener), [readable]);\n const read = useCallback(() => readable.current(), [readable]);\n return useSyncExternalStore(subscribe, read, read);\n}\n\nexport function useHistory<TCommit>(history: LocalHistory<TCommit>): HistoryState & {\n undo(): OperationResult<TCommit>;\n redo(): OperationResult<TCommit>;\n} {\n const subscribe = useCallback((listener: () => void) => history.subscribe(listener), [history]);\n const read = useCallback(() => history.current(), [history]);\n const state = useSyncExternalStore(subscribe, read, read);\n const undo = useCallback(() => history.undo(), [history]);\n const redo = useCallback(() => history.redo(), [history]);\n\n return useMemo(() => ({ ...state, undo, redo }), [redo, state, undo]);\n}\n"],"mappings":";;;;AAyBA,MAAM,YAAe,UAAa,SAAqB,OAAO,GAAG,UAAU,KAAK;AAChF,MAAM,eACJ,MACA,UACY;AACZ,KAAI,KAAK,WAAW,MAAM,OAAQ,QAAO;AACzC,MAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS,EAChD,KAAI,CAAC,OAAO,KAAK,KAAK,QAAQ,MAAM,OAAO,CAAE,QAAO;AACtD,QAAO;;AAGT,SAAgB,oBACd,SACA,UACA,SACS;CACT,MAAM,WAAW,SAAS,WAAW;CACrC,MAAM,QAAQ,OAAoD,KAAA,EAAU;CAC5E,MAAM,cAAc,OAElB,KAAA,EAAU;CAEZ,MAAM,OAAO,kBAA2B;EACtC,MAAM,YAAY,MAAM,SAAS,SAAS;EAC1C,MAAM,OAAO,UAAU;EACvB,MAAM,WAAW,MAAM;EAIvB,MAAM,UAAU,UAAU;AAC1B,MAAI,YAAY,SAAS,YAAY,WAAW,SAAS,SAAS,OAAO,KAAK,EAAE;AAC9E,SAAM,UAAU;IAAE;IAAS,OAAO,SAAS;IAAO;IAAS;AAC3D,UAAO,SAAS;;AAGlB,QAAM,UAAU;GAAE;GAAS,OAAO;GAAM;GAAS;AACjD,SAAO;IACN;EAAC;EAAU;EAAS;EAAS,CAAC;CAEjC,MAAM,YAAY,aACf,aAAyB;EACxB,IAAI,UAAU,MAAM,SAAS,WAAW,EAAE;EAC1C,IAAI,oBAAgC,KAAA;EACpC,MAAM,gBAAgB;AACpB,OAAI,QAAQ,WAAW,EAAG,cAAa,KAAA;AACvC,UAAO,QAAQ,UACb,QAAQ,WAAW,IACf,QAAQ,KACP,SACL,SACD;;EAEH,MAAM,iBAAiB;GACrB,MAAM,WAAW,MAAM;GACvB,MAAM,OAAO,MAAM;GACnB,MAAM,cAAc,MAAM,SAAS,WAAW,EAAE;AAChD,OAAI,CAAC,YAAY,SAAS,YAAY,EAAE;AACtC,iBAAa;AACb,cAAU;AACV,kBAAc,SAAS;;AAEzB,OAAI,YAAY,SAAS,UAAU,KAAM,WAAU;;AAErD,gBAAc,SAAS;AACvB,eAAa,aAAa;IAE5B,CAAC,MAAM,QAAQ,CAChB;CAED,MAAM,SAAS,SAAS;AASxB,QAAO,qBAAqB,WAAW,MARpB,kBAA2B;EAC5C,MAAM,WAAW,YAAY;AAC7B,MAAI,YAAY,SAAS,WAAW,OAAQ,QAAO,SAAS;EAC5D,MAAM,QAAQ,SAAS,QAAQ,GAAG,MAAM;AACxC,cAAY,UAAU;GAAE,QAAQ;GAAQ;GAAO;AAC/C,SAAO;IACN,CAAC,MAAM,OAAO,CAEsC,CAAC;;AAG1D,SAAgB,YAAe,UAA0B;CACvD,MAAM,YAAY,aAAa,aAAyB,SAAS,UAAU,SAAS,EAAE,CAAC,SAAS,CAAC;CACjG,MAAM,OAAO,kBAAkB,SAAS,SAAS,EAAE,CAAC,SAAS,CAAC;AAC9D,QAAO,qBAAqB,WAAW,MAAM,KAAK;;AAGpD,SAAgB,WAAoB,SAGlC;CACA,MAAM,YAAY,aAAa,aAAyB,QAAQ,UAAU,SAAS,EAAE,CAAC,QAAQ,CAAC;CAC/F,MAAM,OAAO,kBAAkB,QAAQ,SAAS,EAAE,CAAC,QAAQ,CAAC;CAC5D,MAAM,QAAQ,qBAAqB,WAAW,MAAM,KAAK;CACzD,MAAM,OAAO,kBAAkB,QAAQ,MAAM,EAAE,CAAC,QAAQ,CAAC;CACzD,MAAM,OAAO,kBAAkB,QAAQ,MAAM,EAAE,CAAC,QAAQ,CAAC;AAEzD,QAAO,eAAe;EAAE,GAAG;EAAO;EAAM;EAAM,GAAG;EAAC;EAAM;EAAO;EAAK,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "doxum",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Doxum is a typed runtime for complex mutable documents.",
|
|
@@ -36,6 +36,11 @@
|
|
|
36
36
|
"import": "./dist/integration.js",
|
|
37
37
|
"require": "./dist/integration.cjs"
|
|
38
38
|
},
|
|
39
|
+
"./local-sync": {
|
|
40
|
+
"types": "./dist/local-sync.d.ts",
|
|
41
|
+
"import": "./dist/local-sync.js",
|
|
42
|
+
"require": "./dist/local-sync.cjs"
|
|
43
|
+
},
|
|
39
44
|
"./react": {
|
|
40
45
|
"types": "./dist/react.d.ts",
|
|
41
46
|
"import": "./dist/react.js",
|
|
@@ -57,20 +62,21 @@
|
|
|
57
62
|
"sideEffects": false,
|
|
58
63
|
"devDependencies": {
|
|
59
64
|
"@eslint/js": "^9.35.0",
|
|
65
|
+
"@types/react": "^19.2.5",
|
|
66
|
+
"@types/react-dom": "^19.2.3",
|
|
67
|
+
"@types/react-test-renderer": "^19.1.0",
|
|
60
68
|
"eslint": "^9.35.0",
|
|
69
|
+
"fake-indexeddb": "^6.2.5",
|
|
61
70
|
"prettier": "^3.6.2",
|
|
71
|
+
"react": "19.2.4",
|
|
72
|
+
"react-dom": "19.2.4",
|
|
73
|
+
"react-test-renderer": "19.2.4",
|
|
62
74
|
"rimraf": "^6.1.3",
|
|
63
75
|
"tsdown": "^0.21.1",
|
|
64
76
|
"tsx": "^4.21.0",
|
|
65
77
|
"typescript": "^5.9.3",
|
|
66
78
|
"typescript-eslint": "^8.43.0",
|
|
67
|
-
"vitest": "^4.0.16"
|
|
68
|
-
"@types/react": "^19.2.5",
|
|
69
|
-
"@types/react-dom": "^19.2.3",
|
|
70
|
-
"@types/react-test-renderer": "^19.1.0",
|
|
71
|
-
"react": "19.2.4",
|
|
72
|
-
"react-dom": "19.2.4",
|
|
73
|
-
"react-test-renderer": "19.2.4"
|
|
79
|
+
"vitest": "^4.0.16"
|
|
74
80
|
},
|
|
75
81
|
"scripts": {
|
|
76
82
|
"build": "tsdown --config tsdown.config.ts",
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
# Doxum Runtime Guide
|
|
2
2
|
|
|
3
3
|
This is the task-oriented public guide for Doxum. It describes how to model,
|
|
4
|
-
read, mutate, observe, and project one in-memory document with
|
|
5
|
-
`doxum`, and
|
|
4
|
+
read, mutate, observe, and project one in-memory document with `doxum`, persist
|
|
5
|
+
one browser-origin document with `doxum/local-sync`, and bind read models with
|
|
6
|
+
`doxum/react`.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
The `doxum` core entry owns typed document state, atomic mutation, history,
|
|
9
|
+
impact, subscriptions, and derived views. `doxum/local-sync` is the optional
|
|
10
|
+
browser adapter for IndexedDB-backed offline editing and same-origin cross-tab
|
|
11
|
+
sync. Your application still owns network ordering, authorization, and conflict
|
|
12
|
+
resolution.
|
|
10
13
|
|
|
11
14
|
## Choose the right entry point
|
|
12
15
|
|
|
@@ -14,6 +17,7 @@ persistence, network ordering, authorization, and conflict resolution.
|
|
|
14
17
|
| ------------------------------------- | -------------------------------------------------------- |
|
|
15
18
|
| Define document shape | `schema`, `field`, `object`, and collection constructors |
|
|
16
19
|
| Create the canonical runtime | `createDocument` |
|
|
20
|
+
| Persist and sync one browser document | `attachLocalSync` from `doxum/local-sync` |
|
|
17
21
|
| Read once | `select(runtime, read => ...)` |
|
|
18
22
|
| Make local business changes | `runtime.update(tx => ...)` |
|
|
19
23
|
| Replay persisted or remote operations | `runtime.apply(operations, options)` |
|
|
@@ -202,6 +206,57 @@ the inverse or forward operation batch through the same mutation pipeline.
|
|
|
202
206
|
or listeners after canonical state and history settled. They are not mutation
|
|
203
207
|
failures and must not cause the caller to repeat the write.
|
|
204
208
|
|
|
209
|
+
## Attach local browser sync
|
|
210
|
+
|
|
211
|
+
`attachLocalSync` is an optional browser attachment. Create and keep the
|
|
212
|
+
runtime yourself, then await attachment before allowing the document to be used.
|
|
213
|
+
It hydrates that runtime from an IndexedDB checkpoint and append-only command
|
|
214
|
+
tail, then uses a Web Lock to choose exactly one writable tab. The `leader`
|
|
215
|
+
uses normal synchronous runtime writes; every other attached tab is a
|
|
216
|
+
`follower` read-only mirror. A direct follower write through `update`,
|
|
217
|
+
`prepare`, `apply`, or `replace` throws `LocalSyncReadOnlyError`.
|
|
218
|
+
|
|
219
|
+
The leader's local, system, and history commits are observed after they have
|
|
220
|
+
settled and persisted to IndexedDB in order. BroadcastChannel carries only a
|
|
221
|
+
new-head hint. Followers reload the durable tail and apply it as `remote`; this
|
|
222
|
+
keeps their document ordered and invalidates their in-memory history. When the
|
|
223
|
+
leader disposes, a caught-up follower takes the lock and becomes leader.
|
|
224
|
+
|
|
225
|
+
Local-sync persists operation commands, not arbitrary new baselines. While it
|
|
226
|
+
is attached, `runtime.replace()` and an externally supplied
|
|
227
|
+
`runtime.apply(..., { source: 'remote' })` throw
|
|
228
|
+
`LocalSyncUnsupportedOperationError`; internal hydration and tail replay use a
|
|
229
|
+
trusted attachment path instead.
|
|
230
|
+
|
|
231
|
+
```ts
|
|
232
|
+
import { attachLocalSync } from 'doxum/local-sync';
|
|
233
|
+
|
|
234
|
+
const runtime = createDocument({ schema: taskSchema, initial });
|
|
235
|
+
const localSync = await attachLocalSync({
|
|
236
|
+
runtime,
|
|
237
|
+
database: 'my-app',
|
|
238
|
+
documentId: 'project-1',
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
if (localSync.state().status === 'leader') {
|
|
242
|
+
runtime.update(tx => tx.write.title.set('Ship Doxum'));
|
|
243
|
+
runtime.history.undo();
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
await localSync.flush(); // persist observed leader commands or catch up a follower
|
|
247
|
+
await localSync.dispose();
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
This is synchronous visibility with asynchronous persistence, not strict
|
|
251
|
+
durability: a crash, storage failure, or invalid JSON payload can leave a
|
|
252
|
+
visible leader commit unpersisted. Use `localSync.state()` and `onError` to show
|
|
253
|
+
that condition. `flush()` is the explicit persistence/catch-up boundary. The
|
|
254
|
+
attachment does not own or dispose the runtime and it does not expose an undo
|
|
255
|
+
API: use `runtime.history.undo()` and `runtime.history.redo()` while the tab is
|
|
256
|
+
leader. Runtime history is intentionally in-memory only; attachment hydration
|
|
257
|
+
and remote tail replay invalidate it, so it is not transferred across reopening
|
|
258
|
+
or leader handoff.
|
|
259
|
+
|
|
205
260
|
## Subscribe through schema-owned targets
|
|
206
261
|
|
|
207
262
|
Create stable selectors from the schema, then subscribe to them. This is the
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Doxum Runtime 使用指南
|
|
2
2
|
|
|
3
|
-
这是 Doxum 面向任务的公开使用指南。它说明如何借助 `doxum`
|
|
3
|
+
这是 Doxum 面向任务的公开使用指南。它说明如何借助 `doxum` 建模、读取、修改、观察和派生一个内存文档,如何通过 `doxum/local-sync` 持久化并同步同一浏览器 origin 的文档,以及如何通过 `doxum/react` 将读模型接入 React。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`doxum` core 负责类型化文档状态、原子修改、历史记录、影响范围、订阅和派生视图。`doxum/local-sync` 是可选的浏览器适配器,提供 IndexedDB 离线持久化和同一 origin 的跨标签页同步。网络顺序、授权和冲突解决仍由应用负责。
|
|
6
6
|
|
|
7
7
|
## 先选择正确入口
|
|
8
8
|
|
|
@@ -10,6 +10,7 @@ Doxum 有意保持本地化:它负责类型化文档状态、原子修改、
|
|
|
10
10
|
| -------------------------- | ----------------------------------------------------- |
|
|
11
11
|
| 定义文档结构 | `schema`、`field`、`object` 和集合构造器 |
|
|
12
12
|
| 创建 canonical runtime | `createDocument` |
|
|
13
|
+
| 持久化并同步一个浏览器文档 | 从 `doxum/local-sync` 导入 `attachLocalSync` |
|
|
13
14
|
| 一次性读取 | `select(runtime, read => ...)` |
|
|
14
15
|
| 执行本地业务修改 | `runtime.update(tx => ...)` |
|
|
15
16
|
| 回放持久化或远端 operation | `runtime.apply(operations, options)` |
|
|
@@ -166,6 +167,51 @@ if (result.status === 'rejected') {
|
|
|
166
167
|
|
|
167
168
|
committed 结果中的 `observerErrors` 是 canonical state 和 history 已稳定后,processor、flush 或 listener 发生的失败。它们不是 mutation 失败,调用方不能因此重复写入。
|
|
168
169
|
|
|
170
|
+
## 附着浏览器本地同步
|
|
171
|
+
|
|
172
|
+
`attachLocalSync` 是可选的浏览器 attachment。runtime 仍由应用创建并持有;在使用
|
|
173
|
+
文档前必须等待 attach 完成。它会从 IndexedDB 的 checkpoint 与 append-only command
|
|
174
|
+
tail 恢复传入 runtime,随后以 Web Lock 为一个 document 选出唯一可写标签页。`leader`
|
|
175
|
+
可继续使用同步的 runtime 写入 API;其他已附着标签页都是只读的 `follower` mirror。
|
|
176
|
+
follower 直接调用 `update`、`prepare`、`apply` 或 `replace` 会抛出
|
|
177
|
+
`LocalSyncReadOnlyError`。
|
|
178
|
+
|
|
179
|
+
leader 已完成的 local、system 与 history commit 会被监听,并按顺序异步写入
|
|
180
|
+
IndexedDB。BroadcastChannel 只传递新的 head 提示;follower 从 IndexedDB 补读 durable
|
|
181
|
+
tail,并以 `remote` source 顺序 apply,因此其内存 history 会失效。leader dispose
|
|
182
|
+
之后,已经 catch-up 的 follower 会接管锁并成为新的 leader。
|
|
183
|
+
|
|
184
|
+
local-sync 只持久化 operation command,不接受任意的新基线。附着期间,
|
|
185
|
+
`runtime.replace()` 与由应用提供的 `runtime.apply(..., { source: 'remote' })` 会抛出
|
|
186
|
+
`LocalSyncUnsupportedOperationError`;内部 hydration 与 tail replay 使用受信任的
|
|
187
|
+
attachment path。
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
import { attachLocalSync } from 'doxum/local-sync';
|
|
191
|
+
|
|
192
|
+
const runtime = createDocument({ schema: taskSchema, initial });
|
|
193
|
+
const localSync = await attachLocalSync({
|
|
194
|
+
runtime,
|
|
195
|
+
database: 'my-app',
|
|
196
|
+
documentId: 'project-1',
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
if (localSync.state().status === 'leader') {
|
|
200
|
+
runtime.update(tx => tx.write.title.set('Ship Doxum'));
|
|
201
|
+
runtime.history.undo();
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
await localSync.flush(); // 持久化已观察到的 leader command,或让 follower 追赶
|
|
205
|
+
await localSync.dispose();
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
开始使用前必须等待 attachment,因为它会用 IndexedDB 恢复传入 runtime。这是“同步可见、
|
|
209
|
+
异步持久化”而不是严格 durable:崩溃、存储失败或非 JSON payload,都可能让已经可见的
|
|
210
|
+
leader commit 未持久化。用 `localSync.state()` 与 `onError` 显示该状态,`flush()` 是显式
|
|
211
|
+
的持久化/追赶边界。attachment 不拥有也不会 dispose runtime,且不提供另一套 undo API:
|
|
212
|
+
leader 使用 `runtime.history.undo()` 与 `runtime.history.redo()`。history 有意只在内存中
|
|
213
|
+
存在;attachment 恢复及 remote tail apply 都会使它失效,因此不会跨重开或 leader 交接保留。
|
|
214
|
+
|
|
169
215
|
## 通过 schema 所有的 target 订阅
|
|
170
216
|
|
|
171
217
|
从 schema 创建稳定 selector,再订阅 selector。这是整个 runtime 共用的 address 与 impact 模型。
|
|
@@ -6,10 +6,12 @@ not optional style preferences.
|
|
|
6
6
|
|
|
7
7
|
## One canonical write authority
|
|
8
8
|
|
|
9
|
-
`createDocument` owns canonical mutable document state.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
`createDocument` owns canonical mutable document state. Canonical writes must
|
|
10
|
+
pass through `runtime.update`, `runtime.apply`, or `runtime.replace`.
|
|
11
|
+
`runtime.prepare` may use the same mutation session to produce a rolled-back,
|
|
12
|
+
uncommitted operation batch for a durable adapter; it is not a second write
|
|
13
|
+
path. Writers emit operations into a mutation session; they are not a public
|
|
14
|
+
escape hatch to mutate an object.
|
|
13
15
|
|
|
14
16
|
Never add:
|
|
15
17
|
|
|
@@ -128,10 +130,23 @@ views and subscriptions with their owner.
|
|
|
128
130
|
## Framework and product boundaries
|
|
129
131
|
|
|
130
132
|
`core` is framework-neutral. `doxum/react` is a one-way adapter from core to
|
|
131
|
-
React; core must not import React or UI concepts.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
133
|
+
React; core must not import React or UI concepts. `doxum/local-sync` is an
|
|
134
|
+
optional attachment to an application-owned runtime. It hydrates an IndexedDB
|
|
135
|
+
checkpoint/tail, holds a document Web Lock for exactly one leader, and uses a
|
|
136
|
+
small internal synchronous write policy to reject follower mutations without
|
|
137
|
+
changing the runtime API. The leader observes completed local, system, and
|
|
138
|
+
history commits, appends JSON operation batches asynchronously, and broadcasts
|
|
139
|
+
only a head hint. Followers read and apply the durable tail as `remote`; this
|
|
140
|
+
invalidates their history. There is no pending queue, rebase, actor history, or
|
|
141
|
+
attachment-specific undo API. While attached, external `replace` and external
|
|
142
|
+
`apply` marked `remote` are rejected because only operation commands are
|
|
143
|
+
appendable; the attachment's hydration and replay lease is the one trusted
|
|
144
|
+
exception. Local-sync does not promise strict durability;
|
|
145
|
+
application code uses `state()`, `onError`, and `flush()` when it needs to
|
|
146
|
+
observe persistence or catch-up. Doxum intentionally does not decide network
|
|
147
|
+
synchronization, authorization, retry, acknowledgement, ordering, or conflict
|
|
148
|
+
resolution. An application must make those decisions before applying operations
|
|
149
|
+
or replacing a snapshot.
|
|
135
150
|
|
|
136
151
|
## Change checklist
|
|
137
152
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## 唯一的 canonical 写入权威
|
|
6
6
|
|
|
7
|
-
`createDocument` 拥有 canonical mutable document state
|
|
7
|
+
`createDocument` 拥有 canonical mutable document state。canonical write 只能通过 `runtime.update`、`runtime.apply` 或 `runtime.replace`。`runtime.prepare` 可以复用同一 mutation session 产生随后会回滚的未提交 operation batch,供 durable adapter 使用;它不是第二条写入路径。writer 只是向 mutation session 产生 operation,而不是绕过 runtime 修改对象的出口。
|
|
8
8
|
|
|
9
9
|
绝不能新增:
|
|
10
10
|
|
|
@@ -84,7 +84,7 @@ update 与 notification 窗口中禁止写入。processor、flush 和 listener e
|
|
|
84
84
|
|
|
85
85
|
## Framework 与产品边界
|
|
86
86
|
|
|
87
|
-
`core` 必须保持 framework-neutral。`doxum/react` 是从 core 到 React 的单向 adapter;core 不能 import React 或 UI
|
|
87
|
+
`core` 必须保持 framework-neutral。`doxum/react` 是从 core 到 React 的单向 adapter;core 不能 import React 或 UI 概念。`doxum/local-sync` 是附着到应用自有 runtime 的可选浏览器 attachment:它会恢复 IndexedDB checkpoint/tail,以 document Web Lock 选出唯一 leader,并通过一个很小的内部同步写入 policy 拒绝 follower mutation,而不改变 runtime API。leader 监听已完成的 local、system 与 history commit,将 JSON operation batch 异步追加到日志,并且只广播 head 提示。follower 从 durable tail 顺序读取并按 `remote` apply,因此 history 会失效。没有 pending queue、rebase、actor history 或 attachment 专属的 undo API。附着期间,外部 `replace` 与标记为 `remote` 的外部 `apply` 都会被拒绝,因为只有 operation command 能 append;attachment 的 hydration 与 replay lease 是唯一受信任例外。它不会承诺严格 durability;应用在需要观察持久化或追赶时使用 `state()`、`onError` 与 `flush()`。Doxum 有意不决定网络同步、authorization、retry、acknowledgement、ordering 或 conflict resolution。应用必须在 apply operation 或 replace snapshot 前做出这些决策。
|
|
88
88
|
|
|
89
89
|
## 改动检查清单
|
|
90
90
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dependency-BdEMyquf.js","names":["isRecord","schemaRoot","readAddress","impactTarget.same"],"sources":["../core/src/schema.ts","../core/src/profile.ts","../core/src/address.ts","../core/src/impact-target.ts","../core/src/value/ownership.ts","../core/src/access/reader.ts","../core/src/runtime/contract.ts","../core/src/runtime/access.ts","../core/src/access/dependency.ts"],"sourcesContent":["export type DocumentAddress = readonly string[];\n\nexport type DocumentListConfig<TItem> = {\n readonly keyOf: (item: TItem) => string;\n};\nexport type DocumentTreeNode<TValue> = {\n readonly parentId?: string;\n readonly children: readonly string[];\n readonly value?: TValue;\n};\nexport type DocumentTreeValue<TValue> = {\n readonly rootId?: string;\n readonly nodes: Readonly<Record<string, DocumentTreeNode<TValue>>>;\n};\n\ntype BaseNode<K extends string> = { readonly kind: K };\nexport type FieldNode<T, Optional extends boolean = false> = BaseNode<'field'> & {\n readonly __value?: T;\n readonly optional?: Optional;\n};\nexport type OptionalNode<TNode extends DocumentNode> = TNode & {\n readonly optional: true;\n};\nexport interface ObjectShape {\n readonly [key: string]: DocumentNode;\n}\nexport type ObjectNode<TShape extends ObjectShape> = BaseNode<'object'> & {\n readonly shape: TShape;\n};\nexport interface VariantShape {\n readonly [key: string]: ObjectNode<ObjectShape>;\n}\nexport type VariantNode<\n TTag extends string,\n TVariants extends VariantShape,\n> = BaseNode<'variant'> & {\n readonly tag: TTag;\n readonly variants: TVariants;\n};\nexport type SingleNode<TValue extends ObjectNode<ObjectShape> | VariantNode<string, VariantShape>> =\n BaseNode<'single'> & {\n readonly value: TValue;\n };\nexport type TableNode<TValue extends ObjectNode<ObjectShape> | VariantNode<string, VariantShape>> =\n BaseNode<'table'> & {\n readonly value: TValue;\n };\nexport type MapNode<TValue extends ObjectNode<ObjectShape> | VariantNode<string, VariantShape>> =\n BaseNode<'map'> & {\n readonly value: TValue;\n };\nexport type RecordNode<TId extends string, TValue> = BaseNode<'record'> & {\n readonly __id?: TId;\n readonly __value?: TValue;\n};\nexport type DictNode<TKey extends string, TValue> = BaseNode<'dict'> & {\n readonly __key?: TKey;\n readonly __value?: TValue;\n};\nexport type ListNode<TItem> = BaseNode<'list'> & {\n readonly __item?: TItem;\n keyOf(item: TItem): string;\n};\nexport type TreeNode<TValue> = BaseNode<'tree'> & {\n readonly __value?: TValue;\n};\n\nexport type DocumentNode =\n | FieldNode<unknown, boolean>\n | ObjectNode<ObjectShape>\n | VariantNode<string, VariantShape>\n | SingleNode<ObjectNode<ObjectShape> | VariantNode<string, VariantShape>>\n | TableNode<ObjectNode<ObjectShape> | VariantNode<string, VariantShape>>\n | MapNode<ObjectNode<ObjectShape> | VariantNode<string, VariantShape>>\n | RecordNode<string, unknown>\n | DictNode<string, unknown>\n | ListNode<unknown>\n | TreeNode<unknown>;\n\ntype EntityValue<N extends ObjectNode<ObjectShape> | VariantNode<string, VariantShape>> =\n N extends ObjectNode<infer S>\n ? DocumentValueOfShape<S>\n : N extends VariantNode<infer T, infer V>\n ? {\n [K in keyof V & string]: { [P in T]: K } & DocumentValueOfShape<\n V[K] extends ObjectNode<infer S> ? S : never\n >;\n }[keyof V & string]\n : never;\n\nexport type DocumentValueOfNode<N> =\n N extends FieldNode<infer T, infer O>\n ? O extends true\n ? T | undefined\n : T\n : N extends ObjectNode<infer S>\n ? DocumentValueOfShape<S>\n : N extends VariantNode<infer T, infer V>\n ? EntityValue<VariantNode<T, V>>\n : N extends SingleNode<infer V>\n ? EntityValue<V>\n : N extends TableNode<infer V>\n ? {\n readonly ids: readonly string[];\n readonly byId: Readonly<Record<string, EntityValue<V>>>;\n }\n : N extends MapNode<infer V>\n ? Readonly<Record<string, EntityValue<V>>>\n : N extends RecordNode<infer I, infer T>\n ? Readonly<Record<I, T>>\n : N extends DictNode<infer K, infer T>\n ? Readonly<Partial<Record<K, T>>>\n : N extends ListNode<infer I>\n ? readonly I[]\n : N extends TreeNode<infer T>\n ? DocumentTreeValue<T>\n : never;\n\ntype OptionalKeys<S extends ObjectShape> = {\n [K in keyof S]: S[K] extends { readonly optional: true } ? K : never;\n}[keyof S];\ntype RequiredKeys<S extends ObjectShape> = Exclude<keyof S, OptionalKeys<S>>;\nexport type DocumentValueOfShape<S extends ObjectShape> = {\n readonly [K in RequiredKeys<S>]: DocumentValueOfNode<S[K]>;\n} & { readonly [K in OptionalKeys<S>]?: DocumentValueOfNode<S[K]> };\nexport type ReadonlyDocument<S extends DocumentSchema> = DocumentValueOfShape<S['shape']>;\n\nexport type CollectionSelector<TId extends string = string, TEntry = unknown> = {\n readonly kind: 'collection';\n readonly schema: DocumentSchema;\n readonly address: DocumentAddress;\n readonly __id?: TId;\n readonly __entry?: TEntry;\n};\nexport type ValueSelector<TResult = unknown> = {\n readonly kind: 'value';\n readonly schema: DocumentSchema;\n readonly address: DocumentAddress;\n readonly __value?: TResult;\n};\nexport type ImpactTarget<T = unknown> =\n | { readonly kind: 'value'; readonly at: DocumentAddress }\n | ValueSelector<T>\n | {\n readonly kind: 'collection';\n readonly at: DocumentAddress;\n readonly id?: string;\n }\n | CollectionSelector<string, T>;\ntype PathMarker<TValue> = { readonly __value?: TValue };\n\ntype SchemaPathFor<S extends ObjectShape = ObjectShape, TValue = unknown> = {\n readonly [K in keyof S]: PathValue<S[K]>;\n} & {\n readonly item: (id: string) => SchemaPathFor<{}, unknown>;\n} & PathMarker<TValue>;\n\nexport type DocumentSchema<TShape extends ObjectShape = {}> = {\n readonly kind: 'schema';\n readonly shape: TShape;\n collection<TPath extends PathMarker<unknown>>(\n pick: (path: SchemaPath<TShape>) => TPath\n ): CollectionSelector<CollectionId<TPath>, CollectionEntry<TPath>>;\n value<TPath extends PathMarker<unknown>>(\n pick: (path: SchemaPath<TShape>) => TPath\n ): ValueSelector<PathValueResult<TPath>>;\n};\n\nexport type SchemaPath<S extends ObjectShape = {}> = SchemaPathFor<S, DocumentValueOfShape<S>>;\n\ntype VariantKeys<V extends VariantShape> = {\n [K in keyof V & string]: keyof (V[K] extends ObjectNode<infer S> ? S : {});\n}[keyof V & string] &\n string;\ntype VariantFieldPath<V extends VariantShape, K extends string> = {\n [P in keyof V & string]: V[P] extends ObjectNode<infer S>\n ? K extends keyof S\n ? PathValue<S[K]>\n : never\n : never;\n}[keyof V & string];\ntype VariantPath<V extends VariantShape> = {\n readonly [K in VariantKeys<V>]: VariantFieldPath<V, K>;\n} & {\n readonly item: (id: string) => SchemaPathFor<{}, unknown>;\n} & PathMarker<EntityValue<VariantNode<string, V>>>;\ntype PathNodeValue<N extends DocumentNode> = N extends { readonly optional: true }\n ? DocumentValueOfNode<N> | undefined\n : DocumentValueOfNode<N>;\ntype EntityPath<N extends ObjectNode<ObjectShape> | VariantNode<string, VariantShape>> =\n N extends ObjectNode<infer S>\n ? SchemaPathFor<S, PathNodeValue<N>>\n : N extends VariantNode<string, infer V>\n ? VariantPath<V>\n : never;\ntype CollectionPath<N extends ObjectNode<ObjectShape> | VariantNode<string, VariantShape>> = Omit<\n EntityPath<N>,\n 'item'\n> & {\n readonly item: (id: string) => EntityPath<N>;\n readonly __collection?: {\n readonly id: string;\n readonly entry: DocumentValueOfNode<N>;\n };\n};\n\ntype PathValue<N extends DocumentNode> =\n N extends ObjectNode<infer S>\n ? SchemaPathFor<S, PathNodeValue<N>>\n : N extends VariantNode<infer _TTag, infer V>\n ? VariantPath<V>\n : N extends TableNode<infer V> | MapNode<infer V>\n ? CollectionPath<V>\n : N extends SingleNode<infer V>\n ? EntityPath<V>\n : SchemaPathFor<{}, PathNodeValue<N>>;\ntype CollectionInfo<T> = T extends {\n readonly __collection?: {\n readonly id: infer TId;\n readonly entry: infer TEntry;\n };\n}\n ? { readonly id: TId; readonly entry: TEntry }\n : never;\ntype CollectionId<T> =\n CollectionInfo<T> extends { readonly id: infer TId extends string } ? TId : string;\ntype CollectionEntry<T> =\n CollectionInfo<T> extends { readonly entry: infer TEntry } ? TEntry : never;\ntype PathValueResult<T> = T extends PathMarker<infer TValue> ? TValue : unknown;\n\nconst node = <T extends DocumentNode>(value: T): T => Object.freeze(value);\nexport const field = <T>(): FieldNode<T> => node({ kind: 'field' });\nexport const optional = <T extends DocumentNode>(value: T): OptionalNode<T> =>\n node({ ...value, optional: true } as OptionalNode<T>);\nexport const object = <S extends ObjectShape>(shape: S): ObjectNode<S> =>\n node({ kind: 'object', shape });\nexport const variant = <T extends string, V extends VariantShape>(\n tag: T,\n variants: V\n): VariantNode<T, V> => node({ kind: 'variant', tag, variants });\nexport const single = <V extends ObjectNode<ObjectShape> | VariantNode<string, VariantShape>>(\n value: V\n): SingleNode<V> => node({ kind: 'single', value });\nexport const table = <V extends ObjectNode<ObjectShape> | VariantNode<string, VariantShape>>(\n value: V\n): TableNode<V> => node({ kind: 'table', value });\nexport const map = <V extends ObjectNode<ObjectShape> | VariantNode<string, VariantShape>>(\n value: V\n): MapNode<V> => node({ kind: 'map', value });\nexport const record = <TId extends string = string, TValue = unknown>(): RecordNode<TId, TValue> =>\n node({ kind: 'record' });\nexport const dict = <TKey extends string = string, TValue = unknown>(): DictNode<TKey, TValue> =>\n node({ kind: 'dict' });\nexport const list = <TItem>(config: DocumentListConfig<TItem>): ListNode<TItem> =>\n ({ kind: 'list', keyOf: config.keyOf }) as ListNode<TItem>;\nexport const tree = <TValue = unknown>(): TreeNode<TValue> => node({ kind: 'tree' });\n\nconst pathProxy = (address: DocumentAddress): SchemaPath & { readonly address: DocumentAddress } =>\n new Proxy({ address } as SchemaPath & { readonly address: DocumentAddress }, {\n get: (_target, property: string | symbol) => {\n if (property === 'address') return address;\n if (property === 'item') return (id: string) => pathProxy([...address, id]);\n if (typeof property === 'symbol') return undefined;\n return pathProxy([...address, property]);\n },\n });\n\nconst select = <S extends ObjectShape>(\n owner: DocumentSchema<S>,\n kind: 'collection' | 'value',\n pick: (path: SchemaPath<S>) => unknown\n): CollectionSelector | ValueSelector => {\n const value = pick(pathProxy([]) as unknown as SchemaPath<S>);\n const selected = value as { readonly address?: DocumentAddress };\n return Object.freeze({\n kind,\n schema: owner,\n address: Object.freeze([...(selected.address ?? [])]),\n }) as CollectionSelector | ValueSelector;\n};\n\nexport const schema = <S extends ObjectShape>(shape: S): DocumentSchema<S> => {\n const result: DocumentSchema<S> = {\n kind: 'schema',\n shape,\n collection: <TPath extends PathMarker<unknown>>(pick: (path: SchemaPath<S>) => TPath) =>\n select(result, 'collection', pick) as CollectionSelector<\n CollectionId<TPath>,\n CollectionEntry<TPath>\n >,\n value: <TPath extends PathMarker<unknown>>(pick: (path: SchemaPath<S>) => TPath) =>\n select(result, 'value', pick) as ValueSelector<PathValueResult<TPath>>,\n };\n return Object.freeze(result);\n};\n","export type CloneReason =\n 'initial' | 'canonical' | 'commit' | 'inverse' | 'reader' | 'replace' | 'journal';\n\ntype CloneCounters = {\n calls: number;\n containers: number;\n nodes: Record<CloneReason, number>;\n deepEqual: { calls: number; containers: number };\n documents: { initial: number };\n};\ntype ProfileCounters = {\n clone: CloneCounters;\n mutation: { normalized: number; executed: number; inverseCreated: number };\n batch: {\n operations: number;\n entries: number;\n collectionsResolved: number;\n journalRecords: number;\n rejected: number;\n inverseOperations: number;\n payloadTransferred: number;\n payloadSnapshots: number;\n };\n journal: {\n subjects: number;\n comparisons: number;\n absorbed: number;\n orderSnapshots: number;\n orderItems: number;\n };\n address: {\n schemaSteps: number;\n documentSteps: number;\n prefixComparisons: number;\n segmentsCompared: number;\n arraysCopied: number;\n };\n impact: { affectsChecks: number };\n reader: {\n sessions: number;\n nodeLookups: number;\n collectionIds: number;\n structuralSnapshots: number;\n };\n collectionView: {\n mappedItems: number;\n idsScanned: number;\n arraysCopied: number;\n };\n materialized: {\n updated: number;\n skipped: number;\n rebuilt: number;\n sourceChanges: number;\n notifications: number;\n };\n};\n\nexport type ProfileSnapshot = Readonly<{\n clone: Readonly<{\n calls: number;\n containers: number;\n nodes: Readonly<Record<CloneReason, number>>;\n deepEqual: Readonly<{ calls: number; containers: number }>;\n documents: Readonly<{ initial: number }>;\n }>;\n mutation: Readonly<{\n normalized: number;\n executed: number;\n inverseCreated: number;\n }>;\n batch: Readonly<ProfileCounters['batch']>;\n journal: Readonly<ProfileCounters['journal']>;\n address: Readonly<ProfileCounters['address']>;\n impact: Readonly<ProfileCounters['impact']>;\n reader: Readonly<ProfileCounters['reader']>;\n collectionView: Readonly<ProfileCounters['collectionView']>;\n materialized: Readonly<ProfileCounters['materialized']>;\n}>;\n\nconst cloneReasons = (): Record<CloneReason, number> => ({\n initial: 0,\n canonical: 0,\n commit: 0,\n inverse: 0,\n reader: 0,\n replace: 0,\n journal: 0,\n});\n\nconst counters = (): ProfileCounters => ({\n clone: {\n calls: 0,\n containers: 0,\n nodes: cloneReasons(),\n deepEqual: { calls: 0, containers: 0 },\n documents: { initial: 0 },\n },\n mutation: { normalized: 0, executed: 0, inverseCreated: 0 },\n batch: {\n operations: 0,\n entries: 0,\n collectionsResolved: 0,\n journalRecords: 0,\n rejected: 0,\n inverseOperations: 0,\n payloadTransferred: 0,\n payloadSnapshots: 0,\n },\n journal: {\n subjects: 0,\n comparisons: 0,\n absorbed: 0,\n orderSnapshots: 0,\n orderItems: 0,\n },\n address: {\n schemaSteps: 0,\n documentSteps: 0,\n prefixComparisons: 0,\n segmentsCompared: 0,\n arraysCopied: 0,\n },\n impact: { affectsChecks: 0 },\n reader: {\n sessions: 0,\n nodeLookups: 0,\n collectionIds: 0,\n structuralSnapshots: 0,\n },\n collectionView: { mappedItems: 0, idsScanned: 0, arraysCopied: 0 },\n materialized: {\n updated: 0,\n skipped: 0,\n rebuilt: 0,\n sourceChanges: 0,\n notifications: 0,\n },\n});\n\n// Recorder calls are stable no-op-capable functions. Only this module owns the\n// mutable session counter tree; domain code never branches on profile state.\nconst active = { current: undefined as ProfileCounters | undefined };\n\n// Snapshot allocation is intentionally delayed until the caller asks for it.\nconst freezeSnapshot = (value: ProfileCounters): ProfileSnapshot =>\n Object.freeze({\n clone: Object.freeze({\n calls: value.clone.calls,\n containers: value.clone.containers,\n nodes: Object.freeze({ ...value.clone.nodes }),\n deepEqual: Object.freeze({ ...value.clone.deepEqual }),\n documents: Object.freeze({ ...value.clone.documents }),\n }),\n mutation: Object.freeze({ ...value.mutation }),\n batch: Object.freeze({ ...value.batch }),\n journal: Object.freeze({ ...value.journal }),\n address: Object.freeze({ ...value.address }),\n impact: Object.freeze({ ...value.impact }),\n reader: Object.freeze({ ...value.reader }),\n collectionView: Object.freeze({ ...value.collectionView }),\n materialized: Object.freeze({ ...value.materialized }),\n });\n\nexport const profile = {\n clone: {\n call: (): void => {\n const value = active.current;\n if (value) value.clone.calls += 1;\n },\n node: (reason: CloneReason): void => {\n const value = active.current;\n if (!value) return;\n value.clone.nodes[reason] += 1;\n },\n container: (): void => {\n const value = active.current;\n if (value) value.clone.containers += 1;\n },\n deepEqual: (): void => {\n const value = active.current;\n if (value) value.clone.deepEqual.calls += 1;\n },\n deepEqualContainer: (): void => {\n const value = active.current;\n if (value) value.clone.deepEqual.containers += 1;\n },\n initialDocument: (): void => {\n const value = active.current;\n if (value) value.clone.documents.initial += 1;\n },\n },\n mutation: {\n normalized: (): void => {\n const value = active.current;\n if (value) value.mutation.normalized += 1;\n },\n executed: (): void => {\n const value = active.current;\n if (value) value.mutation.executed += 1;\n },\n inverse: (): void => {\n const value = active.current;\n if (value) value.mutation.inverseCreated += 1;\n },\n },\n batch: {\n operation: (): void => {\n const value = active.current;\n if (value) value.batch.operations += 1;\n },\n entry: (amount = 1): void => {\n const value = active.current;\n if (value) value.batch.entries += amount;\n },\n collectionResolved: (): void => {\n const value = active.current;\n if (value) value.batch.collectionsResolved += 1;\n },\n journalRecord: (): void => {\n const value = active.current;\n if (value) value.batch.journalRecords += 1;\n },\n rejected: (): void => {\n const value = active.current;\n if (value) value.batch.rejected += 1;\n },\n inverse: (): void => {\n const value = active.current;\n if (value) value.batch.inverseOperations += 1;\n },\n payloadTransferred: (): void => {\n const value = active.current;\n if (value) value.batch.payloadTransferred += 1;\n },\n payloadSnapshot: (): void => {\n const value = active.current;\n if (value) value.batch.payloadSnapshots += 1;\n },\n },\n journal: {\n subject: (): void => {\n const value = active.current;\n if (value) value.journal.subjects += 1;\n },\n comparison: (): void => {\n const value = active.current;\n if (value) value.journal.comparisons += 1;\n },\n absorbed: (): void => {\n const value = active.current;\n if (value) value.journal.absorbed += 1;\n },\n orderSnapshot: (items: number): void => {\n const value = active.current;\n if (!value) return;\n value.journal.orderSnapshots += 1;\n value.journal.orderItems += items;\n },\n },\n address: {\n schemaStep: (): void => {\n const value = active.current;\n if (value) value.address.schemaSteps += 1;\n },\n documentStep: (): void => {\n const value = active.current;\n if (value) value.address.documentSteps += 1;\n },\n arrayCopied: (): void => {\n const value = active.current;\n if (value) value.address.arraysCopied += 1;\n },\n prefixComparison: (): void => {\n const value = active.current;\n if (value) value.address.prefixComparisons += 1;\n },\n segmentCompared: (): void => {\n const value = active.current;\n if (value) value.address.segmentsCompared += 1;\n },\n },\n impact: {\n affects: (): void => {\n const value = active.current;\n if (value) value.impact.affectsChecks += 1;\n },\n },\n reader: {\n session: (): void => {\n const value = active.current;\n if (value) value.reader.sessions += 1;\n },\n lookup: (): void => {\n const value = active.current;\n if (value) value.reader.nodeLookups += 1;\n },\n collectionIds: (amount = 1): void => {\n const value = active.current;\n if (value) value.reader.collectionIds += amount;\n },\n structuralSnapshot: (): void => {\n const value = active.current;\n if (value) value.reader.structuralSnapshots += 1;\n },\n },\n collectionView: {\n mapped: (): void => {\n const value = active.current;\n if (value) value.collectionView.mappedItems += 1;\n },\n idsScanned: (amount = 1): void => {\n const value = active.current;\n if (value) value.collectionView.idsScanned += amount;\n },\n arrayCopied: (): void => {\n const value = active.current;\n if (value) value.collectionView.arraysCopied += 1;\n },\n },\n materialized: {\n updated: (): void => {\n const value = active.current;\n if (value) value.materialized.updated += 1;\n },\n skipped: (): void => {\n const value = active.current;\n if (value) value.materialized.skipped += 1;\n },\n rebuilt: (): void => {\n const value = active.current;\n if (value) value.materialized.rebuilt += 1;\n },\n sourceChanged: (): void => {\n const value = active.current;\n if (value) value.materialized.sourceChanges += 1;\n },\n notification: (): void => {\n const value = active.current;\n if (value) value.materialized.notifications += 1;\n },\n },\n} as const;\n\nexport type ProfileSession = {\n readonly snapshot: () => ProfileSnapshot;\n readonly stop: () => ProfileSnapshot;\n};\n\nexport const startProfile = (): ProfileSession => {\n if (active.current) throw new Error('A document profile session is already active.');\n const value = counters();\n active.current = value;\n let stopped = false;\n const snapshot = (): ProfileSnapshot => freezeSnapshot(value);\n return {\n snapshot,\n stop: (): ProfileSnapshot => {\n if (!stopped) {\n stopped = true;\n active.current = undefined;\n }\n return snapshot();\n },\n };\n};\n\nexport const measureProfile = <T>(\n run: () => T\n): { readonly value: T; readonly profile: ProfileSnapshot } => {\n const session = startProfile();\n try {\n const value = run();\n return { value, profile: session.stop() };\n } catch (error) {\n session.stop();\n throw error;\n }\n};\n","import type { DocumentAddress, DocumentNode, DocumentSchema, ObjectShape } from './schema';\nimport { profile } from './profile';\n\n/** The only resolved address representation used inside the runtime. */\nexport type AddressRef = {\n readonly path: number;\n readonly address: DocumentAddress;\n};\n\ntype RegistryNode = {\n readonly static: Map<string, RegistryNode>;\n dynamic?: RegistryNode;\n path?: number;\n};\n\ntype Registry = {\n readonly root: RegistryNode;\n nextPath: number;\n};\n\nconst registries = new WeakMap<object, Registry>();\nconst registryNode = (): RegistryNode => ({ static: new Map() });\nconst registryFor = (schema: DocumentSchema): Registry => {\n const cached = registries.get(schema as object);\n if (cached) return cached;\n const registry: Registry = { root: registryNode(), nextPath: 0 };\n registries.set(schema as object, registry);\n return registry;\n};\n\nconst hashText = (value: string, seed: number): number => {\n let hash = seed;\n for (let index = 0; index < value.length; index += 1)\n hash = Math.imul(hash ^ value.charCodeAt(index), 16_777_619);\n return hash >>> 0;\n};\n\nconst appendAddressHash = (hash: number, segment: string): number =>\n hashText(segment, hashText('/', hash));\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst unwrap = (node: DocumentNode | undefined): DocumentNode | undefined => {\n let current = node;\n while (current?.kind === 'single') current = current.value;\n return current;\n};\n\nconst variantNode = (\n node: Extract<DocumentNode, { kind: 'variant' }>,\n value: unknown\n): DocumentNode | undefined => {\n const tag = isRecord(value) && typeof value[node.tag] === 'string' ? value[node.tag] : undefined;\n return node.variants[String(tag ?? Object.keys(node.variants)[0] ?? '')];\n};\n\nconst schemaRoot = (schema: DocumentSchema): DocumentNode => ({\n kind: 'object',\n shape: schema.shape,\n});\n\ntype Step = {\n readonly node: DocumentNode | undefined;\n readonly dynamic: boolean;\n};\n\nconst step = (nodeInput: DocumentNode | undefined, value: unknown, segment: string): Step => {\n let node = unwrap(nodeInput);\n if (!node) return { node: undefined, dynamic: false };\n if (node.kind === 'variant') {\n node = unwrap(variantNode(node, value));\n }\n if (!node) return { node: undefined, dynamic: false };\n if (node.kind === 'object') return { node: node.shape[segment], dynamic: false };\n if (node.kind === 'table' || node.kind === 'map') return { node: node.value, dynamic: true };\n // These nodes use operation-specific keys rather than address segments, but\n // accepting a dynamic step keeps address resolution total for user targets.\n if (\n node.kind === 'record' ||\n node.kind === 'dict' ||\n node.kind === 'list' ||\n node.kind === 'tree'\n )\n return { node, dynamic: true };\n return { node: undefined, dynamic: false };\n};\n\nconst pathFor = (\n schema: DocumentSchema,\n address: DocumentAddress,\n document?: unknown\n): number | undefined => {\n const registry = registryFor(schema);\n let trie = registry.root;\n let node: DocumentNode | undefined = schemaRoot(schema);\n let value: unknown = document;\n for (const segment of address) {\n profile.address.schemaStep();\n profile.address.documentStep();\n const resolved = step(node, value, segment);\n if (!resolved.node) return undefined;\n const next = resolved.dynamic\n ? (trie.dynamic ??= registryNode())\n : (() => {\n const existing = trie.static.get(segment);\n if (existing) return existing;\n const created = registryNode();\n trie.static.set(segment, created);\n return created;\n })();\n trie = next;\n node = resolved.node;\n value = readSegment(value, segment);\n }\n if (trie.path === undefined) trie.path = registry.nextPath++;\n return trie.path;\n};\n\nexport const resolveAddress = (\n schema: DocumentSchema,\n address: DocumentAddress,\n document?: unknown\n): AddressRef | undefined => {\n if (!Array.isArray(address)) return undefined;\n for (const segment of address) if (typeof segment !== 'string') return undefined;\n profile.address.arrayCopied();\n const owned = Object.freeze(address.slice()) as DocumentAddress;\n const path = pathFor(schema, owned, document);\n return path === undefined ? undefined : { path, address: owned };\n};\n\nexport const nodeAt = (\n schema: DocumentSchema,\n address: DocumentAddress,\n document?: unknown\n): DocumentNode | undefined => {\n let node: DocumentNode | undefined = schemaRoot(schema);\n let value = document;\n for (const segment of address) {\n const resolved = step(node, value, segment);\n node = resolved.node;\n value = readSegment(value, segment);\n if (!node) return undefined;\n }\n return unwrap(node);\n};\n\nexport const readSegment = (value: unknown, segment: string): unknown => {\n if (!isRecord(value) && !Array.isArray(value)) return undefined;\n if (isRecord(value) && 'byId' in value && isRecord(value.byId)) {\n const entity = value.byId[segment];\n if (entity !== undefined || Object.prototype.hasOwnProperty.call(value.byId, segment))\n return entity;\n }\n return (value as Record<string, unknown>)[segment];\n};\n\nexport const read = (root: unknown, address: DocumentAddress): unknown => {\n let value = root;\n for (const segment of address) {\n value = readSegment(value, segment);\n if (value === undefined) return undefined;\n }\n return value;\n};\n\nexport type Located = {\n readonly parent: Record<string, unknown> | unknown[];\n readonly key: string | number;\n readonly value: unknown;\n};\n\ntype ResolvedCollection = {\n readonly address: DocumentAddress;\n readonly addressHash: number;\n readonly id: string;\n readonly parent?: ResolvedCollection;\n};\n\nexport type ResolvedAddress = Located & {\n readonly addressHash: number;\n readonly node: DocumentNode;\n readonly collection?: ResolvedCollection;\n};\n\n/** Resolves schema and document location in one address traversal. */\nexport const resolveLocated = (\n schema: DocumentSchema,\n root: unknown,\n address: DocumentAddress\n): ResolvedAddress | undefined => {\n if (address.length === 0) return undefined;\n let node: DocumentNode | undefined = schemaRoot(schema);\n let current: unknown = root;\n let collection: ResolvedCollection | undefined;\n let addressHash = 2_166_136_261;\n for (let index = 0; index < address.length - 1; index += 1) {\n profile.address.schemaStep();\n profile.address.documentStep();\n const resolved = step(node, current, address[index]);\n if (!resolved.node) return undefined;\n if (node?.kind === 'table' || node?.kind === 'map')\n collection = {\n address: address.slice(0, index),\n addressHash,\n id: address[index],\n ...(collection ? { parent: collection } : {}),\n };\n addressHash = appendAddressHash(addressHash, address[index]);\n node = resolved.node;\n current = readSegment(current, address[index]);\n if (!node) return undefined;\n }\n profile.address.schemaStep();\n profile.address.documentStep();\n const last = address[address.length - 1];\n const resolved = step(node, current, last);\n if (!resolved.node || (!isRecord(current) && !Array.isArray(current))) return undefined;\n if (node?.kind === 'table' || node?.kind === 'map')\n collection = {\n address: address.slice(0, -1),\n addressHash,\n id: last,\n ...(collection ? { parent: collection } : {}),\n };\n addressHash = appendAddressHash(addressHash, last);\n if (isRecord(current) && 'byId' in current && isRecord(current.byId) && last in current.byId)\n return {\n addressHash,\n node: resolved.node,\n parent: current.byId,\n key: last,\n value: current.byId[last],\n ...(collection ? { collection } : {}),\n };\n return {\n addressHash,\n node: resolved.node,\n parent: current,\n key: Array.isArray(current) && /^\\d+$/.test(last) ? Number(last) : last,\n value: readSegment(current, last),\n ...(collection ? { collection } : {}),\n };\n};\n\nexport const locate = (root: unknown, address: DocumentAddress): Located | undefined => {\n if (address.length === 0) return undefined;\n let current: unknown = root;\n for (let index = 0; index < address.length - 1; index += 1)\n current = readSegment(current, address[index]);\n if (!isRecord(current) && !Array.isArray(current)) return undefined;\n const last = address[address.length - 1];\n if (isRecord(current) && 'byId' in current && isRecord(current.byId) && last in current.byId)\n return { parent: current.byId, key: last, value: current.byId[last] };\n return {\n parent: current,\n key: Array.isArray(current) && /^\\d+$/.test(last) ? Number(last) : last,\n value: readSegment(current, last),\n };\n};\n\nexport const set = (root: unknown, address: DocumentAddress, value: unknown): boolean => {\n const target = locate(root, address);\n if (!target) return false;\n (target.parent as Record<string | number, unknown>)[target.key] = value;\n return true;\n};\n\nexport const remove = (root: unknown, address: DocumentAddress): boolean => {\n const target = locate(root, address);\n if (!target || !Object.prototype.hasOwnProperty.call(target.parent, target.key)) return false;\n if (Array.isArray(target.parent)) target.parent.splice(Number(target.key), 1);\n else delete target.parent[String(target.key)];\n return true;\n};\n\nexport const contains = (parent: DocumentAddress, child: DocumentAddress): boolean => {\n profile.address.prefixComparison();\n if (parent.length > child.length) return false;\n for (let index = 0; index < parent.length; index += 1) {\n profile.address.segmentCompared();\n if (parent[index] !== child[index]) return false;\n }\n return true;\n};\n\nexport const overlaps = (a: DocumentAddress, b: DocumentAddress): boolean =>\n contains(a, b) || contains(b, a);\n\nexport const debugKey = (address: DocumentAddress): string => {\n let result = '';\n for (let index = 0; index < address.length; index += 1) {\n if (index > 0) result += '/';\n result += address[index].replaceAll('~', '~~').replaceAll('/', '~/');\n }\n return result;\n};\n\nexport const same = (a: AddressRef, b: AddressRef): boolean => {\n if (a.path !== b.path || a.address.length !== b.address.length) return false;\n for (let index = 0; index < a.address.length; index += 1) {\n profile.address.segmentCompared();\n if (a.address[index] !== b.address[index]) return false;\n }\n return true;\n};\n\nexport type { DocumentAddress } from './schema';\n","import type { DocumentAddress, DocumentSchema, ImpactTarget } from './schema';\n\nexport const address = (target: ImpactTarget<unknown>): DocumentAddress =>\n 'at' in target ? target.at : target.address;\n\nexport const id = (target: ImpactTarget<unknown>): string | undefined =>\n target.kind === 'collection' && 'id' in target ? target.id : undefined;\n\nexport const belongs = (target: ImpactTarget<unknown>, schema: DocumentSchema): boolean =>\n !('schema' in target) || target.schema === schema;\n\nexport const same = (left: ImpactTarget<unknown>, right: ImpactTarget<unknown>): boolean => {\n if (left.kind !== right.kind) return false;\n if ('schema' in left && 'schema' in right && left.schema !== right.schema) return false;\n const leftAddress = address(left);\n const rightAddress = address(right);\n if (leftAddress.length !== rightAddress.length) return false;\n for (let index = 0; index < leftAddress.length; index += 1)\n if (leftAddress[index] !== rightAddress[index]) return false;\n return left.kind !== 'collection' || id(left) === id(right);\n};\n\nexport const bucket = (target: ImpactTarget<unknown>): string | undefined => address(target)[0];\n","import type { DocumentOperationUnion } from '../operations';\nimport { profile } from '../profile';\n\nexport type CloneReason =\n 'initial' | 'canonical' | 'commit' | 'inverse' | 'reader' | 'replace' | 'journal';\n\nconst stablePayloads = new WeakSet<object>();\n\nconst markStablePayload = <T>(value: T): T => {\n if (Array.isArray(value) || isPlainObject(value)) stablePayloads.add(value as object);\n return value;\n};\n\nexport const isStablePayload = (value: unknown): boolean =>\n (Array.isArray(value) || isPlainObject(value)) && stablePayloads.has(value as object);\n\nexport const isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (value === null || typeof value !== 'object') return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n};\n\nconst countCloneReason = (reason: CloneReason | undefined): void => {\n if (reason) profile.clone.node(reason);\n};\n\nexport const cloneValue = <T>(value: T, reason?: CloneReason): T => {\n profile.clone.call();\n countCloneReason(reason);\n if (Array.isArray(value)) {\n profile.clone.container();\n const result = new Array(value.length);\n for (let index = 0; index < value.length; index += 1)\n result[index] = cloneValue(value[index], reason);\n return (\n reason === 'commit' || reason === 'inverse'\n ? markStablePayload(Object.freeze(result))\n : result\n ) as T;\n }\n if (isPlainObject(value)) {\n profile.clone.container();\n const result: Record<string, unknown> = Object.create(Object.getPrototypeOf(value)) as Record<\n string,\n unknown\n >;\n for (const key in value) {\n if (Object.prototype.hasOwnProperty.call(value, key))\n result[key] = cloneValue(value[key], reason);\n }\n return (\n reason === 'commit' || reason === 'inverse'\n ? markStablePayload(Object.freeze(result))\n : result\n ) as T;\n }\n return value;\n};\n\n// Structural document values cross an ownership boundary by cloning. Atomic\n// values are shared because their schema contract treats them as immutable.\nexport const ownPayload = <T>(value: T, reason: CloneReason = 'canonical'): T =>\n Array.isArray(value) || isPlainObject(value) ? cloneValue(value, reason) : value;\n\n// The caller transfers structural ownership to the mutable canonical document.\n// Public commit/history boundaries use snapshotPayload instead.\nexport const transferPayload = <T>(value: T): T => {\n profile.batch.payloadTransferred();\n return value;\n};\nexport const snapshotPayload = <T>(value: T, reason: CloneReason = 'commit'): T => (\n profile.batch.payloadSnapshot(),\n ownPayload(value, reason)\n);\n\nexport const operationOwnsStructuralPayload = (operation: DocumentOperationUnion): boolean =>\n operation.type === 'variant.replace' ||\n operation.type === 'dict.replace' ||\n operation.type === 'entity.create' ||\n operation.type === 'list.insert' ||\n operation.type === 'list.replace' ||\n operation.type === 'tree.replace';\n\nexport const deepEqual = (left: unknown, right: unknown): boolean => {\n profile.clone.deepEqual();\n if (Object.is(left, right)) return true;\n if (Array.isArray(left) && Array.isArray(right)) {\n profile.clone.deepEqualContainer();\n if (left.length !== right.length) return false;\n for (let index = 0; index < left.length; index += 1)\n if (!deepEqual(left[index], right[index])) return false;\n return true;\n }\n if (isPlainObject(left) && isPlainObject(right)) {\n profile.clone.deepEqualContainer();\n const leftKeys = Object.keys(left);\n if (leftKeys.length !== Object.keys(right).length) return false;\n for (const key of leftKeys) {\n if (!Object.prototype.hasOwnProperty.call(right, key) || !deepEqual(left[key], right[key]))\n return false;\n }\n return true;\n }\n return false;\n};\n\nexport const sameStructuralValue = (left: unknown, right: unknown): boolean =>\n Object.is(left, right) ||\n ((Array.isArray(left) || isPlainObject(left)) && deepEqual(left, right));\n\nexport const isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n","import { object } from '../schema';\nimport type {\n DictNode,\n DocumentAddress,\n DocumentNode,\n DocumentSchema,\n DocumentValueOfNode,\n ImpactTarget,\n ListNode,\n MapNode,\n ObjectNode,\n ReadonlyDocument,\n SingleNode,\n TableNode,\n TreeNode,\n VariantNode,\n} from '../schema';\nimport { read as readAddress } from '../address';\nimport { cloneValue, isRecord } from '../value/ownership';\nimport { profile } from '../profile';\nimport type { DependencyTracker } from './dependency';\n\nexport type FieldReader<T> = { readonly get: () => T };\nexport type CollectionReader<TId, TEntry> = {\n readonly ids: () => readonly TId[];\n readonly has: (id: TId) => boolean;\n readonly get: (id: TId) => EntityReader<TEntry> | undefined;\n};\nexport type ListReader<T> = {\n readonly values: () => readonly T[];\n readonly length: () => number;\n readonly at: (index: number) => T | undefined;\n};\nexport type TreeReader<T> = {\n readonly rootId: () => string | undefined;\n readonly has: (id: string) => boolean;\n readonly value: (id: string) => T | undefined;\n readonly parent: (id: string) => string | undefined;\n readonly children: (id: string) => readonly string[];\n};\n\nexport type EntityReader<T> = T extends object\n ? { readonly [K in keyof T]: ReaderValue<T[K]> }\n : FieldReader<T>;\nexport type ReaderValue<T> = T extends readonly (infer TItem)[]\n ? ListReader<TItem>\n : T extends object\n ? EntityReader<T>\n : FieldReader<T>;\nexport type ReaderOfNode<TNode extends DocumentNode> = TNode extends {\n kind: 'field';\n}\n ? FieldReader<DocumentValueOfNode<TNode>>\n : TNode extends ObjectNode<infer TShape>\n ? { readonly [K in keyof TShape]: ReaderOfNode<TShape[K]> }\n : TNode extends VariantNode<string, infer TVariants>\n ? { readonly [K in keyof TVariants]: ReaderOfNode<TVariants[K]> }\n : TNode extends SingleNode<infer TValue>\n ? ReaderOfNode<TValue>\n : TNode extends TableNode<infer TValue>\n ? CollectionReader<string, DocumentValueOfNode<TValue>>\n : TNode extends MapNode<infer TValue>\n ? CollectionReader<string, DocumentValueOfNode<TValue>>\n : TNode extends DictNode<infer TKey, infer TValue>\n ? FieldReader<Readonly<Partial<Record<TKey, TValue>>>>\n : TNode extends ListNode<infer TItem>\n ? ListReader<TItem>\n : TNode extends TreeNode<infer TValue>\n ? TreeReader<TValue>\n : FieldReader<DocumentValueOfNode<TNode>>;\nexport type DocumentReader<TSchema extends DocumentSchema> = ReaderOfNode<\n ObjectNode<TSchema['shape']>\n>;\n\nexport type ReaderContext = {\n readonly root: () => unknown;\n readonly active: () => boolean;\n readonly dependencies?: DependencyTracker;\n};\n\nconst schemaRoot = (schema: DocumentSchema): DocumentNode => object(schema.shape);\n\nconst assertActive = (context: ReaderContext): void => {\n if (!context.active()) throw new Error('Document reader is no longer active.');\n};\n\nconst readAt = (context: ReaderContext, address: DocumentAddress): unknown => {\n assertActive(context);\n profile.reader.lookup();\n return readAddress(context.root(), address);\n};\n\nconst collectValue = (context: ReaderContext, address: DocumentAddress): void => {\n context.dependencies?.record({ kind: 'value', at: address });\n};\n\nconst collectCollection = (context: ReaderContext, address: DocumentAddress, id?: string): void => {\n const target: ImpactTarget<unknown> = {\n kind: 'collection',\n at: address,\n ...(id === undefined ? {} : { id }),\n };\n context.dependencies?.record(target);\n};\n\nexport const readerFor = (\n node: DocumentNode,\n context: ReaderContext,\n address: DocumentAddress = []\n): unknown => {\n if (node.kind === 'field')\n return {\n get: () => {\n collectValue(context, address);\n return readAt(context, address);\n },\n };\n if (node.kind === 'dict' || node.kind === 'record')\n return {\n get: () => {\n collectValue(context, address);\n profile.reader.structuralSnapshot();\n return cloneValue(readAt(context, address), 'reader');\n },\n };\n if (node.kind === 'list')\n return {\n values: () => {\n collectValue(context, address);\n const value = readAt(context, address);\n profile.reader.structuralSnapshot();\n return cloneValue(Array.isArray(value) ? value : [], 'reader');\n },\n length: () => {\n collectValue(context, address);\n const value = readAt(context, address);\n return Array.isArray(value) ? value.length : 0;\n },\n at: (index: number) => {\n collectValue(context, address);\n const value = readAt(context, address);\n profile.reader.structuralSnapshot();\n return cloneValue(Array.isArray(value) ? value[index] : undefined, 'reader');\n },\n };\n if (node.kind === 'tree')\n return {\n rootId: () => {\n collectValue(context, address);\n const value = readAt(context, address);\n return isRecord(value) && typeof value.rootId === 'string' ? value.rootId : undefined;\n },\n has: (id: string) => {\n collectValue(context, address);\n const value = readAt(context, address);\n return (\n isRecord(value) &&\n isRecord(value.nodes) &&\n Object.prototype.hasOwnProperty.call(value.nodes, id)\n );\n },\n value: (id: string) => {\n collectValue(context, address);\n const value = readAt(context, address);\n profile.reader.structuralSnapshot();\n return cloneValue(\n isRecord(value) && isRecord(value.nodes) && isRecord(value.nodes[id])\n ? value.nodes[id].value\n : undefined,\n 'reader'\n );\n },\n parent: (id: string) => {\n collectValue(context, address);\n const value = readAt(context, address);\n const entry = isRecord(value) && isRecord(value.nodes) ? value.nodes[id] : undefined;\n return isRecord(entry) && typeof entry.parentId === 'string' ? entry.parentId : undefined;\n },\n children: (id: string) => {\n collectValue(context, address);\n const value = readAt(context, address);\n const entry = isRecord(value) && isRecord(value.nodes) ? value.nodes[id] : undefined;\n return isRecord(entry) && Array.isArray(entry.children) ? [...entry.children] : [];\n },\n };\n if (node.kind === 'table' || node.kind === 'map') {\n let items: Map<string, unknown> | undefined;\n return {\n ids: () => {\n collectCollection(context, address);\n const value = readAt(context, address);\n const ids =\n node.kind === 'table' && isRecord(value) && Array.isArray(value.ids)\n ? [...value.ids]\n : isRecord(value)\n ? Object.keys(value)\n : [];\n profile.reader.collectionIds(ids.length);\n return ids;\n },\n has: (id: string) => {\n collectCollection(context, address, id);\n const value = readAt(context, address);\n const byId =\n node.kind === 'table' && isRecord(value) && isRecord(value.byId) ? value.byId : value;\n return isRecord(byId) && Object.prototype.hasOwnProperty.call(byId, id);\n },\n get: (id: string) => {\n collectCollection(context, address, id);\n const value = readAt(context, address);\n const byId =\n node.kind === 'table' && isRecord(value) && isRecord(value.byId) ? value.byId : value;\n if (!isRecord(byId) || !Object.prototype.hasOwnProperty.call(byId, id)) return undefined;\n const cached = items?.get(id);\n if (cached) return cached as EntityReader<unknown>;\n const reader = readerFor(node.value, context, [...address, id]);\n (items ??= new Map()).set(id, reader);\n return reader;\n },\n };\n }\n if (node.kind === 'single') return readerFor(node.value, context, address);\n if (node.kind === 'variant')\n return new Proxy(\n {},\n {\n get: (_target, property: string | symbol) => {\n if (typeof property === 'symbol') return undefined;\n const value = readAt(context, address);\n const tag =\n isRecord(value) && typeof value[node.tag] === 'string'\n ? String(value[node.tag])\n : undefined;\n const branch = tag ? node.variants[tag] : undefined;\n const child = branch?.shape[property];\n return child ? readerFor(child, context, [...address, property]) : undefined;\n },\n }\n );\n\n let children: Map<string, unknown> | undefined;\n return new Proxy(\n {},\n {\n get: (_target, property: string | symbol) => {\n if (typeof property === 'symbol') return undefined;\n const child = node.shape[property];\n if (!child) return undefined;\n const cached = children?.get(property);\n if (cached) return cached;\n const reader = readerFor(child, context, [...address, property]);\n (children ??= new Map()).set(property, reader);\n return reader;\n },\n }\n );\n};\n\nexport const documentReader = <TSchema extends DocumentSchema>(\n schema: TSchema,\n root: () => ReadonlyDocument<TSchema>,\n active: () => boolean,\n dependencies?: DependencyTracker\n): DocumentReader<TSchema> => {\n profile.reader.session();\n return readerFor(schemaRoot(schema), {\n root,\n active,\n dependencies,\n }) as DocumentReader<TSchema>;\n};\n","import type { DocumentAddress, DocumentSchema, ImpactTarget, ReadonlyDocument } from '../schema';\nimport type { AddressRef } from '../address';\nimport type { DocumentOperationUnion } from '../operations';\nimport type { DocumentImpact } from '../impact';\nimport type { DocumentReader } from '../access/reader';\nimport type { DocumentWriter } from '../access/writer';\nimport type { MutationIssue } from '../mutation/issue';\n\nexport type Unsubscribe = () => void;\nexport type CommitSource = 'local' | 'system' | 'history' | 'remote';\n\nexport class DocumentReentrancyError extends Error {\n constructor() {\n super('Document writes cannot be re-entered during an update or notification.');\n this.name = 'DocumentReentrancyError';\n }\n}\n\nexport class DocumentDisposedError extends Error {\n constructor() {\n super('Doxum runtime has been disposed.');\n this.name = 'DocumentDisposedError';\n }\n}\nexport type DocumentCommit<TSchema extends DocumentSchema> = {\n readonly revision: number;\n readonly kind: 'operations' | 'replace';\n readonly source: CommitSource;\n readonly operations: readonly DocumentOperationUnion<TSchema>[];\n readonly inverse: readonly DocumentOperationUnion<TSchema>[];\n readonly impact: DocumentImpact<TSchema>;\n};\nexport type DocumentDiagnostic = {\n readonly source: 'application';\n readonly code: string;\n readonly message: string;\n readonly address?: DocumentAddress;\n};\nexport type DocumentProblem = DocumentDiagnostic | MutationIssue;\nexport type ObserverError = {\n readonly phase: 'processor' | 'flush' | 'listener';\n readonly error: unknown;\n};\nexport type TransactionResult<TValue, TCommit> =\n | {\n readonly status: 'committed';\n readonly value: TValue;\n readonly commit: TCommit;\n readonly reports: readonly DocumentDiagnostic[];\n readonly observerErrors: readonly ObserverError[];\n }\n | {\n readonly status: 'unchanged';\n readonly value: TValue;\n readonly revision: number;\n readonly reports: readonly DocumentDiagnostic[];\n }\n | {\n readonly status: 'rejected';\n readonly issues: readonly DocumentProblem[];\n readonly revision: number;\n };\nexport type OperationResult<TCommit> =\n | {\n readonly status: 'committed';\n readonly commit: TCommit;\n readonly observerErrors: readonly ObserverError[];\n }\n | { readonly status: 'unchanged'; readonly revision: number }\n | {\n readonly status: 'rejected';\n readonly issues: readonly MutationIssue[];\n readonly revision: number;\n };\n\nexport type HistoryState = {\n readonly undoDepth: number;\n readonly redoDepth: number;\n};\nexport type LocalHistory<TCommit> = {\n current(): HistoryState;\n subscribe(listener: () => void): Unsubscribe;\n undo(): OperationResult<TCommit>;\n redo(): OperationResult<TCommit>;\n clear(): void;\n};\n\nexport type DocumentTransaction<TSchema extends DocumentSchema> = {\n readonly read: DocumentReader<TSchema>;\n readonly write: DocumentWriter<TSchema>;\n readonly reject: (issue: DocumentDiagnostic | readonly DocumentDiagnostic[]) => never;\n readonly report: (issue: DocumentDiagnostic) => void;\n};\nexport type CommitListener<TSchema extends DocumentSchema> = (\n commit: DocumentCommit<TSchema>\n) => void;\nexport type RuntimeProcessor<TSchema extends DocumentSchema> = {\n readonly process: (commit: DocumentCommit<TSchema>) => void;\n readonly flush: () => void;\n};\n\nexport type DocumentRuntime<TSchema extends DocumentSchema> = {\n readonly address: {\n readonly resolve: (address: DocumentAddress) => AddressRef | undefined;\n readonly read: (address: DocumentAddress) => unknown;\n readonly contains: (parent: DocumentAddress, child: DocumentAddress) => boolean;\n readonly overlaps: (left: DocumentAddress, right: DocumentAddress) => boolean;\n readonly debugKey: (address: DocumentAddress) => string;\n };\n revision(): number;\n update<TResult>(\n run: (transaction: DocumentTransaction<TSchema>) => TResult,\n options?: {\n readonly source?: Extract<CommitSource, 'local' | 'system'>;\n readonly history?: boolean;\n }\n ): TransactionResult<TResult, DocumentCommit<TSchema>>;\n apply(\n operations: unknown,\n options?: {\n readonly source?: Exclude<CommitSource, 'history'>;\n readonly history?: boolean;\n }\n ): OperationResult<DocumentCommit<TSchema>>;\n replace(\n document: ReadonlyDocument<TSchema>,\n options?: { readonly source?: Extract<CommitSource, 'system' | 'remote'> }\n ): OperationResult<DocumentCommit<TSchema>>;\n subscribe(listener: CommitListener<TSchema>): Unsubscribe;\n subscribe(\n target: ImpactTarget<unknown> | readonly [ImpactTarget<unknown>, ...ImpactTarget<unknown>[]],\n listener: CommitListener<TSchema>\n ): Unsubscribe;\n readonly history: LocalHistory<DocumentCommit<TSchema>>;\n dispose(): void;\n};\n","import type { DocumentSchema, ReadonlyDocument } from '../schema';\nimport type { DocumentReader } from '../access/reader';\nimport { documentReader } from '../access/reader';\nimport type { DependencyTracker } from '../access/dependency';\nimport { DocumentDisposedError } from './contract';\nimport type { DocumentRuntime } from './contract';\n\nexport type RuntimeAccessState<TSchema extends DocumentSchema> = {\n readonly schema: TSchema;\n document: ReadonlyDocument<TSchema>;\n disposed: boolean;\n};\n\nconst states = new WeakMap<object, RuntimeAccessState<DocumentSchema>>();\n\nexport const bindRuntimeAccess = <TSchema extends DocumentSchema>(\n runtime: DocumentRuntime<TSchema>,\n state: RuntimeAccessState<TSchema>\n): void => {\n states.set(runtime as object, state as RuntimeAccessState<DocumentSchema>);\n};\n\nexport const accessOf = <TSchema extends DocumentSchema>(\n runtime: DocumentRuntime<TSchema>\n): RuntimeAccessState<TSchema> => {\n const state = states.get(runtime as object);\n if (!state) throw new Error('Unknown Doxum runtime.');\n return state as RuntimeAccessState<TSchema>;\n};\n\nexport const schemaOf = <TSchema extends DocumentSchema>(\n runtime: DocumentRuntime<TSchema>\n): TSchema => accessOf(runtime).schema;\n\nexport const documentOf = <TSchema extends DocumentSchema>(\n runtime: DocumentRuntime<TSchema>\n): ReadonlyDocument<TSchema> => accessOf(runtime).document;\n\nexport const readWith = <TSchema extends DocumentSchema, TResult>(\n runtime: DocumentRuntime<TSchema>,\n run: (read: DocumentReader<TSchema>) => TResult,\n dependencies?: DependencyTracker\n): TResult => {\n const state = accessOf(runtime);\n if (state.disposed) throw new DocumentDisposedError();\n let active = true;\n const reader = documentReader(\n state.schema,\n () => state.document,\n () => active,\n dependencies\n );\n try {\n return run(reader);\n } finally {\n // Readers are transaction-scoped; retaining one cannot expose later\n // mutable canonical state outside the coordinating operation.\n active = false;\n }\n};\n","import type { ImpactTarget } from '../schema';\nimport * as impactTarget from '../impact-target';\n\nexport type DependencyTracker = {\n readonly record: (target: ImpactTarget<unknown>) => void;\n readonly clear: () => void;\n readonly size: () => number;\n readonly some: (test: (target: ImpactTarget<unknown>) => boolean) => boolean;\n readonly snapshot: () => readonly ImpactTarget<unknown>[];\n};\n\nexport const createDependencyTracker = (): DependencyTracker => {\n const targets: ImpactTarget<unknown>[] = [];\n return {\n record: value => {\n if (!targets.some(entry => impactTarget.same(entry, value))) targets.push(value);\n },\n clear: () => {\n targets.length = 0;\n },\n size: () => targets.length,\n some: test => targets.some(test),\n snapshot: () => Object.freeze(targets.slice()),\n };\n};\n"],"mappings":"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"}
|