doxum 0.1.2 → 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 +59 -27
- package/dist/{contract-DGkZcTiP.d.cts → contract-BsY1XLiG.d.ts} +2 -1
- package/dist/{contract-Dh3az8aN.d.ts → contract-D8kjdfqT.d.cts} +2 -1
- package/dist/{access-5D4KKFm7.js → dependency-C5_R1tvQ.js} +40 -262
- package/dist/dependency-C5_R1tvQ.js.map +1 -0
- package/dist/{access-z56fVqZ2.cjs → dependency-Dfzs3khk.cjs} +62 -344
- 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 +2636 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2594 -4
- package/dist/index.js.map +1 -1
- package/dist/integration.cjs +2 -3
- package/dist/integration.cjs.map +1 -1
- package/dist/integration.d.cts +1 -1
- package/dist/integration.d.ts +1 -1
- package/dist/integration.js +1 -2
- package/dist/integration.js.map +1 -1
- package/dist/local-sync.cjs +154 -329
- package/dist/local-sync.cjs.map +1 -1
- package/dist/local-sync.d.cts +17 -22
- package/dist/local-sync.d.ts +17 -22
- package/dist/local-sync.js +149 -326
- package/dist/local-sync.js.map +1 -1
- 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/package.json +1 -1
- package/skills/doxum-runtime/references/guide.en.md +52 -1
- package/skills/doxum-runtime/references/guide.zh-CN.md +46 -1
- package/skills/doxum-runtime/references/invariants.en.md +14 -4
- package/skills/doxum-runtime/references/invariants.zh-CN.md +1 -1
- package/dist/access-5D4KKFm7.js.map +0 -1
- package/dist/access-z56fVqZ2.cjs.map +0 -1
- package/dist/dependency-BRn1TRDi.js +0 -20
- package/dist/dependency-BRn1TRDi.js.map +0 -1
- package/dist/dependency-DmQXyj7q.cjs +0 -25
- package/dist/dependency-DmQXyj7q.cjs.map +0 -1
- package/dist/readable-B8E3FMq6.cjs +0 -2614
- package/dist/readable-B8E3FMq6.cjs.map +0 -1
- package/dist/readable-CIj02gIj.js +0 -2579
- package/dist/readable-CIj02gIj.js.map +0 -1
package/dist/local-sync.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-sync.cjs","names":["isPlainObject","nonNegativeInteger","positiveInteger","isRecord","decodeCommandFootprint","createDocument","commandFootprint","asReadable"],"sources":["../core/src/local-sync/contract.ts","../core/src/local-sync/json.ts","../core/src/local-sync/timeline.ts","../core/src/local-sync/session.ts"],"sourcesContent":["import type { DocumentSchema, ReadonlyDocument } from '../schema';\nimport type {\n DocumentCommit,\n DocumentReadable,\n DocumentTransaction,\n OperationResult,\n TransactionResult,\n} from '../runtime/contract';\nimport type { JsonCommandLimits } from './json';\n\nexport class LocalSyncUnavailableError extends Error {\n constructor(capability: 'IndexedDB' | 'Web Locks' | 'BroadcastChannel') {\n super(`${capability} is required by doxum/local-sync in this environment.`);\n this.name = 'LocalSyncUnavailableError';\n }\n}\n\nexport class LocalSyncSchemaError extends Error {\n constructor(documentId: string, expected: number, actual: number) {\n super(\n `Local document '${documentId}' uses schema version ${actual}, but version ${expected} was requested.`\n );\n this.name = 'LocalSyncSchemaError';\n }\n}\n\nexport class LocalSyncConsistencyError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'LocalSyncConsistencyError';\n }\n}\n\nexport class LocalSyncDisposedError extends Error {\n constructor() {\n super('Local sync document has been disposed.');\n this.name = 'LocalSyncDisposedError';\n }\n}\n\nexport type LocalSyncCommit<TSchema extends DocumentSchema> = DocumentCommit<TSchema> & {\n readonly seq: number;\n readonly commandId: string;\n readonly actorId: string;\n};\n\nexport type LocalSyncState =\n | { readonly status: 'ready'; readonly headSeq: number; readonly checkpointSeq: number }\n | { readonly status: 'failed'; readonly error: unknown }\n | { readonly status: 'disposed' };\n\nexport type LocalSyncDocument<TSchema extends DocumentSchema> = {\n readonly document: DocumentReadable<TSchema>;\n state(): LocalSyncState;\n sync(): Promise<void>;\n update<TResult>(\n run: (transaction: DocumentTransaction<TSchema>) => TResult\n ): Promise<TransactionResult<TResult, LocalSyncCommit<TSchema>>>;\n undo(): Promise<OperationResult<LocalSyncCommit<TSchema>>>;\n redo(): Promise<OperationResult<LocalSyncCommit<TSchema>>>;\n dispose(): Promise<void>;\n};\n\nexport type OpenLocalDocumentOptions<TSchema extends DocumentSchema> = {\n readonly database: string;\n readonly documentId: string;\n readonly schema: TSchema;\n readonly initial: ReadonlyDocument<TSchema>;\n readonly schemaVersion?: number;\n readonly actorId?: string;\n readonly historyCapacity?: number;\n readonly checkpointEvery?: number;\n readonly commandLimits?: JsonCommandLimits;\n readonly onError?: (error: unknown) => void;\n};\n","import { isPlainObject } from '../value/ownership';\n\nexport type JsonPrimitive = null | boolean | number | string;\nexport type JsonValue =\n JsonPrimitive | readonly JsonValue[] | { readonly [key: string]: JsonValue };\n\nexport type JsonCommandLimits = {\n readonly maxOperations?: number;\n readonly maxBytes?: number;\n readonly maxDepth?: number;\n readonly maxStringLength?: number;\n};\n\ntype ResolvedJsonLimits = {\n readonly maxOperations: number;\n readonly maxBytes: number;\n readonly maxDepth: number;\n readonly maxStringLength: number;\n};\n\nexport const defaultJsonCommandLimits: Readonly<ResolvedJsonLimits> = Object.freeze({\n maxOperations: 1_000,\n maxBytes: 1_000_000,\n maxDepth: 64,\n maxStringLength: 256_000,\n});\n\nexport class LocalSyncDataError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'LocalSyncDataError';\n }\n}\n\nconst describePath = (path: readonly string[]): string =>\n path.length === 0 ? 'value' : path.join('.');\n\nconst limit = (value: number | undefined, fallback: number, label: string): number => {\n if (value === undefined) return fallback;\n if (Number.isSafeInteger(value) && value > 0) return value;\n throw new TypeError(`${label} must be a positive safe integer.`);\n};\n\nconst resolveLimits = (input: JsonCommandLimits | undefined): ResolvedJsonLimits => ({\n maxOperations: limit(\n input?.maxOperations,\n defaultJsonCommandLimits.maxOperations,\n 'maxOperations'\n ),\n maxBytes: limit(input?.maxBytes, defaultJsonCommandLimits.maxBytes, 'maxBytes'),\n maxDepth: limit(input?.maxDepth, defaultJsonCommandLimits.maxDepth, 'maxDepth'),\n maxStringLength: limit(\n input?.maxStringLength,\n defaultJsonCommandLimits.maxStringLength,\n 'maxStringLength'\n ),\n});\n\nconst validate = (\n value: unknown,\n path: readonly string[],\n limits: ResolvedJsonLimits | undefined,\n depth: number,\n ancestors: WeakSet<object>\n): JsonValue => {\n if (limits && depth > limits.maxDepth)\n throw new LocalSyncDataError(`${describePath(path)} exceeds the maximum JSON depth.`);\n if (value === null || typeof value === 'boolean') return value;\n if (typeof value === 'string') {\n if (!limits || value.length <= limits.maxStringLength) return value;\n throw new LocalSyncDataError(`${describePath(path)} exceeds the maximum string length.`);\n }\n if (typeof value === 'number') {\n if (Number.isFinite(value)) return value;\n throw new LocalSyncDataError(`${describePath(path)} contains a non-finite number.`);\n }\n if (Array.isArray(value)) {\n if (ancestors.has(value))\n throw new LocalSyncDataError(`${describePath(path)} contains a cycle.`);\n ancestors.add(value);\n try {\n for (let index = 0; index < value.length; index += 1)\n validate(value[index], [...path, String(index)], limits, depth + 1, ancestors);\n } finally {\n ancestors.delete(value);\n }\n return value as readonly JsonValue[];\n }\n if (isPlainObject(value)) {\n if (ancestors.has(value))\n throw new LocalSyncDataError(`${describePath(path)} contains a cycle.`);\n ancestors.add(value);\n try {\n for (const [key, entry] of Object.entries(value))\n validate(entry, [...path, key], limits, depth + 1, ancestors);\n } finally {\n ancestors.delete(value);\n }\n return value as { readonly [key: string]: JsonValue };\n }\n throw new LocalSyncDataError(`${describePath(path)} must be JSON data.`);\n};\n\nexport const json = (value: unknown, label: string): JsonValue =>\n validate(value, [label], undefined, 0, new WeakSet());\n\nexport const jsonArray = (\n value: unknown,\n label: string,\n input?: JsonCommandLimits\n): readonly JsonValue[] => {\n const limits = resolveLimits(input);\n const parsed = validate(value, [label], limits, 0, new WeakSet());\n if (!Array.isArray(parsed)) throw new LocalSyncDataError(`${label} must be a JSON array.`);\n if (parsed.length > limits.maxOperations)\n throw new LocalSyncDataError(`${label} exceeds the maximum operation count.`);\n const serialized = JSON.stringify(parsed);\n if (new TextEncoder().encode(serialized).byteLength > limits.maxBytes)\n throw new LocalSyncDataError(`${label} exceeds the maximum command size.`);\n return parsed;\n};\n","import { isRecord } from '../value/ownership';\nimport { decodeCommandFootprint, type CommandFootprint } from '../mutation/footprint';\nimport {\n LocalSyncConsistencyError,\n LocalSyncSchemaError,\n LocalSyncUnavailableError,\n} from './contract';\nimport { json, jsonArray, type JsonValue } from './json';\n\nconst DATABASE_VERSION = 1;\nconst DOCUMENTS = 'documents';\nconst COMMITS = 'commits';\nconst ACTORS = 'actors';\n\nexport type LocalCommitKind = 'update' | 'undo' | 'redo';\n\nexport type StoredDocument = {\n readonly documentId: string;\n readonly schemaVersion: number;\n readonly checkpointSeq: number;\n readonly headSeq: number;\n readonly checkpoint: JsonValue;\n};\n\nexport type StoredHistoryEntry = {\n readonly commandId: string;\n readonly operations: readonly JsonValue[];\n readonly inverse: readonly JsonValue[];\n readonly footprint: CommandFootprint;\n};\n\nexport type StoredActorHistory = {\n readonly documentId: string;\n readonly actorId: string;\n readonly undo: readonly StoredHistoryEntry[];\n readonly redo: readonly StoredHistoryEntry[];\n};\n\nexport type StoredCommit = {\n readonly documentId: string;\n readonly seq: number;\n readonly commandId: string;\n readonly actorId: string;\n readonly kind: LocalCommitKind;\n readonly operations: readonly JsonValue[];\n readonly inverse: readonly JsonValue[];\n readonly footprint: CommandFootprint;\n readonly createdAt: number;\n};\n\nexport type ActorHistoryChange =\n | { readonly kind: 'record'; readonly entry: StoredHistoryEntry; readonly capacity: number }\n | {\n readonly kind: 'undo';\n readonly expectedCommandId: string;\n readonly entry: StoredHistoryEntry;\n }\n | {\n readonly kind: 'redo';\n readonly expectedCommandId: string;\n readonly entry: StoredHistoryEntry;\n };\n\nconst request = <T>(value: IDBRequest<T>): Promise<T> =>\n new Promise((resolve, reject) => {\n value.onsuccess = () => resolve(value.result);\n value.onerror = () => reject(value.error ?? new Error('IndexedDB request failed.'));\n });\n\nconst complete = (transaction: IDBTransaction): Promise<void> =>\n new Promise((resolve, reject) => {\n transaction.oncomplete = () => resolve();\n transaction.onabort = () =>\n reject(transaction.error ?? new Error('IndexedDB transaction was aborted.'));\n transaction.onerror = () =>\n reject(transaction.error ?? new Error('IndexedDB transaction failed.'));\n });\n\nconst factory = (): IDBFactory => {\n if (!globalThis.indexedDB) throw new LocalSyncUnavailableError('IndexedDB');\n return globalThis.indexedDB;\n};\n\nconst keyRange = (): typeof IDBKeyRange => {\n if (!globalThis.IDBKeyRange) throw new LocalSyncUnavailableError('IndexedDB');\n return globalThis.IDBKeyRange;\n};\n\nconst string = (value: unknown, label: string): string => {\n if (typeof value === 'string') return value;\n throw new LocalSyncConsistencyError(`${label} is malformed in IndexedDB.`);\n};\n\nconst nonNegativeInteger = (value: unknown, label: string): number => {\n if (typeof value === 'number' && Number.isSafeInteger(value) && value >= 0) return value;\n throw new LocalSyncConsistencyError(`${label} is malformed in IndexedDB.`);\n};\n\nconst positiveInteger = (value: unknown, label: string): number => {\n const parsed = nonNegativeInteger(value, label);\n if (parsed > 0) return parsed;\n throw new LocalSyncConsistencyError(`${label} is malformed in IndexedDB.`);\n};\n\nconst historyEntry = (value: unknown, label: string): StoredHistoryEntry => {\n if (!isRecord(value)) throw new LocalSyncConsistencyError(`${label} is malformed in IndexedDB.`);\n const footprint = decodeCommandFootprint(value.footprint);\n if (!footprint)\n throw new LocalSyncConsistencyError(`${label}.footprint is malformed in IndexedDB.`);\n return Object.freeze({\n commandId: string(value.commandId, `${label}.commandId`),\n operations: jsonArray(value.operations, `${label}.operations`),\n inverse: jsonArray(value.inverse, `${label}.inverse`),\n footprint,\n });\n};\n\nconst historyEntries = (value: unknown, label: string): readonly StoredHistoryEntry[] => {\n if (!Array.isArray(value))\n throw new LocalSyncConsistencyError(`${label} is malformed in IndexedDB.`);\n return Object.freeze(value.map((entry, index) => historyEntry(entry, `${label}.${index}`)));\n};\n\nconst documentRecord = (value: unknown): StoredDocument => {\n if (!isRecord(value))\n throw new LocalSyncConsistencyError('Document record is malformed in IndexedDB.');\n const checkpointSeq = nonNegativeInteger(value.checkpointSeq, 'document.checkpointSeq');\n const headSeq = nonNegativeInteger(value.headSeq, 'document.headSeq');\n if (checkpointSeq > headSeq)\n throw new LocalSyncConsistencyError('Document checkpoint exceeds its head sequence.');\n return Object.freeze({\n documentId: string(value.documentId, 'document.documentId'),\n schemaVersion: positiveInteger(value.schemaVersion, 'document.schemaVersion'),\n checkpointSeq,\n headSeq,\n checkpoint: json(value.checkpoint, 'document.checkpoint'),\n });\n};\n\nconst commitRecord = (value: unknown): StoredCommit => {\n if (!isRecord(value))\n throw new LocalSyncConsistencyError('Commit record is malformed in IndexedDB.');\n const kind = value.kind;\n if (kind !== 'update' && kind !== 'undo' && kind !== 'redo')\n throw new LocalSyncConsistencyError('Commit kind is malformed in IndexedDB.');\n const footprint = decodeCommandFootprint(value.footprint);\n if (!footprint)\n throw new LocalSyncConsistencyError('Commit footprint is malformed in IndexedDB.');\n return Object.freeze({\n documentId: string(value.documentId, 'commit.documentId'),\n seq: positiveInteger(value.seq, 'commit.seq'),\n commandId: string(value.commandId, 'commit.commandId'),\n actorId: string(value.actorId, 'commit.actorId'),\n kind,\n operations: jsonArray(value.operations, 'commit.operations'),\n inverse: jsonArray(value.inverse, 'commit.inverse'),\n footprint,\n createdAt: nonNegativeInteger(value.createdAt, 'commit.createdAt'),\n });\n};\n\nconst actorRecord = (value: unknown, documentId: string, actorId: string): StoredActorHistory => {\n if (value === undefined)\n return Object.freeze({\n documentId,\n actorId,\n undo: Object.freeze([]),\n redo: Object.freeze([]),\n });\n if (!isRecord(value))\n throw new LocalSyncConsistencyError('Actor history is malformed in IndexedDB.');\n const storedDocumentId = string(value.documentId, 'actor.documentId');\n const storedActorId = string(value.actorId, 'actor.actorId');\n if (storedDocumentId !== documentId || storedActorId !== actorId)\n throw new LocalSyncConsistencyError('Actor history key does not match its record.');\n return Object.freeze({\n documentId,\n actorId,\n undo: historyEntries(value.undo, 'actor.undo'),\n redo: historyEntries(value.redo, 'actor.redo'),\n });\n};\n\nconst nextHistory = (\n current: StoredActorHistory,\n change: ActorHistoryChange\n): StoredActorHistory => {\n if (change.kind === 'record') {\n const undo = [...current.undo, change.entry];\n const start = Math.max(0, undo.length - change.capacity);\n return Object.freeze({\n documentId: current.documentId,\n actorId: current.actorId,\n undo: Object.freeze(undo.slice(start)),\n redo: Object.freeze([]),\n });\n }\n const source = change.kind === 'undo' ? current.undo : current.redo;\n const latest = source[source.length - 1];\n if (!latest || latest.commandId !== change.expectedCommandId)\n throw new LocalSyncConsistencyError('Local undo history changed before it could be committed.');\n if (change.kind === 'undo')\n return Object.freeze({\n documentId: current.documentId,\n actorId: current.actorId,\n undo: Object.freeze(current.undo.slice(0, -1)),\n redo: Object.freeze([...current.redo, change.entry]),\n });\n return Object.freeze({\n documentId: current.documentId,\n actorId: current.actorId,\n undo: Object.freeze([...current.undo, change.entry]),\n redo: Object.freeze(current.redo.slice(0, -1)),\n });\n};\n\nconst deleteCommitsThrough = async (\n store: IDBObjectStore,\n documentId: string,\n seq: number\n): Promise<void> => {\n const range = keyRange().bound([documentId, 0], [documentId, seq]);\n await new Promise<void>((resolve, reject) => {\n const cursor = store.openCursor(range);\n cursor.onerror = () => reject(cursor.error ?? new Error('IndexedDB cursor failed.'));\n cursor.onsuccess = () => {\n const current = cursor.result;\n if (!current) {\n resolve();\n return;\n }\n current.delete();\n current.continue();\n };\n });\n};\n\nexport type IndexedDbTimeline = {\n readonly initialize: (\n documentId: string,\n schemaVersion: number,\n checkpoint: JsonValue\n ) => Promise<StoredDocument>;\n readonly read: (documentId: string) => Promise<StoredDocument>;\n readonly tail: (documentId: string, afterSeq: number) => Promise<readonly StoredCommit[]>;\n readonly history: (documentId: string, actorId: string) => Promise<StoredActorHistory>;\n readonly append: (input: {\n readonly documentId: string;\n readonly expectedHeadSeq: number;\n readonly commandId: string;\n readonly actorId: string;\n readonly kind: LocalCommitKind;\n readonly operations: readonly JsonValue[];\n readonly inverse: readonly JsonValue[];\n readonly footprint: CommandFootprint;\n readonly history: ActorHistoryChange;\n }) => Promise<StoredCommit>;\n readonly compact: (\n documentId: string,\n seq: number,\n checkpoint: JsonValue\n ) => Promise<StoredDocument>;\n readonly close: () => void;\n};\n\nexport const openIndexedDbTimeline = async (databaseName: string): Promise<IndexedDbTimeline> => {\n const database = await new Promise<IDBDatabase>((resolve, reject) => {\n const open = factory().open(databaseName, DATABASE_VERSION);\n open.onerror = () => reject(open.error ?? new Error('Unable to open IndexedDB.'));\n open.onblocked = () => reject(new Error(`IndexedDB database '${databaseName}' is blocked.`));\n open.onupgradeneeded = () => {\n const db = open.result;\n if (!db.objectStoreNames.contains(DOCUMENTS))\n db.createObjectStore(DOCUMENTS, { keyPath: 'documentId' });\n if (!db.objectStoreNames.contains(COMMITS))\n db.createObjectStore(COMMITS, { keyPath: ['documentId', 'seq'] });\n if (!db.objectStoreNames.contains(ACTORS))\n db.createObjectStore(ACTORS, { keyPath: ['documentId', 'actorId'] });\n };\n open.onsuccess = () => resolve(open.result);\n });\n\n const readDocument = async (\n transaction: IDBTransaction,\n documentId: string\n ): Promise<StoredDocument> => {\n const value = await request(transaction.objectStore(DOCUMENTS).get(documentId));\n if (value === undefined)\n throw new LocalSyncConsistencyError(`Local document '${documentId}' does not exist.`);\n return documentRecord(value);\n };\n\n return {\n initialize: async (documentId, schemaVersion, checkpoint) => {\n const transaction = database.transaction(DOCUMENTS, 'readwrite');\n const store = transaction.objectStore(DOCUMENTS);\n const existing = await request(store.get(documentId));\n if (existing !== undefined) {\n const record = documentRecord(existing);\n if (record.schemaVersion !== schemaVersion)\n throw new LocalSyncSchemaError(documentId, schemaVersion, record.schemaVersion);\n await complete(transaction);\n return record;\n }\n const record: StoredDocument = {\n documentId,\n schemaVersion,\n checkpointSeq: 0,\n headSeq: 0,\n checkpoint,\n };\n store.put(record);\n await complete(transaction);\n return Object.freeze(record);\n },\n read: async documentId => {\n const transaction = database.transaction(DOCUMENTS, 'readonly');\n const record = await readDocument(transaction, documentId);\n await complete(transaction);\n return record;\n },\n tail: async (documentId, afterSeq) => {\n const transaction = database.transaction(COMMITS, 'readonly');\n const range = keyRange().bound(\n [documentId, afterSeq + 1],\n [documentId, Number.MAX_SAFE_INTEGER]\n );\n const values = await request(transaction.objectStore(COMMITS).getAll(range));\n await complete(transaction);\n return Object.freeze(values.map(commitRecord).sort((left, right) => left.seq - right.seq));\n },\n history: async (documentId, actorId) => {\n const transaction = database.transaction(ACTORS, 'readonly');\n const value = await request(transaction.objectStore(ACTORS).get([documentId, actorId]));\n await complete(transaction);\n return actorRecord(value, documentId, actorId);\n },\n append: async input => {\n const transaction = database.transaction([DOCUMENTS, COMMITS, ACTORS], 'readwrite');\n const documents = transaction.objectStore(DOCUMENTS);\n const commits = transaction.objectStore(COMMITS);\n const actors = transaction.objectStore(ACTORS);\n const current = await readDocument(transaction, input.documentId);\n if (current.headSeq !== input.expectedHeadSeq)\n throw new LocalSyncConsistencyError(\n 'Local document advanced before the writer lock was acquired.'\n );\n const actor = actorRecord(\n await request(actors.get([input.documentId, input.actorId])),\n input.documentId,\n input.actorId\n );\n const seq = current.headSeq + 1;\n const commit: StoredCommit = {\n documentId: input.documentId,\n seq,\n commandId: input.commandId,\n actorId: input.actorId,\n kind: input.kind,\n operations: input.operations,\n inverse: input.inverse,\n footprint: input.footprint,\n createdAt: Date.now(),\n };\n const nextDocument: StoredDocument = { ...current, headSeq: seq };\n commits.put(commit);\n documents.put(nextDocument);\n actors.put(nextHistory(actor, input.history));\n await complete(transaction);\n return Object.freeze(commit);\n },\n compact: async (documentId, seq, checkpoint) => {\n const transaction = database.transaction([DOCUMENTS, COMMITS], 'readwrite');\n const current = await readDocument(transaction, documentId);\n if (seq < current.checkpointSeq || seq > current.headSeq)\n throw new LocalSyncConsistencyError(\n 'Local checkpoint sequence is outside the durable timeline.'\n );\n const next: StoredDocument = { ...current, checkpointSeq: seq, checkpoint };\n transaction.objectStore(DOCUMENTS).put(next);\n await deleteCommitsThrough(transaction.objectStore(COMMITS), documentId, seq);\n await complete(transaction);\n return Object.freeze(next);\n },\n close: () => database.close(),\n };\n};\n","import { createDocument } from '../runtime';\nimport { asReadable } from '../runtime/readable';\nimport { commandFootprint, type CommandFootprint } from '../mutation/footprint';\nimport type { DocumentSchema, ReadonlyDocument } from '../schema';\nimport type {\n DocumentCommit,\n DocumentTransaction,\n OperationResult,\n TransactionResult,\n} from '../runtime/contract';\nimport {\n LocalSyncConsistencyError,\n LocalSyncDisposedError,\n LocalSyncUnavailableError,\n type LocalSyncCommit,\n type LocalSyncDocument,\n type LocalSyncState,\n type OpenLocalDocumentOptions,\n} from './contract';\nimport { json, jsonArray, type JsonValue } from './json';\nimport {\n openIndexedDbTimeline,\n type ActorHistoryChange,\n type LocalCommitKind,\n type StoredActorHistory,\n type StoredCommit,\n} from './timeline';\n\ntype LockManager = {\n readonly request: <T>(\n name: string,\n options: { readonly mode: 'exclusive' },\n callback: () => T | PromiseLike<T>\n ) => Promise<T>;\n};\n\ntype Channel = {\n onmessage: ((event: MessageEvent<unknown>) => void) | null;\n postMessage(message: unknown): void;\n close(): void;\n};\n\ntype ChannelConstructor = new (name: string) => Channel;\n\ntype CommitNotification = {\n readonly kind: 'commit';\n readonly documentId: string;\n readonly headSeq: number;\n readonly senderId: string;\n};\n\nconst locks = (): LockManager => {\n const value: unknown = globalThis.navigator?.locks;\n if (\n typeof value !== 'object' ||\n value === null ||\n !('request' in value) ||\n typeof value.request !== 'function'\n )\n throw new LocalSyncUnavailableError('Web Locks');\n return value as LockManager;\n};\n\nconst channelConstructor = (): ChannelConstructor => {\n const value: unknown = globalThis.BroadcastChannel;\n if (typeof value !== 'function') throw new LocalSyncUnavailableError('BroadcastChannel');\n return value as ChannelConstructor;\n};\n\nconst requiredString = (value: string, label: string): string => {\n if (value.length > 0) return value;\n throw new TypeError(`${label} must not be empty.`);\n};\n\nconst nonNegativeInteger = (value: number, label: string): number => {\n if (Number.isSafeInteger(value) && value >= 0) return value;\n throw new TypeError(`${label} must be a non-negative safe integer.`);\n};\n\nconst positiveInteger = (value: number, label: string): number => {\n if (Number.isSafeInteger(value) && value > 0) return value;\n throw new TypeError(`${label} must be a positive safe integer.`);\n};\n\nconst identifier = (): string =>\n globalThis.crypto?.randomUUID?.() ??\n `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;\n\nconst notification = (value: unknown): CommitNotification | undefined => {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined;\n const record = value as Record<string, unknown>;\n if (\n record.kind !== 'commit' ||\n typeof record.documentId !== 'string' ||\n typeof record.senderId !== 'string' ||\n typeof record.headSeq !== 'number' ||\n !Number.isSafeInteger(record.headSeq) ||\n record.headSeq < 0\n )\n return undefined;\n return record as CommitNotification;\n};\n\nconst localCommit = <TSchema extends DocumentSchema>(\n commit: DocumentCommit<TSchema>,\n stored: StoredCommit\n): LocalSyncCommit<TSchema> =>\n Object.freeze({\n ...commit,\n seq: stored.seq,\n commandId: stored.commandId,\n actorId: stored.actorId,\n });\n\nconst operationResult = <TSchema extends DocumentSchema>(\n result: OperationResult<DocumentCommit<TSchema>>,\n stored: StoredCommit\n): OperationResult<LocalSyncCommit<TSchema>> => {\n if (result.status !== 'committed')\n throw new LocalSyncConsistencyError('A durable local command could not be applied.');\n return {\n status: 'committed',\n commit: localCommit(result.commit, stored),\n observerErrors: result.observerErrors,\n };\n};\n\nexport const openLocalDocument = async <TSchema extends DocumentSchema>(\n input: OpenLocalDocumentOptions<TSchema>\n): Promise<LocalSyncDocument<TSchema>> => {\n const databaseName = requiredString(input.database, 'database');\n const documentId = requiredString(input.documentId, 'documentId');\n const actorId = requiredString(input.actorId ?? 'local', 'actorId');\n const schemaVersion = positiveInteger(input.schemaVersion ?? 1, 'schemaVersion');\n const historyCapacity = nonNegativeInteger(input.historyCapacity ?? 100, 'historyCapacity');\n const checkpointEvery = nonNegativeInteger(input.checkpointEvery ?? 500, 'checkpointEvery');\n const commandLimits = input.commandLimits;\n const initial = json(input.initial, 'initial document');\n const lockManager = locks();\n const BroadcastChannel = channelConstructor();\n const timeline = await openIndexedDbTimeline(databaseName);\n\n let channel: Channel | undefined;\n let runtime: ReturnType<typeof createDocument<TSchema>> | undefined;\n try {\n const stored = await timeline.initialize(documentId, schemaVersion, initial);\n const documentRuntime = createDocument({\n schema: input.schema,\n initial: stored.checkpoint as ReadonlyDocument<TSchema>,\n history: false,\n });\n runtime = documentRuntime;\n let headSeq = stored.checkpointSeq;\n let checkpointSeq = stored.checkpointSeq;\n let queued: Promise<void> = Promise.resolve();\n let fault: unknown;\n let closing = false;\n let disposed = false;\n const senderId = identifier();\n\n const fail = (error: unknown): void => {\n if (closing || disposed || fault) return;\n fault = error;\n try {\n input.onError?.(error);\n } catch {\n // Error reporting cannot repair or replace the original session failure.\n }\n };\n\n const assertOpen = (): void => {\n if (closing || disposed) throw new LocalSyncDisposedError();\n if (fault) throw fault;\n };\n\n const applyStored = (commit: StoredCommit): LocalSyncCommit<TSchema> => {\n if (commit.seq !== headSeq + 1)\n throw new LocalSyncConsistencyError('Local commit log contains a sequence gap.');\n const result = documentRuntime.apply(commit.operations, { source: 'local', history: false });\n const local = operationResult(result, commit);\n if (local.status !== 'committed')\n throw new LocalSyncConsistencyError('A durable local command was not committed.');\n headSeq = commit.seq;\n return local.commit;\n };\n\n const catchUp = async (): Promise<void> => {\n const current = await timeline.read(documentId);\n if (current.schemaVersion !== schemaVersion)\n throw new LocalSyncConsistencyError(\n 'Local document schema changed while this session was open.'\n );\n if (headSeq < current.checkpointSeq) {\n const replaced = documentRuntime.replace(current.checkpoint as ReadonlyDocument<TSchema>, {\n source: 'system',\n });\n if (replaced.status !== 'committed' && replaced.status !== 'unchanged')\n throw new LocalSyncConsistencyError('Local checkpoint could not be restored.');\n headSeq = current.checkpointSeq;\n checkpointSeq = current.checkpointSeq;\n }\n const tail = await timeline.tail(documentId, headSeq);\n for (const commit of tail) applyStored(commit);\n if (headSeq !== current.headSeq)\n throw new LocalSyncConsistencyError(\n 'Local commit log does not reach its recorded head sequence.'\n );\n checkpointSeq = current.checkpointSeq;\n };\n\n const execute = <T>(run: () => Promise<T>): Promise<T> => {\n const next = queued.then(run, run);\n queued = next.then(\n () => undefined,\n () => undefined\n );\n return next;\n };\n\n const withWriter = <T>(run: () => Promise<T>): Promise<T> =>\n lockManager.request(`doxum:${documentId}`, { mode: 'exclusive' }, async () => {\n assertOpen();\n try {\n await catchUp();\n } catch (error) {\n fail(error);\n throw error;\n }\n return run();\n });\n\n const persistAndApply = async (input: {\n readonly commandId: string;\n readonly kind: LocalCommitKind;\n readonly operations: readonly JsonValue[];\n readonly inverse: readonly JsonValue[];\n readonly footprint: CommandFootprint;\n readonly history: ActorHistoryChange;\n }): Promise<OperationResult<LocalSyncCommit<TSchema>>> => {\n try {\n const storedCommit = await timeline.append({\n documentId,\n expectedHeadSeq: headSeq,\n commandId: input.commandId,\n actorId,\n kind: input.kind,\n operations: input.operations,\n inverse: input.inverse,\n footprint: input.footprint,\n history: input.history,\n });\n const result = operationResult(\n documentRuntime.apply(storedCommit.operations, { source: 'local', history: false }),\n storedCommit\n );\n headSeq = storedCommit.seq;\n if (checkpointEvery > 0 && headSeq - checkpointSeq >= checkpointEvery) {\n const checkpoint = json(documentRuntime.snapshot(), 'local checkpoint');\n const compacted = await timeline.compact(documentId, headSeq, checkpoint);\n checkpointSeq = compacted.checkpointSeq;\n }\n channel?.postMessage({\n kind: 'commit',\n documentId,\n headSeq,\n senderId,\n } satisfies CommitNotification);\n return result;\n } catch (error) {\n fail(error);\n throw error;\n }\n };\n\n const replay = (operations: readonly JsonValue[]): OperationResult<DocumentCommit<TSchema>> => {\n const candidate = createDocument({\n schema: input.schema,\n initial: documentRuntime.snapshot(),\n history: false,\n });\n try {\n return candidate.apply(operations, { source: 'local', history: false });\n } finally {\n candidate.dispose();\n }\n };\n\n const applyHistory = async (\n history: StoredActorHistory,\n kind: 'undo' | 'redo'\n ): Promise<OperationResult<LocalSyncCommit<TSchema>>> => {\n const source = kind === 'undo' ? history.undo : history.redo;\n const entry = source[source.length - 1];\n if (!entry) return { status: 'unchanged', revision: documentRuntime.revision() };\n const preview = replay(kind === 'undo' ? entry.inverse : entry.operations);\n if (preview.status !== 'committed') return preview;\n const operations = jsonArray(preview.commit.operations, `${kind} operations`, commandLimits);\n const inverse = jsonArray(preview.commit.inverse, `${kind} inverse`, commandLimits);\n return persistAndApply({\n commandId: identifier(),\n kind,\n operations,\n inverse,\n footprint: commandFootprint(preview.commit.operations),\n history:\n kind === 'undo'\n ? { kind: 'undo', expectedCommandId: entry.commandId, entry }\n : { kind: 'redo', expectedCommandId: entry.commandId, entry },\n });\n };\n\n const initialTail = await timeline.tail(documentId, headSeq);\n for (const commit of initialTail) applyStored(commit);\n if (headSeq !== stored.headSeq)\n throw new LocalSyncConsistencyError(\n 'Local commit log does not reach its recorded head sequence.'\n );\n\n channel = new BroadcastChannel(`doxum:${databaseName}:${documentId}`);\n channel.onmessage = event => {\n const message = notification(event.data);\n if (\n !message ||\n message.documentId !== documentId ||\n message.senderId === senderId ||\n message.headSeq <= headSeq ||\n closing ||\n disposed\n )\n return;\n void execute(() => withWriter(async () => undefined)).catch(() => undefined);\n };\n\n const localDocument: LocalSyncDocument<TSchema> = {\n document: asReadable(documentRuntime),\n state: (): LocalSyncState => {\n if (disposed) return { status: 'disposed' };\n if (fault) return { status: 'failed', error: fault };\n return { status: 'ready', headSeq, checkpointSeq };\n },\n sync: () => execute(() => withWriter(async () => undefined)),\n update: <TResult>(\n run: (transaction: DocumentTransaction<TSchema>) => TResult\n ): Promise<TransactionResult<TResult, LocalSyncCommit<TSchema>>> => {\n assertOpen();\n return execute(() =>\n withWriter(async () => {\n const prepared = documentRuntime.prepare(run);\n if (prepared.status === 'unchanged')\n return {\n status: 'unchanged',\n value: prepared.value,\n revision: documentRuntime.revision(),\n reports: prepared.reports,\n };\n if (prepared.status === 'rejected')\n return {\n status: 'rejected',\n issues: prepared.issues,\n revision: documentRuntime.revision(),\n };\n const operations = jsonArray(\n prepared.operations,\n 'local command operations',\n commandLimits\n );\n const inverse = jsonArray(prepared.inverse, 'local command inverse', commandLimits);\n const commandId = identifier();\n const result = await persistAndApply({\n commandId,\n kind: 'update',\n operations,\n inverse,\n footprint: prepared.footprint,\n history: {\n kind: 'record',\n entry: Object.freeze({\n commandId,\n operations,\n inverse,\n footprint: prepared.footprint,\n }),\n capacity: historyCapacity,\n },\n });\n if (result.status !== 'committed')\n throw new LocalSyncConsistencyError('Prepared local command was not committed.');\n return {\n status: 'committed',\n value: prepared.value,\n commit: result.commit,\n reports: prepared.reports,\n observerErrors: result.observerErrors,\n };\n })\n );\n },\n undo: () => {\n assertOpen();\n return execute(() =>\n withWriter(async () => applyHistory(await timeline.history(documentId, actorId), 'undo'))\n );\n },\n redo: () => {\n assertOpen();\n return execute(() =>\n withWriter(async () => applyHistory(await timeline.history(documentId, actorId), 'redo'))\n );\n },\n dispose: async () => {\n if (disposed) return;\n if (closing) {\n await queued;\n return;\n }\n closing = true;\n await queued;\n disposed = true;\n channel?.close();\n timeline.close();\n documentRuntime.dispose();\n },\n };\n return Object.freeze(localDocument);\n } catch (error) {\n channel?.close();\n runtime?.dispose();\n timeline.close();\n throw error;\n }\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"local-sync.cjs","names":["isPlainObject","positiveInteger","isRecord","installRuntimeWriteDriver"],"sources":["../core/src/local-sync/contract.ts","../core/src/local-sync/json.ts","../core/src/local-sync/timeline.ts","../core/src/local-sync/session.ts"],"sourcesContent":["import type { DocumentSchema } from '../schema';\nimport type { DocumentRuntime } from '../runtime/contract';\nimport type { JsonCommandLimits } from './json';\n\nexport class LocalSyncUnavailableError extends Error {\n constructor(capability: 'IndexedDB' | 'Web Locks' | 'BroadcastChannel') {\n super(`${capability} is required by doxum/local-sync in this environment.`);\n this.name = 'LocalSyncUnavailableError';\n }\n}\n\nexport class LocalSyncSchemaError extends Error {\n constructor(documentId: string, expected: number, actual: number) {\n super(\n `Local document '${documentId}' uses schema version ${actual}, but version ${expected} was requested.`\n );\n this.name = 'LocalSyncSchemaError';\n }\n}\n\nexport class LocalSyncConsistencyError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'LocalSyncConsistencyError';\n }\n}\n\nexport class LocalSyncReadOnlyError extends Error {\n constructor() {\n super('This tab is following the local document and cannot write until it becomes the leader.');\n this.name = 'LocalSyncReadOnlyError';\n }\n}\n\nexport class LocalSyncUnsupportedOperationError extends Error {\n constructor() {\n super(\n 'Local sync persists operation commands. runtime.replace() and externally supplied remote operations are unavailable while it is attached.'\n );\n this.name = 'LocalSyncUnsupportedOperationError';\n }\n}\n\nexport class LocalSyncDisposedError extends Error {\n constructor() {\n super('Local sync has been disposed.');\n this.name = 'LocalSyncDisposedError';\n }\n}\n\nexport type LocalSyncState =\n | {\n readonly status: 'leader' | 'follower';\n readonly headSeq: number;\n readonly checkpointSeq: number;\n }\n | {\n readonly status: 'error';\n readonly headSeq: number;\n readonly checkpointSeq: number;\n readonly error: unknown;\n }\n | { readonly status: 'disposed' };\n\nexport type LocalSync = {\n state(): LocalSyncState;\n flush(): Promise<void>;\n dispose(): Promise<void>;\n};\n\nexport type AttachLocalSyncOptions<TSchema extends DocumentSchema> = {\n readonly runtime: DocumentRuntime<TSchema>;\n readonly database: string;\n readonly documentId: string;\n readonly schemaVersion?: number;\n readonly commandLimits?: JsonCommandLimits;\n readonly onError?: (error: unknown) => void;\n};\n","import { isPlainObject } from '../value/ownership';\n\nexport type JsonPrimitive = null | boolean | number | string;\nexport type JsonValue =\n JsonPrimitive | readonly JsonValue[] | { readonly [key: string]: JsonValue };\n\nexport type JsonCommandLimits = {\n readonly maxOperations?: number;\n readonly maxBytes?: number;\n readonly maxDepth?: number;\n readonly maxStringLength?: number;\n};\n\ntype ResolvedJsonLimits = {\n readonly maxOperations: number;\n readonly maxBytes: number;\n readonly maxDepth: number;\n readonly maxStringLength: number;\n};\n\nexport const defaultJsonCommandLimits: Readonly<ResolvedJsonLimits> = Object.freeze({\n maxOperations: 1_000,\n maxBytes: 1_000_000,\n maxDepth: 64,\n maxStringLength: 256_000,\n});\n\nexport class LocalSyncDataError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'LocalSyncDataError';\n }\n}\n\nconst describePath = (path: readonly string[]): string =>\n path.length === 0 ? 'value' : path.join('.');\n\nconst limit = (value: number | undefined, fallback: number, label: string): number => {\n if (value === undefined) return fallback;\n if (Number.isSafeInteger(value) && value > 0) return value;\n throw new TypeError(`${label} must be a positive safe integer.`);\n};\n\nconst resolveLimits = (input: JsonCommandLimits | undefined): ResolvedJsonLimits => ({\n maxOperations: limit(\n input?.maxOperations,\n defaultJsonCommandLimits.maxOperations,\n 'maxOperations'\n ),\n maxBytes: limit(input?.maxBytes, defaultJsonCommandLimits.maxBytes, 'maxBytes'),\n maxDepth: limit(input?.maxDepth, defaultJsonCommandLimits.maxDepth, 'maxDepth'),\n maxStringLength: limit(\n input?.maxStringLength,\n defaultJsonCommandLimits.maxStringLength,\n 'maxStringLength'\n ),\n});\n\nconst validate = (\n value: unknown,\n path: readonly string[],\n limits: ResolvedJsonLimits | undefined,\n depth: number,\n ancestors: WeakSet<object>\n): JsonValue => {\n if (limits && depth > limits.maxDepth)\n throw new LocalSyncDataError(`${describePath(path)} exceeds the maximum JSON depth.`);\n if (value === null || typeof value === 'boolean') return value;\n if (typeof value === 'string') {\n if (!limits || value.length <= limits.maxStringLength) return value;\n throw new LocalSyncDataError(`${describePath(path)} exceeds the maximum string length.`);\n }\n if (typeof value === 'number') {\n if (Number.isFinite(value)) return value;\n throw new LocalSyncDataError(`${describePath(path)} contains a non-finite number.`);\n }\n if (Array.isArray(value)) {\n if (ancestors.has(value))\n throw new LocalSyncDataError(`${describePath(path)} contains a cycle.`);\n ancestors.add(value);\n try {\n for (let index = 0; index < value.length; index += 1)\n validate(value[index], [...path, String(index)], limits, depth + 1, ancestors);\n } finally {\n ancestors.delete(value);\n }\n return value as readonly JsonValue[];\n }\n if (isPlainObject(value)) {\n if (ancestors.has(value))\n throw new LocalSyncDataError(`${describePath(path)} contains a cycle.`);\n ancestors.add(value);\n try {\n for (const [key, entry] of Object.entries(value))\n validate(entry, [...path, key], limits, depth + 1, ancestors);\n } finally {\n ancestors.delete(value);\n }\n return value as { readonly [key: string]: JsonValue };\n }\n throw new LocalSyncDataError(`${describePath(path)} must be JSON data.`);\n};\n\nexport const json = (value: unknown, label: string): JsonValue =>\n validate(value, [label], undefined, 0, new WeakSet());\n\nexport const jsonArray = (\n value: unknown,\n label: string,\n input?: JsonCommandLimits\n): readonly JsonValue[] => {\n const limits = resolveLimits(input);\n const parsed = validate(value, [label], limits, 0, new WeakSet());\n if (!Array.isArray(parsed)) throw new LocalSyncDataError(`${label} must be a JSON array.`);\n if (parsed.length > limits.maxOperations)\n throw new LocalSyncDataError(`${label} exceeds the maximum operation count.`);\n const serialized = JSON.stringify(parsed);\n if (new TextEncoder().encode(serialized).byteLength > limits.maxBytes)\n throw new LocalSyncDataError(`${label} exceeds the maximum command size.`);\n return parsed;\n};\n","import {\n LocalSyncConsistencyError,\n LocalSyncSchemaError,\n LocalSyncUnavailableError,\n} from './contract';\nimport { json, jsonArray, type JsonValue } from './json';\nimport { isRecord } from '../value/ownership';\n\nconst DATABASE_VERSION = 2;\nconst DOCUMENTS = 'documents';\nconst COMMITS = 'commits';\nconst ACTORS = 'actors';\n\nexport type StoredDocument = {\n readonly documentId: string;\n readonly schemaVersion: number;\n readonly checkpointSeq: number;\n readonly headSeq: number;\n readonly checkpoint: JsonValue;\n};\n\nexport type StoredCommit = {\n readonly documentId: string;\n readonly seq: number;\n readonly operations: readonly JsonValue[];\n readonly createdAt: number;\n};\n\nconst request = <T>(value: IDBRequest<T>): Promise<T> =>\n new Promise((resolve, reject) => {\n value.onsuccess = () => resolve(value.result);\n value.onerror = () => reject(value.error ?? new Error('IndexedDB request failed.'));\n });\n\nconst complete = (transaction: IDBTransaction): Promise<void> =>\n new Promise((resolve, reject) => {\n transaction.oncomplete = () => resolve();\n transaction.onabort = () =>\n reject(transaction.error ?? new Error('IndexedDB transaction was aborted.'));\n transaction.onerror = () =>\n reject(transaction.error ?? new Error('IndexedDB transaction failed.'));\n });\n\nconst factory = (): IDBFactory => {\n if (!globalThis.indexedDB) throw new LocalSyncUnavailableError('IndexedDB');\n return globalThis.indexedDB;\n};\n\nconst keyRange = (): typeof IDBKeyRange => {\n if (!globalThis.IDBKeyRange) throw new LocalSyncUnavailableError('IndexedDB');\n return globalThis.IDBKeyRange;\n};\n\nconst string = (value: unknown, label: string): string => {\n if (typeof value === 'string') return value;\n throw new LocalSyncConsistencyError(`${label} is malformed in IndexedDB.`);\n};\n\nconst nonNegativeInteger = (value: unknown, label: string): number => {\n if (typeof value === 'number' && Number.isSafeInteger(value) && value >= 0) return value;\n throw new LocalSyncConsistencyError(`${label} is malformed in IndexedDB.`);\n};\n\nconst positiveInteger = (value: unknown, label: string): number => {\n const parsed = nonNegativeInteger(value, label);\n if (parsed > 0) return parsed;\n throw new LocalSyncConsistencyError(`${label} is malformed in IndexedDB.`);\n};\n\nconst documentRecord = (value: unknown): StoredDocument => {\n if (!isRecord(value))\n throw new LocalSyncConsistencyError('Document record is malformed in IndexedDB.');\n const checkpointSeq = nonNegativeInteger(value.checkpointSeq, 'document.checkpointSeq');\n const headSeq = nonNegativeInteger(value.headSeq, 'document.headSeq');\n if (checkpointSeq > headSeq)\n throw new LocalSyncConsistencyError('Document checkpoint exceeds its head sequence.');\n return Object.freeze({\n documentId: string(value.documentId, 'document.documentId'),\n schemaVersion: positiveInteger(value.schemaVersion, 'document.schemaVersion'),\n checkpointSeq,\n headSeq,\n checkpoint: json(value.checkpoint, 'document.checkpoint'),\n });\n};\n\nconst commitRecord = (value: unknown): StoredCommit => {\n if (!isRecord(value))\n throw new LocalSyncConsistencyError('Commit record is malformed in IndexedDB.');\n return Object.freeze({\n documentId: string(value.documentId, 'commit.documentId'),\n seq: positiveInteger(value.seq, 'commit.seq'),\n operations: jsonArray(value.operations, 'commit.operations'),\n createdAt: nonNegativeInteger(value.createdAt, 'commit.createdAt'),\n });\n};\n\nexport type IndexedDbTimeline = {\n readonly initialize: (\n documentId: string,\n schemaVersion: number,\n checkpoint: JsonValue\n ) => Promise<StoredDocument>;\n readonly read: (documentId: string) => Promise<StoredDocument>;\n readonly tail: (documentId: string, afterSeq: number) => Promise<readonly StoredCommit[]>;\n readonly append: (input: {\n readonly documentId: string;\n readonly expectedHeadSeq: number;\n readonly operations: readonly JsonValue[];\n }) => Promise<StoredCommit>;\n readonly close: () => void;\n};\n\nexport const openIndexedDbTimeline = async (databaseName: string): Promise<IndexedDbTimeline> => {\n const database = await new Promise<IDBDatabase>((resolve, reject) => {\n const open = factory().open(databaseName, DATABASE_VERSION);\n open.onerror = () => reject(open.error ?? new Error('Unable to open IndexedDB.'));\n open.onblocked = () => reject(new Error(`IndexedDB database '${databaseName}' is blocked.`));\n open.onupgradeneeded = () => {\n const db = open.result;\n if (!db.objectStoreNames.contains(DOCUMENTS))\n db.createObjectStore(DOCUMENTS, { keyPath: 'documentId' });\n if (!db.objectStoreNames.contains(COMMITS))\n db.createObjectStore(COMMITS, { keyPath: ['documentId', 'seq'] });\n if (db.objectStoreNames.contains(ACTORS)) db.deleteObjectStore(ACTORS);\n };\n open.onsuccess = () => resolve(open.result);\n });\n\n const readDocument = async (\n transaction: IDBTransaction,\n documentId: string\n ): Promise<StoredDocument> => {\n const value = await request(transaction.objectStore(DOCUMENTS).get(documentId));\n if (value === undefined)\n throw new LocalSyncConsistencyError(`Local document '${documentId}' does not exist.`);\n return documentRecord(value);\n };\n\n return {\n initialize: async (documentId, schemaVersion, checkpoint) => {\n const transaction = database.transaction(DOCUMENTS, 'readwrite');\n const store = transaction.objectStore(DOCUMENTS);\n const existing = await request(store.get(documentId));\n if (existing !== undefined) {\n const record = documentRecord(existing);\n if (record.schemaVersion !== schemaVersion)\n throw new LocalSyncSchemaError(documentId, schemaVersion, record.schemaVersion);\n await complete(transaction);\n return record;\n }\n const record: StoredDocument = {\n documentId,\n schemaVersion,\n checkpointSeq: 0,\n headSeq: 0,\n checkpoint,\n };\n store.put(record);\n await complete(transaction);\n return Object.freeze(record);\n },\n read: async documentId => {\n const transaction = database.transaction(DOCUMENTS, 'readonly');\n const record = await readDocument(transaction, documentId);\n await complete(transaction);\n return record;\n },\n tail: async (documentId, afterSeq) => {\n const transaction = database.transaction(COMMITS, 'readonly');\n const range = keyRange().bound(\n [documentId, afterSeq + 1],\n [documentId, Number.MAX_SAFE_INTEGER]\n );\n const values = await request(transaction.objectStore(COMMITS).getAll(range));\n await complete(transaction);\n return Object.freeze(values.map(commitRecord).sort((left, right) => left.seq - right.seq));\n },\n append: async input => {\n const transaction = database.transaction([DOCUMENTS, COMMITS], 'readwrite');\n const documents = transaction.objectStore(DOCUMENTS);\n const current = await readDocument(transaction, input.documentId);\n if (current.headSeq !== input.expectedHeadSeq)\n throw new LocalSyncConsistencyError(\n 'Local document advanced before the leader could append its command.'\n );\n const commit: StoredCommit = {\n documentId: input.documentId,\n seq: current.headSeq + 1,\n operations: input.operations,\n createdAt: Date.now(),\n };\n documents.put({ ...current, headSeq: commit.seq });\n transaction.objectStore(COMMITS).put(commit);\n await complete(transaction);\n return Object.freeze(commit);\n },\n close: () => database.close(),\n };\n};\n","import {\n installRuntimeWriteDriver,\n type RuntimeWriteDriverLease,\n type RuntimeWriteIntent,\n} from '../runtime/driver';\nimport type { DocumentCommit, DocumentRuntime, OperationResult } from '../runtime/contract';\nimport type { DocumentSchema, ReadonlyDocument } from '../schema';\nimport {\n LocalSyncConsistencyError,\n LocalSyncDisposedError,\n LocalSyncReadOnlyError,\n LocalSyncUnsupportedOperationError,\n LocalSyncUnavailableError,\n type AttachLocalSyncOptions,\n type LocalSync,\n type LocalSyncState,\n} from './contract';\nimport { json, jsonArray, type JsonValue } from './json';\nimport { openIndexedDbTimeline, type StoredCommit } from './timeline';\n\ntype LockOptions = {\n readonly mode: 'exclusive';\n readonly ifAvailable?: boolean;\n};\n\ntype LockManager = {\n readonly request: <TResult>(\n name: string,\n options: LockOptions,\n callback: (lock: unknown | null) => TResult | PromiseLike<TResult>\n ) => Promise<TResult>;\n};\n\ntype Channel = {\n onmessage: ((event: MessageEvent<unknown>) => void) | null;\n postMessage(message: unknown): void;\n close(): void;\n};\n\ntype ChannelConstructor = new (name: string) => Channel;\n\ntype CommitNotification = {\n readonly kind: 'commit';\n readonly documentId: string;\n readonly headSeq: number;\n};\n\nconst locks = (): LockManager => {\n const value: unknown = globalThis.navigator?.locks;\n if (\n typeof value !== 'object' ||\n value === null ||\n !('request' in value) ||\n typeof value.request !== 'function'\n )\n throw new LocalSyncUnavailableError('Web Locks');\n return value as LockManager;\n};\n\nconst channelConstructor = (): ChannelConstructor => {\n const value: unknown = globalThis.BroadcastChannel;\n if (typeof value !== 'function') throw new LocalSyncUnavailableError('BroadcastChannel');\n return value as ChannelConstructor;\n};\n\nconst requiredString = (value: string, label: string): string => {\n if (value.length > 0) return value;\n throw new TypeError(`${label} must not be empty.`);\n};\n\nconst positiveInteger = (value: number, label: string): number => {\n if (Number.isSafeInteger(value) && value > 0) return value;\n throw new TypeError(`${label} must be a positive safe integer.`);\n};\n\nconst notification = (value: unknown): CommitNotification | undefined => {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined;\n const record = value as Record<string, unknown>;\n if (\n record.kind !== 'commit' ||\n typeof record.documentId !== 'string' ||\n typeof record.headSeq !== 'number' ||\n !Number.isSafeInteger(record.headSeq) ||\n record.headSeq < 0\n )\n return undefined;\n return record as CommitNotification;\n};\n\nexport const attachLocalSync = async <TSchema extends DocumentSchema>(\n input: AttachLocalSyncOptions<TSchema>\n): Promise<LocalSync> => {\n const runtime = input.runtime;\n const databaseName = requiredString(input.database, 'database');\n const documentId = requiredString(input.documentId, 'documentId');\n const schemaVersion = positiveInteger(input.schemaVersion ?? 1, 'schemaVersion');\n const lockManager = locks();\n const BroadcastChannel = channelConstructor();\n const timeline = await openIndexedDbTimeline(databaseName);\n\n let channel: Channel | undefined;\n let unsubscribe: (() => void) | undefined;\n let driver: RuntimeWriteDriverLease | undefined;\n try {\n const stored = await timeline.initialize(\n documentId,\n schemaVersion,\n json(runtime.snapshot(), 'runtime snapshot')\n );\n let headSeq = stored.checkpointSeq;\n let checkpointSeq = stored.checkpointSeq;\n let role: 'leader' | 'follower' = 'follower';\n let fault: unknown;\n let closing = false;\n let disposed = false;\n let releaseLeadership: (() => void) | undefined;\n let leadershipLease: Promise<void> | undefined;\n let queued: Promise<void> = Promise.resolve();\n\n const fail = (error: unknown): void => {\n if (fault || disposed) return;\n fault = error;\n try {\n input.onError?.(error);\n } catch {\n // Error reporting cannot repair or replace the original synchronization failure.\n }\n };\n\n const assertOpen = (): void => {\n if (closing || disposed) throw new LocalSyncDisposedError();\n if (fault) throw fault;\n };\n\n const assertLeader = (intent: RuntimeWriteIntent): void => {\n assertOpen();\n if (role !== 'leader') throw new LocalSyncReadOnlyError();\n if (intent.kind === 'replace' || (intent.kind === 'apply' && intent.source === 'remote'))\n throw new LocalSyncUnsupportedOperationError();\n };\n\n const runRuntime = <TResult>(run: () => TResult): TResult => driver?.run(run) ?? run();\n\n const applyStored = (commit: StoredCommit): void => {\n if (commit.seq !== headSeq + 1)\n throw new LocalSyncConsistencyError('Local commit log contains a sequence gap.');\n const result = runRuntime(() =>\n runtime.apply(commit.operations, { source: 'remote', history: false })\n );\n if (result.status !== 'committed')\n throw new LocalSyncConsistencyError('A stored local command could not be applied.');\n headSeq = commit.seq;\n };\n\n const restore = async (reset = false): Promise<void> => {\n const current = await timeline.read(documentId);\n if (current.schemaVersion !== schemaVersion)\n throw new LocalSyncConsistencyError(\n 'Local document schema changed while this attachment was open.'\n );\n if (headSeq > current.headSeq)\n throw new LocalSyncConsistencyError('The local timeline moved behind this attachment.');\n if (reset || headSeq < current.checkpointSeq) {\n const result = runRuntime(() =>\n runtime.replace(current.checkpoint as ReadonlyDocument<TSchema>, { source: 'remote' })\n );\n if (result.status === 'rejected')\n throw new LocalSyncConsistencyError('The local checkpoint could not be restored.');\n headSeq = current.checkpointSeq;\n }\n const tail = await timeline.tail(documentId, headSeq);\n for (const commit of tail) applyStored(commit);\n if (headSeq !== current.headSeq)\n throw new LocalSyncConsistencyError(\n 'Local commit log does not reach its recorded head sequence.'\n );\n checkpointSeq = current.checkpointSeq;\n };\n\n const enqueue = (run: () => Promise<void>): Promise<void> => {\n const next = queued.then(run, run);\n queued = next.then(\n () => undefined,\n error => {\n fail(error);\n }\n );\n return next;\n };\n\n const persist = async (operations: readonly JsonValue[]): Promise<void> => {\n const storedCommit = await timeline.append({\n documentId,\n expectedHeadSeq: headSeq,\n operations,\n });\n if (storedCommit.seq !== headSeq + 1)\n throw new LocalSyncConsistencyError('A local command was assigned an unexpected sequence.');\n headSeq = storedCommit.seq;\n channel?.postMessage({\n kind: 'commit',\n documentId,\n headSeq,\n } satisfies CommitNotification);\n };\n\n const record = (commit: DocumentCommit<TSchema>): void => {\n try {\n const operations = jsonArray(\n commit.operations,\n 'local command operations',\n input.commandLimits\n );\n void enqueue(() => persist(operations)).catch(() => undefined);\n } catch (error) {\n fail(error);\n }\n };\n\n const holdLeadership = (): Promise<void> =>\n new Promise(resolve => {\n releaseLeadership = resolve;\n });\n\n const lead = async (activated?: () => void): Promise<void> => {\n if (closing || disposed || fault) return;\n await restore();\n if (closing || disposed || fault) return;\n role = 'leader';\n activated?.();\n try {\n await holdLeadership();\n } finally {\n releaseLeadership = undefined;\n if (!closing && !disposed && !fault) role = 'follower';\n }\n };\n\n const watchLeadership = (): void => {\n leadershipLease = lockManager\n .request(`doxum:${documentId}`, { mode: 'exclusive' }, async () => {\n try {\n await lead();\n } catch (error) {\n fail(error);\n }\n })\n .catch(error => {\n if (!closing && !disposed) fail(error);\n });\n };\n\n const claimInitialLeadership = async (): Promise<void> => {\n let resolve!: (value: boolean) => void;\n const claimed = new Promise<boolean>(done => {\n resolve = done;\n });\n leadershipLease = lockManager\n .request(`doxum:${documentId}`, { mode: 'exclusive', ifAvailable: true }, async lock => {\n if (lock === null) {\n resolve(false);\n return;\n }\n try {\n await lead(() => resolve(true));\n } catch (error) {\n fail(error);\n resolve(false);\n }\n })\n .catch(error => {\n if (!closing && !disposed) fail(error);\n resolve(false);\n });\n if (!(await claimed) && !fault && !closing && !disposed) watchLeadership();\n };\n\n await restore(true);\n // The timeline, not a runtime constructed before attachment, is the baseline\n // for local undo. Even an identical restored snapshot must discard prior history.\n runtime.history.clear();\n driver = installRuntimeWriteDriver(runtime, { assertWritable: assertLeader });\n channel = new BroadcastChannel(`doxum:${databaseName}:${documentId}`);\n unsubscribe = runtime.subscribe(commit => {\n if (\n (commit.source === 'local' || commit.source === 'system' || commit.source === 'history') &&\n !closing &&\n !disposed\n )\n record(commit);\n });\n channel.onmessage = event => {\n const message = notification(event.data);\n if (\n !message ||\n message.documentId !== documentId ||\n message.headSeq <= headSeq ||\n closing ||\n disposed ||\n fault\n )\n return;\n void enqueue(restore).catch(() => undefined);\n };\n await claimInitialLeadership();\n if (fault) throw fault;\n\n const localSync: LocalSync = {\n state: (): LocalSyncState => {\n if (disposed) return { status: 'disposed' };\n if (fault) return { status: 'error', headSeq, checkpointSeq, error: fault };\n return { status: role, headSeq, checkpointSeq };\n },\n flush: async (): Promise<void> => {\n assertOpen();\n try {\n await enqueue(restore);\n } catch (error) {\n fail(error);\n throw error;\n }\n assertOpen();\n },\n dispose: async (): Promise<void> => {\n if (disposed) return;\n if (closing) {\n await queued;\n return;\n }\n closing = true;\n unsubscribe?.();\n await queued;\n releaseLeadership?.();\n if (role === 'leader') await leadershipLease;\n disposed = true;\n driver?.dispose();\n channel?.close();\n timeline.close();\n },\n };\n return Object.freeze(localSync);\n } catch (error) {\n unsubscribe?.();\n driver?.dispose();\n channel?.close();\n timeline.close();\n throw error;\n }\n};\n"],"mappings":"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"}
|
package/dist/local-sync.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as DocumentRuntime, xt as DocumentSchema } from "./contract-D8kjdfqT.cjs";
|
|
2
2
|
|
|
3
3
|
//#region core/src/local-sync/json.d.ts
|
|
4
4
|
type JsonPrimitive = null | boolean | number | string;
|
|
@@ -32,48 +32,43 @@ declare class LocalSyncSchemaError extends Error {
|
|
|
32
32
|
declare class LocalSyncConsistencyError extends Error {
|
|
33
33
|
constructor(message: string);
|
|
34
34
|
}
|
|
35
|
+
declare class LocalSyncReadOnlyError extends Error {
|
|
36
|
+
constructor();
|
|
37
|
+
}
|
|
38
|
+
declare class LocalSyncUnsupportedOperationError extends Error {
|
|
39
|
+
constructor();
|
|
40
|
+
}
|
|
35
41
|
declare class LocalSyncDisposedError extends Error {
|
|
36
42
|
constructor();
|
|
37
43
|
}
|
|
38
|
-
type LocalSyncCommit<TSchema extends DocumentSchema> = DocumentCommit<TSchema> & {
|
|
39
|
-
readonly seq: number;
|
|
40
|
-
readonly commandId: string;
|
|
41
|
-
readonly actorId: string;
|
|
42
|
-
};
|
|
43
44
|
type LocalSyncState = {
|
|
44
|
-
readonly status: '
|
|
45
|
+
readonly status: 'leader' | 'follower';
|
|
45
46
|
readonly headSeq: number;
|
|
46
47
|
readonly checkpointSeq: number;
|
|
47
48
|
} | {
|
|
48
|
-
readonly status: '
|
|
49
|
+
readonly status: 'error';
|
|
50
|
+
readonly headSeq: number;
|
|
51
|
+
readonly checkpointSeq: number;
|
|
49
52
|
readonly error: unknown;
|
|
50
53
|
} | {
|
|
51
54
|
readonly status: 'disposed';
|
|
52
55
|
};
|
|
53
|
-
type
|
|
54
|
-
readonly document: DocumentReadable<TSchema>;
|
|
56
|
+
type LocalSync = {
|
|
55
57
|
state(): LocalSyncState;
|
|
56
|
-
|
|
57
|
-
update<TResult>(run: (transaction: DocumentTransaction<TSchema>) => TResult): Promise<TransactionResult<TResult, LocalSyncCommit<TSchema>>>;
|
|
58
|
-
undo(): Promise<OperationResult<LocalSyncCommit<TSchema>>>;
|
|
59
|
-
redo(): Promise<OperationResult<LocalSyncCommit<TSchema>>>;
|
|
58
|
+
flush(): Promise<void>;
|
|
60
59
|
dispose(): Promise<void>;
|
|
61
60
|
};
|
|
62
|
-
type
|
|
61
|
+
type AttachLocalSyncOptions<TSchema extends DocumentSchema> = {
|
|
62
|
+
readonly runtime: DocumentRuntime<TSchema>;
|
|
63
63
|
readonly database: string;
|
|
64
64
|
readonly documentId: string;
|
|
65
|
-
readonly schema: TSchema;
|
|
66
|
-
readonly initial: ReadonlyDocument<TSchema>;
|
|
67
65
|
readonly schemaVersion?: number;
|
|
68
|
-
readonly actorId?: string;
|
|
69
|
-
readonly historyCapacity?: number;
|
|
70
|
-
readonly checkpointEvery?: number;
|
|
71
66
|
readonly commandLimits?: JsonCommandLimits;
|
|
72
67
|
readonly onError?: (error: unknown) => void;
|
|
73
68
|
};
|
|
74
69
|
//#endregion
|
|
75
70
|
//#region core/src/local-sync/session.d.ts
|
|
76
|
-
declare const
|
|
71
|
+
declare const attachLocalSync: <TSchema extends DocumentSchema>(input: AttachLocalSyncOptions<TSchema>) => Promise<LocalSync>;
|
|
77
72
|
//#endregion
|
|
78
|
-
export { type JsonCommandLimits, type JsonPrimitive, type JsonValue, type
|
|
73
|
+
export { type AttachLocalSyncOptions, type JsonCommandLimits, type JsonPrimitive, type JsonValue, type LocalSync, LocalSyncConsistencyError, LocalSyncDataError, LocalSyncDisposedError, LocalSyncReadOnlyError, LocalSyncSchemaError, type LocalSyncState, LocalSyncUnavailableError, LocalSyncUnsupportedOperationError, attachLocalSync, defaultJsonCommandLimits };
|
|
79
74
|
//# sourceMappingURL=local-sync.d.cts.map
|
package/dist/local-sync.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as DocumentRuntime, xt as DocumentSchema } from "./contract-BsY1XLiG.js";
|
|
2
2
|
|
|
3
3
|
//#region core/src/local-sync/json.d.ts
|
|
4
4
|
type JsonPrimitive = null | boolean | number | string;
|
|
@@ -32,48 +32,43 @@ declare class LocalSyncSchemaError extends Error {
|
|
|
32
32
|
declare class LocalSyncConsistencyError extends Error {
|
|
33
33
|
constructor(message: string);
|
|
34
34
|
}
|
|
35
|
+
declare class LocalSyncReadOnlyError extends Error {
|
|
36
|
+
constructor();
|
|
37
|
+
}
|
|
38
|
+
declare class LocalSyncUnsupportedOperationError extends Error {
|
|
39
|
+
constructor();
|
|
40
|
+
}
|
|
35
41
|
declare class LocalSyncDisposedError extends Error {
|
|
36
42
|
constructor();
|
|
37
43
|
}
|
|
38
|
-
type LocalSyncCommit<TSchema extends DocumentSchema> = DocumentCommit<TSchema> & {
|
|
39
|
-
readonly seq: number;
|
|
40
|
-
readonly commandId: string;
|
|
41
|
-
readonly actorId: string;
|
|
42
|
-
};
|
|
43
44
|
type LocalSyncState = {
|
|
44
|
-
readonly status: '
|
|
45
|
+
readonly status: 'leader' | 'follower';
|
|
45
46
|
readonly headSeq: number;
|
|
46
47
|
readonly checkpointSeq: number;
|
|
47
48
|
} | {
|
|
48
|
-
readonly status: '
|
|
49
|
+
readonly status: 'error';
|
|
50
|
+
readonly headSeq: number;
|
|
51
|
+
readonly checkpointSeq: number;
|
|
49
52
|
readonly error: unknown;
|
|
50
53
|
} | {
|
|
51
54
|
readonly status: 'disposed';
|
|
52
55
|
};
|
|
53
|
-
type
|
|
54
|
-
readonly document: DocumentReadable<TSchema>;
|
|
56
|
+
type LocalSync = {
|
|
55
57
|
state(): LocalSyncState;
|
|
56
|
-
|
|
57
|
-
update<TResult>(run: (transaction: DocumentTransaction<TSchema>) => TResult): Promise<TransactionResult<TResult, LocalSyncCommit<TSchema>>>;
|
|
58
|
-
undo(): Promise<OperationResult<LocalSyncCommit<TSchema>>>;
|
|
59
|
-
redo(): Promise<OperationResult<LocalSyncCommit<TSchema>>>;
|
|
58
|
+
flush(): Promise<void>;
|
|
60
59
|
dispose(): Promise<void>;
|
|
61
60
|
};
|
|
62
|
-
type
|
|
61
|
+
type AttachLocalSyncOptions<TSchema extends DocumentSchema> = {
|
|
62
|
+
readonly runtime: DocumentRuntime<TSchema>;
|
|
63
63
|
readonly database: string;
|
|
64
64
|
readonly documentId: string;
|
|
65
|
-
readonly schema: TSchema;
|
|
66
|
-
readonly initial: ReadonlyDocument<TSchema>;
|
|
67
65
|
readonly schemaVersion?: number;
|
|
68
|
-
readonly actorId?: string;
|
|
69
|
-
readonly historyCapacity?: number;
|
|
70
|
-
readonly checkpointEvery?: number;
|
|
71
66
|
readonly commandLimits?: JsonCommandLimits;
|
|
72
67
|
readonly onError?: (error: unknown) => void;
|
|
73
68
|
};
|
|
74
69
|
//#endregion
|
|
75
70
|
//#region core/src/local-sync/session.d.ts
|
|
76
|
-
declare const
|
|
71
|
+
declare const attachLocalSync: <TSchema extends DocumentSchema>(input: AttachLocalSyncOptions<TSchema>) => Promise<LocalSync>;
|
|
77
72
|
//#endregion
|
|
78
|
-
export { type JsonCommandLimits, type JsonPrimitive, type JsonValue, type
|
|
73
|
+
export { type AttachLocalSyncOptions, type JsonCommandLimits, type JsonPrimitive, type JsonValue, type LocalSync, LocalSyncConsistencyError, LocalSyncDataError, LocalSyncDisposedError, LocalSyncReadOnlyError, LocalSyncSchemaError, type LocalSyncState, LocalSyncUnavailableError, LocalSyncUnsupportedOperationError, attachLocalSync, defaultJsonCommandLimits };
|
|
79
74
|
//# sourceMappingURL=local-sync.d.ts.map
|