@bendyline/docblocks 2.0.0 → 2.1.0
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/dist/{chunk-J32GU3F3.js → chunk-6IYMTYMQ.js} +249 -221
- package/dist/chunk-6IYMTYMQ.js.map +1 -0
- package/dist/{chunk-75UUF6C4.js → chunk-B56KWCSE.js} +2 -2
- package/dist/{chunk-RVQHY3XU.js → chunk-BNKV7MTO.js} +1 -1
- package/dist/{chunk-RVQHY3XU.js.map → chunk-BNKV7MTO.js.map} +1 -1
- package/dist/chunk-BXMF5YQJ.js +149 -0
- package/dist/chunk-BXMF5YQJ.js.map +1 -0
- package/dist/{chunk-PGR7LK6D.js → chunk-COYQXQK3.js} +14 -5
- package/dist/chunk-COYQXQK3.js.map +1 -0
- package/dist/{chunk-RQJRQF46.js → chunk-DN7A33LL.js} +42 -49
- package/dist/chunk-DN7A33LL.js.map +1 -0
- package/dist/chunk-FA7UNOXK.js +20 -0
- package/dist/chunk-FA7UNOXK.js.map +1 -0
- package/dist/chunk-GM5YXU4L.js +29 -0
- package/dist/chunk-GM5YXU4L.js.map +1 -0
- package/dist/{chunk-SI2LU2RP.js → chunk-JS6XFWQK.js} +2 -1
- package/dist/chunk-JS6XFWQK.js.map +1 -0
- package/dist/{chunk-EGNDADXB.js → chunk-MNSZ7EZN.js} +2 -2
- package/dist/chunk-P3DVZQ6S.js +228 -0
- package/dist/chunk-P3DVZQ6S.js.map +1 -0
- package/dist/chunk-P4WATND4.js +52 -0
- package/dist/chunk-P4WATND4.js.map +1 -0
- package/dist/chunk-RVPGQBWR.js +169 -0
- package/dist/chunk-RVPGQBWR.js.map +1 -0
- package/dist/chunk-U722UUFN.js +9 -0
- package/dist/chunk-U722UUFN.js.map +1 -0
- package/dist/{chunk-GCPBEMMH.js → chunk-VTCSF7VS.js} +11 -21
- package/dist/chunk-VTCSF7VS.js.map +1 -0
- package/dist/{chunk-2D7Y4IR3.js → chunk-WJKYY5QR.js} +123 -66
- package/dist/chunk-WJKYY5QR.js.map +1 -0
- package/dist/{chunk-5MYAICRE.js → chunk-XUML3MKV.js} +44 -56
- package/dist/chunk-XUML3MKV.js.map +1 -0
- package/dist/document/index.d.ts +358 -6
- package/dist/document/index.js +24 -3
- package/dist/document/index.js.map +1 -1
- package/dist/filesystem/electron.d.ts +73 -4
- package/dist/filesystem/electron.js +16 -3
- package/dist/filesystem/electron.js.map +1 -1
- package/dist/filesystem/index.d.ts +228 -22
- package/dist/filesystem/index.js +133 -19
- package/dist/filesystem/index.js.map +1 -1
- package/dist/filesystem/indexeddb.d.ts +284 -5
- package/dist/filesystem/indexeddb.js +22 -4
- package/dist/filesystem/indexeddb.js.map +1 -1
- package/dist/filesystem/memory.d.ts +152 -4
- package/dist/filesystem/memory.js +12 -3
- package/dist/filesystem/memory.js.map +1 -1
- package/dist/filesystem/native.d.ts +136 -4
- package/dist/filesystem/native.js +27 -3
- package/dist/filesystem/native.js.map +1 -1
- package/dist/host/index.d.ts +32 -9
- package/dist/host/index.js +26 -29
- package/dist/host/index.js.map +1 -1
- package/dist/index.d.ts +14 -10
- package/dist/index.js +204 -9
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.d.ts +33 -4
- package/dist/mcp/index.js +31 -3
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/zod.d.ts +637 -635
- package/dist/mcp/zod.js +700 -884
- package/dist/mcp/zod.js.map +1 -1
- package/dist/share/index.d.ts +43 -0
- package/dist/share/index.js +13 -0
- package/dist/share/index.js.map +1 -0
- package/dist/{types-CsX6EN2t.d.ts → types-BEg5SQ1_.d.ts} +1 -1
- package/dist/{types-eOlt9J7n.d.ts → types-CueK0tvU.d.ts} +34 -11
- package/dist/vscode/index.d.ts +220 -3
- package/dist/vscode/index.js +382 -2
- package/dist/vscode/index.js.map +1 -1
- package/dist/workspace/index.d.ts +141 -4
- package/dist/workspace/index.js +28 -2
- package/dist/workspace/index.js.map +1 -1
- package/package.json +9 -5
- package/dist/chunk-2D7Y4IR3.js.map +0 -1
- package/dist/chunk-5MYAICRE.js.map +0 -1
- package/dist/chunk-AYZ4HN5M.js +0 -20
- package/dist/chunk-AYZ4HN5M.js.map +0 -1
- package/dist/chunk-GCPBEMMH.js.map +0 -1
- package/dist/chunk-J32GU3F3.js.map +0 -1
- package/dist/chunk-PGR7LK6D.js.map +0 -1
- package/dist/chunk-RQJRQF46.js.map +0 -1
- package/dist/chunk-SI2LU2RP.js.map +0 -1
- package/dist/chunk-W5UUUII5.js +0 -142
- package/dist/chunk-W5UUUII5.js.map +0 -1
- package/dist/document/document-session.d.ts +0 -127
- package/dist/document/document-session.d.ts.map +0 -1
- package/dist/document/document-session.js +0 -749
- package/dist/document/document-session.js.map +0 -1
- package/dist/document/filesystem-target.d.ts +0 -17
- package/dist/document/filesystem-target.d.ts.map +0 -1
- package/dist/document/filesystem-target.js +0 -70
- package/dist/document/filesystem-target.js.map +0 -1
- package/dist/document/index.d.ts.map +0 -1
- package/dist/document/recovery-journal.d.ts +0 -125
- package/dist/document/recovery-journal.d.ts.map +0 -1
- package/dist/document/recovery-journal.js +0 -385
- package/dist/document/recovery-journal.js.map +0 -1
- package/dist/document/types.d.ts +0 -89
- package/dist/document/types.d.ts.map +0 -1
- package/dist/document/types.js +0 -9
- package/dist/document/types.js.map +0 -1
- package/dist/filesystem/commit-lock.d.ts +0 -3
- package/dist/filesystem/commit-lock.d.ts.map +0 -1
- package/dist/filesystem/commit-lock.js +0 -20
- package/dist/filesystem/commit-lock.js.map +0 -1
- package/dist/filesystem/dbk-workspace.d.ts +0 -34
- package/dist/filesystem/dbk-workspace.d.ts.map +0 -1
- package/dist/filesystem/dbk-workspace.js +0 -85
- package/dist/filesystem/dbk-workspace.js.map +0 -1
- package/dist/filesystem/electron-provider-v2.d.ts +0 -36
- package/dist/filesystem/electron-provider-v2.d.ts.map +0 -1
- package/dist/filesystem/electron-provider-v2.js +0 -503
- package/dist/filesystem/electron-provider-v2.js.map +0 -1
- package/dist/filesystem/electron-provider.d.ts +0 -35
- package/dist/filesystem/electron-provider.d.ts.map +0 -1
- package/dist/filesystem/electron-provider.js +0 -69
- package/dist/filesystem/electron-provider.js.map +0 -1
- package/dist/filesystem/electron.d.ts.map +0 -1
- package/dist/filesystem/file-media-provider.d.ts +0 -23
- package/dist/filesystem/file-media-provider.d.ts.map +0 -1
- package/dist/filesystem/file-media-provider.js +0 -85
- package/dist/filesystem/file-media-provider.js.map +0 -1
- package/dist/filesystem/filesystem-content-container.d.ts +0 -24
- package/dist/filesystem/filesystem-content-container.d.ts.map +0 -1
- package/dist/filesystem/filesystem-content-container.js +0 -153
- package/dist/filesystem/filesystem-content-container.js.map +0 -1
- package/dist/filesystem/fs-error.d.ts +0 -46
- package/dist/filesystem/fs-error.d.ts.map +0 -1
- package/dist/filesystem/fs-error.js +0 -170
- package/dist/filesystem/fs-error.js.map +0 -1
- package/dist/filesystem/index.d.ts.map +0 -1
- package/dist/filesystem/indexeddb-content-container.d.ts +0 -22
- package/dist/filesystem/indexeddb-content-container.d.ts.map +0 -1
- package/dist/filesystem/indexeddb-content-container.js +0 -100
- package/dist/filesystem/indexeddb-content-container.js.map +0 -1
- package/dist/filesystem/indexeddb-provider-v2.d.ts +0 -96
- package/dist/filesystem/indexeddb-provider-v2.d.ts.map +0 -1
- package/dist/filesystem/indexeddb-provider-v2.js +0 -1241
- package/dist/filesystem/indexeddb-provider-v2.js.map +0 -1
- package/dist/filesystem/indexeddb-provider.d.ts +0 -39
- package/dist/filesystem/indexeddb-provider.d.ts.map +0 -1
- package/dist/filesystem/indexeddb-provider.js +0 -145
- package/dist/filesystem/indexeddb-provider.js.map +0 -1
- package/dist/filesystem/indexeddb-store.d.ts +0 -34
- package/dist/filesystem/indexeddb-store.d.ts.map +0 -1
- package/dist/filesystem/indexeddb-store.js +0 -165
- package/dist/filesystem/indexeddb-store.js.map +0 -1
- package/dist/filesystem/indexeddb.d.ts.map +0 -1
- package/dist/filesystem/legacy-v2-adapter.d.ts +0 -62
- package/dist/filesystem/legacy-v2-adapter.d.ts.map +0 -1
- package/dist/filesystem/legacy-v2-adapter.js +0 -499
- package/dist/filesystem/legacy-v2-adapter.js.map +0 -1
- package/dist/filesystem/memory-provider-v2.d.ts +0 -92
- package/dist/filesystem/memory-provider-v2.d.ts.map +0 -1
- package/dist/filesystem/memory-provider-v2.js +0 -615
- package/dist/filesystem/memory-provider-v2.js.map +0 -1
- package/dist/filesystem/memory-provider.d.ts +0 -54
- package/dist/filesystem/memory-provider.d.ts.map +0 -1
- package/dist/filesystem/memory-provider.js +0 -132
- package/dist/filesystem/memory-provider.js.map +0 -1
- package/dist/filesystem/memory.d.ts.map +0 -1
- package/dist/filesystem/move-entry.d.ts +0 -9
- package/dist/filesystem/move-entry.d.ts.map +0 -1
- package/dist/filesystem/move-entry.js +0 -103
- package/dist/filesystem/move-entry.js.map +0 -1
- package/dist/filesystem/move-error.d.ts +0 -53
- package/dist/filesystem/move-error.d.ts.map +0 -1
- package/dist/filesystem/move-error.js +0 -99
- package/dist/filesystem/move-error.js.map +0 -1
- package/dist/filesystem/native-provider-v2.d.ts +0 -75
- package/dist/filesystem/native-provider-v2.d.ts.map +0 -1
- package/dist/filesystem/native-provider-v2.js +0 -849
- package/dist/filesystem/native-provider-v2.js.map +0 -1
- package/dist/filesystem/native-provider.d.ts +0 -53
- package/dist/filesystem/native-provider.d.ts.map +0 -1
- package/dist/filesystem/native-provider.js +0 -471
- package/dist/filesystem/native-provider.js.map +0 -1
- package/dist/filesystem/native.d.ts.map +0 -1
- package/dist/filesystem/types.d.ts +0 -83
- package/dist/filesystem/types.d.ts.map +0 -1
- package/dist/filesystem/types.js +0 -16
- package/dist/filesystem/types.js.map +0 -1
- package/dist/filesystem/v2.d.ts +0 -172
- package/dist/filesystem/v2.d.ts.map +0 -1
- package/dist/filesystem/v2.js +0 -16
- package/dist/filesystem/v2.js.map +0 -1
- package/dist/filesystem/workspace-path.d.ts +0 -21
- package/dist/filesystem/workspace-path.d.ts.map +0 -1
- package/dist/filesystem/workspace-path.js +0 -80
- package/dist/filesystem/workspace-path.js.map +0 -1
- package/dist/host/filesystem-v2.d.ts +0 -45
- package/dist/host/filesystem-v2.d.ts.map +0 -1
- package/dist/host/filesystem-v2.js +0 -13
- package/dist/host/filesystem-v2.js.map +0 -1
- package/dist/host/git.d.ts +0 -200
- package/dist/host/git.d.ts.map +0 -1
- package/dist/host/git.js +0 -15
- package/dist/host/git.js.map +0 -1
- package/dist/host/index.d.ts.map +0 -1
- package/dist/host/types.d.ts +0 -232
- package/dist/host/types.d.ts.map +0 -1
- package/dist/host/types.js +0 -10
- package/dist/host/types.js.map +0 -1
- package/dist/host/wire-policy.d.ts +0 -22
- package/dist/host/wire-policy.d.ts.map +0 -1
- package/dist/host/wire-policy.js +0 -92
- package/dist/host/wire-policy.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/mcp/index.d.ts.map +0 -1
- package/dist/mcp/types.d.ts +0 -466
- package/dist/mcp/types.d.ts.map +0 -1
- package/dist/mcp/types.js +0 -25
- package/dist/mcp/types.js.map +0 -1
- package/dist/mcp/wire.d.ts +0 -29
- package/dist/mcp/wire.d.ts.map +0 -1
- package/dist/mcp/wire.js +0 -1046
- package/dist/mcp/wire.js.map +0 -1
- package/dist/mcp/zod.d.ts.map +0 -1
- package/dist/vscode/index.d.ts.map +0 -1
- package/dist/vscode/messages.d.ts +0 -204
- package/dist/vscode/messages.d.ts.map +0 -1
- package/dist/vscode/messages.js +0 -494
- package/dist/vscode/messages.js.map +0 -1
- package/dist/workspace/index.d.ts.map +0 -1
- package/dist/workspace/reconcile-electron.d.ts +0 -19
- package/dist/workspace/reconcile-electron.d.ts.map +0 -1
- package/dist/workspace/reconcile-electron.js +0 -42
- package/dist/workspace/reconcile-electron.js.map +0 -1
- package/dist/workspace/types.d.ts +0 -69
- package/dist/workspace/types.d.ts.map +0 -1
- package/dist/workspace/types.js +0 -2
- package/dist/workspace/types.js.map +0 -1
- package/dist/workspace/workspace-manager.d.ts +0 -47
- package/dist/workspace/workspace-manager.d.ts.map +0 -1
- package/dist/workspace/workspace-manager.js +0 -126
- package/dist/workspace/workspace-manager.js.map +0 -1
- package/src/document/document-session.ts +0 -834
- package/src/document/filesystem-target.ts +0 -109
- package/src/document/index.ts +0 -41
- package/src/document/recovery-journal.ts +0 -536
- package/src/document/types.ts +0 -116
- package/src/filesystem/commit-lock.ts +0 -29
- package/src/filesystem/dbk-workspace.ts +0 -135
- package/src/filesystem/electron-provider-v2.ts +0 -630
- package/src/filesystem/electron-provider.ts +0 -99
- package/src/filesystem/electron.ts +0 -3
- package/src/filesystem/file-media-provider.ts +0 -103
- package/src/filesystem/filesystem-content-container.ts +0 -164
- package/src/filesystem/fs-error.ts +0 -234
- package/src/filesystem/index.ts +0 -143
- package/src/filesystem/indexeddb-content-container.ts +0 -112
- package/src/filesystem/indexeddb-provider-v2.ts +0 -1740
- package/src/filesystem/indexeddb-provider.ts +0 -171
- package/src/filesystem/indexeddb-store.ts +0 -207
- package/src/filesystem/indexeddb.ts +0 -12
- package/src/filesystem/legacy-v2-adapter.ts +0 -779
- package/src/filesystem/memory-provider-v2.ts +0 -896
- package/src/filesystem/memory-provider.ts +0 -180
- package/src/filesystem/memory.ts +0 -15
- package/src/filesystem/move-entry.ts +0 -142
- package/src/filesystem/move-error.ts +0 -159
- package/src/filesystem/native-provider-v2.ts +0 -1165
- package/src/filesystem/native-provider.ts +0 -537
- package/src/filesystem/native.ts +0 -16
- package/src/filesystem/types.ts +0 -114
- package/src/filesystem/v2.ts +0 -231
- package/src/filesystem/workspace-path.ts +0 -92
- package/src/host/filesystem-v2.ts +0 -104
- package/src/host/git.ts +0 -246
- package/src/host/index.ts +0 -93
- package/src/host/types.ts +0 -274
- package/src/host/wire-policy.ts +0 -103
- package/src/index.ts +0 -10
- package/src/mcp/index.ts +0 -3
- package/src/mcp/types.ts +0 -594
- package/src/mcp/wire.ts +0 -1280
- package/src/mcp/zod.ts +0 -1000
- package/src/vscode/index.ts +0 -2
- package/src/vscode/messages.ts +0 -704
- package/src/workspace/index.ts +0 -17
- package/src/workspace/reconcile-electron.ts +0 -65
- package/src/workspace/types.ts +0 -67
- package/src/workspace/workspace-manager.ts +0 -151
- /package/dist/{chunk-75UUF6C4.js.map → chunk-B56KWCSE.js.map} +0 -0
- /package/dist/{chunk-EGNDADXB.js.map → chunk-MNSZ7EZN.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/filesystem/indexeddb-provider-v2.ts","../src/filesystem/indexeddb-provider.ts","../src/filesystem/indexeddb-content-container.ts","../src/filesystem/internal/mime.ts"],"sourcesContent":["import {\n FsError,\n fsErrorFromUnknown,\n type FsErrorCode,\n type FsErrorContext,\n type FsOperation,\n} from './fs-error.js';\nimport { withFileCommitLock } from './commit-lock.js';\nimport {\n RawIndexedDBFileSystemStore,\n indexedDBWorkspaceDatabaseName,\n type IndexedDBFileSystemStore,\n type IndexedDBFileSystemTransaction,\n type IndexedDBFileSystemTransactionMode,\n} from './indexeddb-store.js';\nimport {\n parseFileSystemVersion,\n type FileSystemCreateDirectoryOptions,\n type FileSystemDirectorySnapshot,\n type FileSystemEntrySnapshot,\n type FileSystemFileRead,\n type FileSystemFileSnapshot,\n type FileSystemMoveOptions,\n type FileSystemProviderCapabilities,\n type FileSystemProviderV2,\n type FileSystemRemoveOptions,\n type FileSystemRemoveResult,\n type FileSystemSnapshot,\n type FileSystemSnapshotEntry,\n type FileSystemVersion,\n type FileSystemWatchListener,\n type FileSystemWatchOptions,\n type FileSystemWatchSubscription,\n type FileSystemWriteOptions,\n} from './v2.js';\nimport {\n WORKSPACE_ROOT,\n parseWorkspacePath,\n workspacePathBasename,\n workspacePathContains,\n workspacePathDirname,\n type WorkspacePath,\n} from './workspace-path.js';\nimport type { FileMeta } from './types.js';\nimport { bytesEqual, copyBytes } from './internal/bytes.js';\nimport { compareSnapshotsByName, compareText } from './internal/entry-order.js';\nimport { parentChainWithRoot } from './internal/parent-chain.js';\nimport { isRecord } from './internal/records.js';\n\nconst ENTRY_SCHEMA_VERSION = 1;\nconst STATE_SCHEMA_VERSION = 1;\nconst LEGACY_CONFLICT_SCHEMA_VERSION = 2;\nconst LEGACY_CONFLICT_SCHEMA_VERSION_V1 = 1;\nconst LEGACY_OPAQUE_SCHEMA_VERSION = 2;\nconst LEGACY_OPAQUE_SCHEMA_VERSION_V1 = 1;\nconst ENTRY_PREFIX = 'v2:entry:';\nconst STATE_KEY = 'v2:state';\nconst LEGACY_CONFLICT_PREFIX = 'v2:legacy-conflict:';\nconst LEGACY_IGNORED_PREFIX = 'v2:legacy-ignored:';\nconst LEGACY_OPAQUE_PREFIX = 'v2:legacy-opaque:';\nconst LEGACY_DIRS_KEY = 'fs:dirs';\nconst LEGACY_PREFIX = 'fs:';\nconst LEGACY_CONTENT_SUFFIX = ':content';\nconst LEGACY_BINARY_SUFFIX = ':binary';\nconst LEGACY_META_SUFFIX = ':meta';\n\nclass LegacyNamespaceDetectedError extends Error {}\n\nconst INDEXEDDB_V2_CAPABILITIES: FileSystemProviderCapabilities = Object.freeze({\n writeAtomicity: 'cross-context',\n moveAtomicity: 'cross-context',\n snapshotAtomicity: 'cross-context',\n conditionalWrite: 'storage-atomic',\n recursiveRemove: true,\n watch: false,\n caseSensitivity: 'sensitive',\n symlinkPolicy: 'unsupported',\n durability: 'best-effort',\n});\n\ninterface PersistedEntryBase {\n readonly schemaVersion: typeof ENTRY_SCHEMA_VERSION;\n readonly path: WorkspacePath;\n readonly version: string;\n readonly lastModified: string;\n}\n\ninterface PersistedFileEntry extends PersistedEntryBase {\n readonly kind: 'file';\n readonly data: ArrayBuffer;\n}\n\ninterface PersistedDirectoryEntry extends PersistedEntryBase {\n readonly kind: 'directory';\n}\n\ntype PersistedEntry = PersistedFileEntry | PersistedDirectoryEntry;\n\ninterface PersistedState {\n readonly schemaVersion: typeof STATE_SCHEMA_VERSION;\n readonly migrationVersion: 1 | 2;\n readonly mutationCounter: number;\n readonly treeVersion: string;\n}\n\nexport type IndexedDBLegacyConflictReason =\n | 'dual-payload'\n | 'kind-collision'\n | 'authority-collision'\n | 'stale-client-write';\n\nexport type IndexedDBLegacyRecoveryKind = 'file' | 'directory';\n\ninterface PersistedLegacyRecoveryCandidate {\n readonly kind: IndexedDBLegacyRecoveryKind;\n readonly reason: IndexedDBLegacyConflictReason;\n readonly text: string | null;\n readonly binary: ArrayBuffer | null;\n readonly metadata: FileMeta | null;\n readonly detectedAt: string;\n}\n\ninterface PersistedLegacyConflict {\n readonly schemaVersion: typeof LEGACY_CONFLICT_SCHEMA_VERSION;\n readonly path: WorkspacePath;\n readonly candidates: readonly PersistedLegacyRecoveryCandidate[];\n}\n\nexport interface IndexedDBLegacyRecoveryCandidate {\n readonly kind: IndexedDBLegacyRecoveryKind;\n readonly reason: IndexedDBLegacyConflictReason;\n readonly text: string | null;\n readonly binary: ArrayBuffer | null;\n readonly metadata: FileMeta | null;\n readonly detectedAt: string;\n}\n\nexport interface IndexedDBLegacyMigrationConflict {\n readonly path: WorkspacePath;\n /** Backward-compatible projection of the newest quarantined candidate. */\n readonly reason: IndexedDBLegacyConflictReason;\n readonly kind: IndexedDBLegacyRecoveryKind;\n readonly text: string | null;\n readonly binary: ArrayBuffer | null;\n readonly metadata: FileMeta | null;\n readonly detectedAt: string;\n readonly candidates: readonly IndexedDBLegacyRecoveryCandidate[];\n}\n\nexport type IndexedDBLegacyConflictResolution =\n | 'v2'\n | 'text'\n | 'binary'\n | {\n readonly candidate: number;\n readonly payload: 'text' | 'binary' | 'directory';\n };\n\ninterface PersistedLegacyOpaqueValue {\n readonly value: unknown;\n /** Null only for values upgraded from the untimestamped v1 archive shape. */\n readonly archivedAt: string | null;\n}\n\ninterface PersistedLegacyOpaqueRecord {\n readonly schemaVersion: typeof LEGACY_OPAQUE_SCHEMA_VERSION;\n readonly key: string;\n readonly values: readonly PersistedLegacyOpaqueValue[];\n}\n\n/** One archived snapshot of an unrecognized legacy key's value. */\nexport interface IndexedDBLegacyOpaqueValue {\n /**\n * The structured-clone value exactly as the legacy key held it. DocBlocks\n * never interpreted these bytes, so the shape is whatever the writing tool\n * chose. Callers must treat it as untrusted and narrow it themselves.\n */\n readonly value: unknown;\n /** Byte size when the value is sized (bytes or string); null otherwise. */\n readonly byteLength: number | null;\n /** Null for values archived before archival timestamps were recorded. */\n readonly archivedAt: string | null;\n}\n\n/** What is archived under one unrecognized legacy key, without its values. */\nexport interface IndexedDBLegacyOpaqueRecordSummary {\n /** The original legacy key, decoded (for example `fs:some-other-tool`). */\n readonly key: string;\n /** Archived snapshots of this key, oldest first. Never zero. */\n readonly valueCount: number;\n /** Total bytes across values; null when any value is not sized. */\n readonly byteLength: number | null;\n readonly firstArchivedAt: string | null;\n readonly lastArchivedAt: string | null;\n}\n\n/** An archived legacy key together with every value snapshot it holds. */\nexport interface IndexedDBLegacyOpaqueRecord extends IndexedDBLegacyOpaqueRecordSummary {\n /** Oldest first. Index N here matches index N of the archival order. */\n readonly values: readonly IndexedDBLegacyOpaqueValue[];\n}\n\n/**\n * One record a caller has looked at and intends to destroy.\n *\n * Both {@link IndexedDBLegacyOpaqueRecordSummary} and\n * {@link IndexedDBLegacyOpaqueRecord} satisfy this shape, so the value returned\n * by a list or read can be handed straight to the discard call.\n */\nexport interface IndexedDBLegacyOpaqueDiscardTarget {\n readonly key: string;\n /**\n * The number of archived values the caller saw. The discard fails if the\n * record has since grown, so a snapshot that arrived after the caller looked\n * is never destroyed unseen.\n */\n readonly valueCount: number;\n}\n\nexport interface IndexedDBFileSystemProviderV2Options {\n /** Injectable store for fault, migration, and concurrency tests. */\n readonly store?: IndexedDBFileSystemStore;\n readonly now?: () => Date;\n /** Shared-store owners can retain the connection when this facade is disposed. */\n readonly closeStoreOnDispose?: boolean;\n}\n\ninterface MutationVersion {\n readonly state: PersistedState;\n readonly version: FileSystemVersion;\n readonly lastModified: string;\n}\n\n/**\n * IndexedDB implementation of the correctness-first filesystem contract.\n *\n * Each canonical path has one authoritative structured-clone record containing\n * its kind, owned bytes (for files), version, and metadata. Every mutation and\n * snapshot is one IndexedDB transaction. Legacy v1 keys are imported once;\n * ambiguous or stale branches move into durable recovery records before the\n * legacy namespace is deleted, leaving one live authority.\n */\nexport class IndexedDBFileSystemProviderV2 implements FileSystemProviderV2 {\n public readonly id: string;\n public readonly label: string;\n public readonly capabilities = INDEXEDDB_V2_CAPABILITIES;\n\n private readonly store: IndexedDBFileSystemStore;\n private readonly now: () => Date;\n private readonly closeStoreOnDispose: boolean;\n private readonly versionPrefix: string;\n private readonly subscriptions = new Set<FileSystemWatchSubscription>();\n private readonly inFlight = new Set<Promise<unknown>>();\n private initialization: Promise<void> | null = null;\n private disposePromise: Promise<void> | null = null;\n private storeClosed = false;\n private disposed = false;\n\n public constructor(\n id: string,\n label: string,\n options: IndexedDBFileSystemProviderV2Options = {},\n ) {\n this.id = id;\n this.label = label;\n this.store =\n options.store ?? new RawIndexedDBFileSystemStore(indexedDBWorkspaceDatabaseName(id), 'files');\n this.now = options.now ?? (() => new Date());\n this.closeStoreOnDispose = options.closeStoreOnDispose ?? true;\n this.versionPrefix = `idb-${encodeURIComponent(id).slice(0, 900) || 'workspace'}`;\n }\n\n /** Track accepted storage work so disposal can join it before closing. */\n private runSharedTransaction<T>(\n mode: IndexedDBFileSystemTransactionMode,\n operation: FsOperation,\n work: (transaction: IndexedDBFileSystemTransaction) => Promise<T>,\n ): Promise<T> {\n this.assertOpen(operation);\n const transaction = this.store.transaction(mode, work);\n this.inFlight.add(transaction);\n void transaction.then(\n () => this.inFlight.delete(transaction),\n () => this.inFlight.delete(transaction),\n );\n return transaction;\n }\n\n public async stat(path: WorkspacePath): Promise<FileSystemEntrySnapshot | null> {\n this.assertOpen('stat');\n const canonical = parseWorkspacePath(path);\n await this.ensureInitialized('stat');\n return this.transaction('readonly', { operation: 'stat', path: canonical }, async (tx) => {\n const entry = await readEntry(tx, canonical);\n return entry ? toEntrySnapshot(entry) : null;\n });\n }\n\n public async readFile(path: WorkspacePath): Promise<FileSystemFileRead | null> {\n this.assertOpen('read');\n const canonical = parseWorkspacePath(path);\n await this.ensureInitialized('read');\n return this.transaction('readonly', { operation: 'read', path: canonical }, async (tx) => {\n const entry = await readEntry(tx, canonical);\n if (!entry) return null;\n if (entry.kind !== 'file') {\n throw this.error(\n 'type-mismatch',\n 'read',\n canonical,\n 'Expected a file but found a directory.',\n );\n }\n return Object.freeze({ entry: toFileSnapshot(entry), data: copyBytes(entry.data) });\n });\n }\n\n public async readDirectory(path: WorkspacePath): Promise<readonly FileSystemEntrySnapshot[]> {\n this.assertOpen('list');\n const canonical = parseWorkspacePath(path);\n await this.ensureInitialized('list');\n return this.transaction('readonly', { operation: 'list', path: canonical }, async (tx) => {\n const directory = await readEntry(tx, canonical);\n if (!directory) {\n throw this.error('not-found', 'list', canonical, 'Directory does not exist.');\n }\n if (directory.kind !== 'directory') {\n throw this.error(\n 'type-mismatch',\n 'list',\n canonical,\n 'Expected a directory but found a file.',\n );\n }\n const paths = await listEntryPaths(tx);\n const children: FileSystemEntrySnapshot[] = [];\n for (const candidate of paths) {\n if (candidate && workspacePathDirname(candidate) === canonical) {\n const entry = await readRequiredEntry(tx, candidate);\n children.push(toEntrySnapshot(entry));\n }\n }\n children.sort(compareSnapshotsByName);\n return Object.freeze(children);\n });\n }\n\n public async writeFile(\n path: WorkspacePath,\n data: ArrayBuffer | Uint8Array,\n options: FileSystemWriteOptions = {},\n ): Promise<FileSystemFileSnapshot> {\n this.assertOpen('write');\n const canonical = this.canonicalNonRoot(path, 'write');\n const ownedData = copyBytes(data);\n await this.ensureInitialized('write');\n return this.withMutationLock(() =>\n this.transaction('readwrite', { operation: 'write', path: canonical }, async (tx) => {\n await assertNoLegacyConflict(tx, canonical, 'write');\n const mutation = new EntryMutation(tx);\n const existing = await mutation.get(canonical);\n if (existing?.kind === 'directory') {\n throw this.error(\n 'type-mismatch',\n 'write',\n canonical,\n 'Cannot replace a directory with a file.',\n );\n }\n const mode = options.mode ?? 'upsert';\n if (mode === 'create' && existing) {\n throw this.error('already-exists', 'write', canonical, 'File already exists.');\n }\n if (mode === 'replace' && !existing) {\n throw this.error('not-found', 'write', canonical, 'File does not exist.');\n }\n this.assertExpectedVersion(existing, options.expectedVersion, 'write', canonical);\n const missingParents = await this.planParents(\n mutation,\n canonical,\n options.createParents ?? false,\n 'write',\n );\n const next = await this.nextMutationVersion(tx);\n this.addDirectories(mutation, missingParents, next);\n const file: PersistedFileEntry = {\n schemaVersion: ENTRY_SCHEMA_VERSION,\n kind: 'file',\n path: canonical,\n data: ownedData,\n version: next.version,\n lastModified: next.lastModified,\n };\n mutation.set(canonical, file);\n await this.touchParents(mutation, canonical, next);\n await mutation.commit(next.state);\n return toFileSnapshot(file);\n }),\n );\n }\n\n public async createDirectory(\n path: WorkspacePath,\n options: FileSystemCreateDirectoryOptions = {},\n ): Promise<FileSystemDirectorySnapshot> {\n this.assertOpen('create-directory');\n const canonical = parseWorkspacePath(path);\n await this.ensureInitialized('create-directory');\n return this.withMutationLock(() =>\n this.transaction(\n 'readwrite',\n { operation: 'create-directory', path: canonical },\n async (tx) => {\n await assertNoLegacyConflict(tx, canonical, 'create-directory');\n const mutation = new EntryMutation(tx);\n const existing = await mutation.get(canonical);\n if (existing) {\n if (existing.kind !== 'directory') {\n throw this.error(\n 'type-mismatch',\n 'create-directory',\n canonical,\n 'Cannot replace a file with a directory.',\n );\n }\n if ((options.mode ?? 'ensure') === 'create') {\n throw this.error(\n 'already-exists',\n 'create-directory',\n canonical,\n 'Directory already exists.',\n );\n }\n return toDirectorySnapshot(existing);\n }\n const missingParents = await this.planParents(\n mutation,\n canonical,\n options.createParents ?? false,\n 'create-directory',\n );\n const next = await this.nextMutationVersion(tx);\n this.addDirectories(mutation, [...missingParents, canonical], next);\n await this.touchParents(mutation, canonical, next);\n await mutation.commit(next.state);\n const created = await mutation.get(canonical);\n if (!created || created.kind !== 'directory') {\n throw corrupt('Created directory was not staged.', canonical);\n }\n return toDirectorySnapshot(created);\n },\n ),\n );\n }\n\n public async remove(\n path: WorkspacePath,\n options: FileSystemRemoveOptions = {},\n ): Promise<FileSystemRemoveResult> {\n this.assertOpen('remove');\n const canonical = this.canonicalNonRoot(path, 'remove');\n await this.ensureInitialized('remove');\n return this.withMutationLock(() =>\n this.transaction('readwrite', { operation: 'remove', path: canonical }, async (tx) => {\n // Deleting the v2 authority under a quarantined path would leave the\n // conflict unresolvable: 'v2' resolution then reports that there is no\n // authority to keep. Callers that want the legacy data gone say so with\n // discardLegacyMigrationConflict().\n await assertNoLegacyConflictInSubtree(tx, canonical, 'remove');\n const mutation = new EntryMutation(tx);\n const existing = await mutation.get(canonical);\n const state = await readRequiredState(tx);\n if (!existing) {\n if ((options.missing ?? 'error') === 'ignore') {\n return Object.freeze({\n removed: false,\n version: parseFileSystemVersion(state.treeVersion),\n });\n }\n throw this.error('not-found', 'remove', canonical, 'Entry does not exist.');\n }\n this.assertExpectedVersion(existing, options.expectedVersion, 'remove', canonical);\n const paths = await mutation.paths();\n const descendants = paths.filter((candidate) =>\n workspacePathContains(canonical, candidate, false),\n );\n if (existing.kind === 'directory' && descendants.length > 0 && !options.recursive) {\n throw this.error('not-empty', 'remove', canonical, 'Directory is not empty.');\n }\n const next = this.advanceState(state);\n mutation.delete(canonical);\n if (existing.kind === 'directory') {\n for (const descendant of descendants) mutation.delete(descendant);\n }\n await this.touchParents(mutation, canonical, next);\n await mutation.commit(next.state);\n return Object.freeze({ removed: true, version: next.version });\n }),\n );\n }\n\n public async move(\n oldPath: WorkspacePath,\n newPath: WorkspacePath,\n options: FileSystemMoveOptions = {},\n ): Promise<FileSystemEntrySnapshot> {\n this.assertOpen('move');\n const sourcePath = this.canonicalNonRoot(oldPath, 'move');\n const destinationPath = this.canonicalNonRoot(newPath, 'move');\n await this.ensureInitialized('move');\n return this.withMutationLock(() =>\n this.transaction(\n 'readwrite',\n { operation: 'move', path: sourcePath, destinationPath },\n async (tx) => {\n await assertNoLegacyConflictInSubtree(tx, sourcePath, 'move');\n await assertNoLegacyConflictInSubtree(tx, destinationPath, 'move');\n const mutation = new EntryMutation(tx);\n const source = await mutation.get(sourcePath);\n if (!source) {\n throw this.error('not-found', 'move', sourcePath, 'Source does not exist.');\n }\n this.assertExpectedVersion(source, options.expectedVersion, 'move', sourcePath);\n if (sourcePath === destinationPath) return toEntrySnapshot(source);\n if (await mutation.get(destinationPath)) {\n throw new FsError('already-exists', 'Destination already exists.', {\n operation: 'move',\n path: sourcePath,\n destinationPath,\n });\n }\n if (\n source.kind === 'directory' &&\n workspacePathContains(sourcePath, destinationPath, false)\n ) {\n throw new FsError('invalid-path', 'Cannot move a directory into itself.', {\n operation: 'move',\n path: sourcePath,\n destinationPath,\n });\n }\n const missingParents = await this.planParents(\n mutation,\n destinationPath,\n options.createParents ?? false,\n 'move',\n );\n const paths = await mutation.paths();\n const sourcePaths = paths.filter((candidate) =>\n workspacePathContains(sourcePath, candidate),\n );\n const sourceSet = new Set(sourcePaths);\n const remapped: Array<readonly [WorkspacePath, WorkspacePath, PersistedEntry]> = [];\n for (const currentPath of sourcePaths) {\n const suffix = currentPath.slice(sourcePath.length);\n const targetPath = parseWorkspacePath(`${destinationPath}${suffix}`);\n const collision = await mutation.get(targetPath);\n if (collision && !sourceSet.has(targetPath)) {\n throw new FsError('already-exists', 'A destination descendant already exists.', {\n operation: 'move',\n path: currentPath,\n destinationPath: targetPath,\n });\n }\n remapped.push([currentPath, targetPath, await mutation.require(currentPath)]);\n }\n const state = await readRequiredState(tx);\n const next = this.advanceState(state);\n for (const currentPath of sourcePaths) mutation.delete(currentPath);\n this.addDirectories(mutation, missingParents, next);\n for (const [, targetPath, current] of remapped) {\n mutation.set(targetPath, withPathAndVersion(current, targetPath, next));\n }\n await this.touchParents(mutation, sourcePath, next);\n await this.touchParents(mutation, destinationPath, next);\n await mutation.commit(next.state);\n return toEntrySnapshot(await mutation.require(destinationPath));\n },\n ),\n );\n }\n\n public async snapshot(): Promise<FileSystemSnapshot> {\n this.assertOpen('snapshot');\n await this.ensureInitialized('snapshot');\n return this.transaction('readonly', { operation: 'snapshot' }, async (tx) => {\n const [state, paths] = await Promise.all([readRequiredState(tx), listEntryPaths(tx)]);\n const entries: FileSystemSnapshotEntry[] = [];\n for (const path of paths.sort(compareText)) {\n const entry = await readRequiredEntry(tx, path);\n entries.push(\n entry.kind === 'file'\n ? Object.freeze({ ...toFileSnapshot(entry), data: copyBytes(entry.data) })\n : toDirectorySnapshot(entry),\n );\n }\n return Object.freeze({\n version: parseFileSystemVersion(state.treeVersion),\n entries: Object.freeze(entries),\n });\n });\n }\n\n /** IndexedDB has no reliable cross-browser external-change observer. */\n public watch(\n _listener: FileSystemWatchListener,\n options: FileSystemWatchOptions = {},\n ): FileSystemWatchSubscription {\n this.assertOpen('watch');\n const error = new FsError('not-supported', 'IndexedDB filesystem watching is unavailable.', {\n operation: 'watch',\n });\n let closed = false;\n let disposePromise: Promise<void> | null = null;\n const ready = Promise.reject(error);\n void ready.catch((caught: FsError) => {\n try {\n options.onError?.(caught);\n } catch {\n // An observational error callback cannot change subscription state.\n }\n });\n const subscription: FileSystemWatchSubscription = {\n get closed() {\n return closed;\n },\n ready,\n dispose: () => {\n if (disposePromise) return disposePromise;\n closed = true;\n this.subscriptions.delete(subscription);\n disposePromise = Promise.resolve();\n return disposePromise;\n },\n };\n this.subscriptions.add(subscription);\n return subscription;\n }\n\n public dispose(): Promise<void> {\n if (this.disposePromise) return this.disposePromise;\n this.disposed = true;\n this.disposePromise = (async () => {\n try {\n await Promise.allSettled([...this.inFlight]);\n await Promise.all([...this.subscriptions].map((subscription) => subscription.dispose()));\n } finally {\n if (this.closeStoreOnDispose && !this.storeClosed) {\n this.storeClosed = true;\n this.store.close?.();\n }\n }\n })();\n return this.disposePromise;\n }\n\n /** List unresolved, byte-preserving conflicts found during v1 migration. */\n public async listLegacyMigrationConflicts(): Promise<\n readonly IndexedDBLegacyMigrationConflict[]\n > {\n this.assertOpen('read');\n await this.ensureInitialized('read');\n return this.transaction('readonly', { operation: 'read' }, async (tx) => {\n const keys = (await tx.keys()).filter((key) => key.startsWith(LEGACY_CONFLICT_PREFIX));\n const conflicts: IndexedDBLegacyMigrationConflict[] = [];\n for (const key of keys) {\n const raw = await tx.get<unknown>(key);\n conflicts.push(toPublicLegacyConflict(validateLegacyConflict(raw)));\n }\n conflicts.sort((left, right) => compareText(left.path, right.path));\n return Object.freeze(conflicts);\n });\n }\n\n /** Resolve quarantined legacy data by choosing v2 or one legacy byte payload. */\n public async resolveLegacyMigrationConflict(\n path: WorkspacePath,\n resolution: IndexedDBLegacyConflictResolution,\n ): Promise<FileSystemEntrySnapshot> {\n this.assertOpen('write');\n const canonical = this.canonicalNonRoot(path, 'write');\n await this.ensureInitialized('write');\n return this.withMutationLock(() =>\n this.transaction('readwrite', { operation: 'write', path: canonical }, async (tx) => {\n const key = legacyConflictKey(canonical);\n const conflict = validateLegacyConflict(await tx.get<unknown>(key));\n if (conflict.path !== canonical) throw corrupt('Legacy conflict key mismatch.', canonical);\n const mutation = new EntryMutation(tx);\n const existing = await mutation.get(canonical);\n if (resolution === 'v2') {\n if (!existing) {\n throw this.error(\n 'type-mismatch',\n 'write',\n canonical,\n 'There is no v2 authority to keep at this path.',\n );\n }\n await tx.delete(key);\n return toEntrySnapshot(existing);\n }\n\n const selected = selectLegacyPayload(conflict, resolution, canonical);\n if (selected.kind === 'directory') {\n if (existing?.kind === 'file') {\n throw this.error(\n 'type-mismatch',\n 'write',\n canonical,\n 'Move or remove the v2 file before restoring a legacy directory at this path.',\n );\n }\n if (existing) {\n await tx.delete(key);\n return toDirectorySnapshot(existing);\n }\n const missingParents = await this.planParents(mutation, canonical, true, 'write');\n const next = await this.nextMutationVersion(tx);\n this.addDirectories(mutation, [...missingParents, canonical], next);\n await this.touchParents(mutation, canonical, next);\n await mutation.commit(next.state);\n await tx.delete(key);\n const restored = await mutation.require(canonical);\n if (restored.kind !== 'directory') {\n throw corrupt('Restored legacy directory was not staged as a directory.', canonical);\n }\n return toDirectorySnapshot(restored);\n }\n if (existing?.kind === 'directory') {\n throw this.error(\n 'type-mismatch',\n 'write',\n canonical,\n 'Move or remove the v2 directory before restoring a legacy file at this path.',\n );\n }\n const missingParents = await this.planParents(mutation, canonical, true, 'write');\n const next = await this.nextMutationVersion(tx);\n this.addDirectories(mutation, missingParents, next);\n const file: PersistedFileEntry = {\n schemaVersion: ENTRY_SCHEMA_VERSION,\n kind: 'file',\n path: canonical,\n data: copyBytes(selected.data),\n version: next.version,\n lastModified: next.lastModified,\n };\n mutation.set(canonical, file);\n await this.touchParents(mutation, canonical, next);\n await mutation.commit(next.state);\n await tx.delete(key);\n return toFileSnapshot(file);\n }),\n );\n }\n\n /** Explicitly discard every quarantined legacy candidate at a path. */\n public async discardLegacyMigrationConflict(path: WorkspacePath): Promise<boolean> {\n this.assertOpen('remove');\n const canonical = this.canonicalNonRoot(path, 'remove');\n await this.ensureInitialized('remove');\n return this.withMutationLock(() =>\n this.transaction('readwrite', { operation: 'remove', path: canonical }, async (tx) => {\n const key = legacyConflictKey(canonical);\n if ((await tx.get<unknown>(key)) === null) return false;\n await tx.delete(key);\n return true;\n }),\n );\n }\n\n /**\n * List the unrecognized legacy keys this workspace archived during migration.\n *\n * Migration deletes the legacy `fs:` namespace, but a key it cannot interpret\n * is copied aside first rather than dropped: those bytes belong to whatever\n * tool wrote them against this origin, and DocBlocks is not entitled to\n * decide they are worthless. Nothing else reads that archive, so without this\n * call the bytes are invisible and their quota is unaccountable.\n *\n * Values are deliberately excluded — an archive large enough to matter is an\n * archive too large to materialize just to count it. Use\n * {@link readLegacyOpaqueRecord} for the values themselves.\n */\n public async listLegacyOpaqueRecords(): Promise<readonly IndexedDBLegacyOpaqueRecordSummary[]> {\n this.assertOpen('read');\n await this.ensureInitialized('read');\n return this.transaction('readonly', { operation: 'read' }, async (tx) => {\n const keys = (await tx.keys()).filter((key) => key.startsWith(LEGACY_OPAQUE_PREFIX));\n const summaries: IndexedDBLegacyOpaqueRecordSummary[] = [];\n for (const key of keys) {\n summaries.push(\n toOpaqueSummary(validateLegacyOpaqueRecord(await tx.get<unknown>(key), key)),\n );\n }\n summaries.sort((left, right) => compareText(left.key, right.key));\n return Object.freeze(summaries);\n });\n }\n\n /** Retrieve every archived value for one unrecognized legacy key. */\n public async readLegacyOpaqueRecord(key: string): Promise<IndexedDBLegacyOpaqueRecord | null> {\n this.assertOpen('read');\n await this.ensureInitialized('read');\n return this.transaction('readonly', { operation: 'read' }, async (tx) => {\n const archiveKey = legacyOpaqueKey(key);\n const raw = await tx.get<unknown>(archiveKey);\n if (raw === null) return null;\n return toPublicOpaqueRecord(validateLegacyOpaqueRecord(raw, archiveKey));\n });\n }\n\n /**\n * Permanently destroy archived legacy values. This is the only operation that\n * can lose data the archive exists to protect.\n *\n * For every target, all of that key's archived value snapshots are erased and\n * the quota they held is reclaimed. There is no undo, no tombstone, and no\n * other copy: migration already deleted the original `fs:` key, so the\n * archive is the last one. Retrieve anything worth keeping with\n * {@link readLegacyOpaqueRecord} before calling this.\n *\n * Each target must carry the `valueCount` the caller actually observed, which\n * is why a target is a value returned by {@link listLegacyOpaqueRecords} or\n * {@link readLegacyOpaqueRecord} rather than a bare key. A stale client can\n * append a new snapshot at any time; if any target has grown since it was\n * observed, the whole call fails with `conflict` and destroys nothing, so\n * re-list and look again. A key that is already absent is not an error —\n * discarding what is gone is a no-op — but a key whose count disagrees is.\n *\n * @returns how many records were destroyed.\n */\n public async discardLegacyOpaqueRecords(\n targets: readonly IndexedDBLegacyOpaqueDiscardTarget[],\n ): Promise<number> {\n this.assertOpen('remove');\n if (targets.length === 0) return 0;\n await this.ensureInitialized('remove');\n return this.withMutationLock(() =>\n this.transaction('readwrite', { operation: 'remove' }, async (tx) => {\n const doomed: string[] = [];\n for (const target of targets) {\n const archiveKey = legacyOpaqueKey(target.key);\n const raw = await tx.get<unknown>(archiveKey);\n if (raw === null) continue;\n const record = validateLegacyOpaqueRecord(raw, archiveKey);\n if (record.values.length !== target.valueCount) {\n throw new FsError(\n 'conflict',\n `Archived legacy key ${target.key} now holds ${record.values.length} values, not ${target.valueCount}. Read it again before discarding it.`,\n { operation: 'remove', retryable: false },\n );\n }\n doomed.push(archiveKey);\n }\n for (const archiveKey of doomed) await tx.delete(archiveKey);\n return doomed.length;\n }),\n );\n }\n\n private async ensureInitialized(operation: FsOperation): Promise<void> {\n this.assertOpen(operation);\n if (this.initialization) return this.initialization;\n const attempt = this.withMutationLock(() =>\n this.runSharedTransaction('readwrite', operation, (tx) => this.migrateLegacy(tx)),\n );\n this.initialization = attempt.catch((error: unknown) => {\n this.initialization = null;\n throw fsErrorFromUnknown(error, { operation });\n });\n return this.initialization;\n }\n\n private async migrateLegacy(tx: IndexedDBFileSystemTransaction): Promise<void> {\n const existingState = await readState(tx);\n const keys = await tx.keys();\n if (existingState) {\n const root = await readEntry(tx, WORKSPACE_ROOT);\n if (!root || root.kind !== 'directory') {\n throw corrupt('Initialized v2 filesystem has no root directory.', WORKSPACE_ROOT);\n }\n if (\n existingState.migrationVersion === 1 ||\n keys.some((key) => key.startsWith(LEGACY_PREFIX))\n ) {\n await this.quarantineExistingLegacy(\n tx,\n keys,\n existingState,\n existingState.migrationVersion === 1 ? 'authority-collision' : 'stale-client-write',\n );\n }\n return;\n }\n\n const now = this.now().toISOString();\n const version = this.makeVersion(1);\n const entries = new Map<WorkspacePath, PersistedEntry>();\n\n // Preserve any authoritative v2 records left by a pre-release build.\n for (const path of entryPathsFromKeys(keys)) {\n entries.set(path, await readRequiredEntry(tx, path));\n }\n if (entries.get(WORKSPACE_ROOT)?.kind === 'file') {\n throw corrupt(\n 'Pre-release v2 authority stored a file at the workspace root.',\n WORKSPACE_ROOT,\n );\n }\n entries.set(\n WORKSPACE_ROOT,\n entries.get(WORKSPACE_ROOT) ?? directoryRecord(WORKSPACE_ROOT, version, now),\n );\n\n const legacyDirectories = await readLegacyDirectories(tx);\n const legacyFilePaths = legacyPathsFromKeys(keys);\n for (const directory of legacyDirectories) {\n const existing = entries.get(directory);\n if (existing?.kind === 'file' || hasFileAncestor(entries, directory)) {\n await appendLegacyConflict(\n tx,\n directory,\n directoryRecoveryCandidate('authority-collision', now),\n );\n continue;\n }\n addParentDirectories(entries, directory, version, now);\n if (!existing) entries.set(directory, directoryRecord(directory, version, now));\n }\n\n for (const path of legacyFilePaths) {\n const legacy = await readLegacyFile(tx, path);\n const existing = entries.get(path);\n if (existing?.kind === 'file') {\n if (!legacyPayloadsMatchEntry(legacy, existing)) {\n await appendLegacyConflict(\n tx,\n path,\n fileRecoveryCandidate(legacy, 'authority-collision', now),\n );\n }\n continue;\n }\n const kindCollision = existing?.kind === 'directory' || hasFileAncestor(entries, path);\n const payloadsDisagree =\n legacy.content !== null &&\n legacy.binary !== null &&\n !bytesEqual(new TextEncoder().encode(legacy.content), legacy.binary);\n if (\n payloadsDisagree ||\n kindCollision ||\n (legacy.content === null && legacy.binary === null)\n ) {\n await appendLegacyConflict(\n tx,\n path,\n fileRecoveryCandidate(\n legacy,\n kindCollision\n ? 'kind-collision'\n : payloadsDisagree\n ? 'dual-payload'\n : 'authority-collision',\n now,\n ),\n );\n continue;\n }\n addParentDirectories(entries, path, version, now);\n const data =\n legacy.content !== null\n ? new TextEncoder().encode(legacy.content).buffer\n : copyBytes(legacy.binary!);\n entries.set(path, {\n schemaVersion: ENTRY_SCHEMA_VERSION,\n kind: 'file',\n path,\n data: copyBytes(data),\n version,\n lastModified: legacy.metadata?.lastModified ?? now,\n });\n }\n\n for (const entry of entries.values()) {\n await tx.put(entryKey(entry.path), entry);\n }\n await deleteLegacyNamespace(tx, keys, now);\n const state: PersistedState = {\n schemaVersion: STATE_SCHEMA_VERSION,\n migrationVersion: 2,\n mutationCounter: 1,\n treeVersion: version,\n };\n await tx.put(STATE_KEY, state);\n }\n\n private async quarantineExistingLegacy(\n tx: IndexedDBFileSystemTransaction,\n keys: readonly string[],\n state: PersistedState,\n reason: 'authority-collision' | 'stale-client-write',\n ): Promise<void> {\n const now = this.now().toISOString();\n const ignored = await readMarkerPaths(\n tx,\n keys,\n LEGACY_IGNORED_PREFIX,\n validateIgnoredLegacyPath,\n );\n const legacyDirectories = await readLegacyDirectories(tx);\n for (const path of legacyDirectories) {\n if (ignored.has(path)) continue;\n const entry = await readEntry(tx, path);\n if (entry?.kind === 'directory') continue;\n await appendLegacyConflict(\n tx,\n path,\n directoryRecoveryCandidate(entry ? 'kind-collision' : reason, now),\n );\n }\n\n for (const path of legacyPathsFromKeys(keys)) {\n if (ignored.has(path)) continue;\n const legacy = await readLegacyFile(tx, path);\n const entry = await readEntry(tx, path);\n if (entry?.kind === 'file' && legacyPayloadsMatchEntry(legacy, entry)) continue;\n await appendLegacyConflict(\n tx,\n path,\n fileRecoveryCandidate(legacy, entry?.kind === 'directory' ? 'kind-collision' : reason, now),\n );\n }\n\n await deleteLegacyNamespace(tx, keys, now);\n for (const key of keys) {\n if (key.startsWith(LEGACY_IGNORED_PREFIX)) await tx.delete(key);\n }\n if (state.migrationVersion === 1) {\n await tx.put(STATE_KEY, { ...state, migrationVersion: 2 } satisfies PersistedState);\n }\n }\n\n private async transaction<T>(\n mode: IndexedDBFileSystemTransactionMode,\n context: FsErrorContext,\n operation: (transaction: IndexedDBFileSystemTransaction) => Promise<T>,\n ): Promise<T> {\n this.assertOpen(context.operation ?? 'read');\n for (let attempt = 0; attempt < 3; attempt += 1) {\n try {\n const outcome = await this.runSharedTransaction(\n mode,\n context.operation ?? 'read',\n async (transaction) => {\n if (await transaction.hasKeyWithPrefix(LEGACY_PREFIX)) {\n if (mode === 'readonly') throw new LegacyNamespaceDetectedError();\n const state = await readRequiredState(transaction);\n await this.quarantineExistingLegacy(\n transaction,\n await transaction.keys(),\n state,\n 'stale-client-write',\n );\n return { retry: true as const };\n }\n return { retry: false as const, value: await operation(transaction) };\n },\n );\n if (outcome.retry) continue;\n return outcome.value;\n } catch (error: unknown) {\n if (!(error instanceof LegacyNamespaceDetectedError)) {\n throw fsErrorFromUnknown(error, context);\n }\n try {\n await this.withMutationLock(() =>\n this.runSharedTransaction(\n 'readwrite',\n context.operation ?? 'read',\n async (transaction) => {\n if (!(await transaction.hasKeyWithPrefix(LEGACY_PREFIX))) return;\n const state = await readRequiredState(transaction);\n await this.quarantineExistingLegacy(\n transaction,\n await transaction.keys(),\n state,\n 'stale-client-write',\n );\n },\n ),\n );\n } catch (quarantineError: unknown) {\n throw fsErrorFromUnknown(quarantineError, context);\n }\n }\n }\n throw new FsError('busy', 'A stale IndexedDB client is continuously writing legacy records.', {\n ...context,\n retryable: true,\n });\n }\n\n private withMutationLock<T>(operation: () => Promise<T>): Promise<T> {\n return withFileCommitLock(`indexeddb:${this.id}:workspace`, operation);\n }\n\n private async nextMutationVersion(tx: IndexedDBFileSystemTransaction): Promise<MutationVersion> {\n return this.advanceState(await readRequiredState(tx));\n }\n\n private advanceState(state: PersistedState): MutationVersion {\n if (state.mutationCounter >= Number.MAX_SAFE_INTEGER) {\n throw corrupt('IndexedDB filesystem mutation counter overflowed.');\n }\n const mutationCounter = state.mutationCounter + 1;\n const version = this.makeVersion(mutationCounter);\n const nextState: PersistedState = {\n ...state,\n mutationCounter,\n treeVersion: version,\n };\n return { state: nextState, version, lastModified: this.now().toISOString() };\n }\n\n private makeVersion(counter: number): FileSystemVersion {\n return parseFileSystemVersion(`${this.versionPrefix}:${counter}`);\n }\n\n private async planParents(\n mutation: EntryMutation,\n path: WorkspacePath,\n createParents: boolean,\n operation: FsOperation,\n ): Promise<WorkspacePath[]> {\n const missing: WorkspacePath[] = [];\n for (const parent of parentChainWithRoot(path)) {\n const entry = await mutation.get(parent);\n if (entry?.kind === 'file') {\n throw this.error(\n 'type-mismatch',\n operation,\n parent,\n 'A parent path is a file, not a directory.',\n );\n }\n if (!entry) {\n if (!createParents) {\n throw this.error('not-found', operation, parent, 'Parent directory does not exist.');\n }\n missing.push(parent);\n }\n }\n return missing;\n }\n\n private addDirectories(\n mutation: EntryMutation,\n paths: readonly WorkspacePath[],\n next: MutationVersion,\n ): void {\n for (const path of paths) {\n mutation.set(path, directoryRecord(path, next.version, next.lastModified));\n }\n }\n\n private async touchParents(\n mutation: EntryMutation,\n path: WorkspacePath,\n next: MutationVersion,\n ): Promise<void> {\n for (const parent of parentChainWithRoot(path)) {\n const entry = await mutation.get(parent);\n if (entry?.kind === 'directory') {\n mutation.set(parent, directoryRecord(parent, next.version, next.lastModified));\n }\n }\n }\n\n private canonicalNonRoot(path: WorkspacePath, operation: FsOperation): WorkspacePath {\n const canonical = parseWorkspacePath(path);\n if (!canonical) {\n throw this.error(\n 'invalid-path',\n operation,\n canonical,\n 'The workspace root is not a file entry.',\n );\n }\n return canonical;\n }\n\n private assertExpectedVersion(\n entry: PersistedEntry | null,\n expected: FileSystemVersion | null | undefined,\n operation: FsOperation,\n path: WorkspacePath,\n ): void {\n if (expected === undefined) return;\n if (expected === null ? !entry : entry?.version === expected) return;\n throw this.error(\n 'conflict',\n operation,\n path,\n 'Entry version does not match the expected version.',\n );\n }\n\n private assertOpen(operation: FsOperation): void {\n if (!this.disposed) return;\n throw new FsError('disposed', 'Filesystem provider is disposed.', { operation });\n }\n\n private error(\n code: FsErrorCode,\n operation: FsOperation,\n path: WorkspacePath,\n message: string,\n ): FsError {\n return new FsError(code, message, { operation, path });\n }\n}\n\nclass EntryMutation {\n private readonly cache = new Map<WorkspacePath, PersistedEntry | null>();\n private readonly changed = new Map<WorkspacePath, PersistedEntry>();\n private readonly deleted = new Set<WorkspacePath>();\n\n public constructor(private readonly transaction: IndexedDBFileSystemTransaction) {}\n\n public async get(path: WorkspacePath): Promise<PersistedEntry | null> {\n if (this.deleted.has(path)) return null;\n const cached = this.cache.get(path);\n if (cached !== undefined) return cached;\n const entry = await readEntry(this.transaction, path);\n this.cache.set(path, entry);\n return entry;\n }\n\n public async require(path: WorkspacePath): Promise<PersistedEntry> {\n const entry = await this.get(path);\n if (!entry) throw corrupt(`Missing staged entry: ${path}.`, path);\n return entry;\n }\n\n public set(path: WorkspacePath, entry: PersistedEntry): void {\n const owned = copyEntry(entry);\n this.cache.set(path, owned);\n this.changed.set(path, owned);\n this.deleted.delete(path);\n }\n\n public delete(path: WorkspacePath): void {\n this.cache.set(path, null);\n this.changed.delete(path);\n this.deleted.add(path);\n }\n\n public async paths(): Promise<WorkspacePath[]> {\n const paths = new Set(await listEntryPaths(this.transaction));\n for (const path of this.deleted) paths.delete(path);\n for (const path of this.changed.keys()) paths.add(path);\n return [...paths];\n }\n\n public async commit(state: PersistedState): Promise<void> {\n for (const path of this.deleted) await this.transaction.delete(entryKey(path));\n for (const [path, entry] of this.changed) await this.transaction.put(entryKey(path), entry);\n await this.transaction.put(STATE_KEY, state);\n }\n}\n\nfunction entryKey(path: WorkspacePath): string {\n return `${ENTRY_PREFIX}${path}`;\n}\n\nfunction legacyConflictKey(path: WorkspacePath): string {\n return `${LEGACY_CONFLICT_PREFIX}${path}`;\n}\n\nfunction entryPathsFromKeys(keys: readonly string[]): WorkspacePath[] {\n return keys\n .filter((key) => key.startsWith(ENTRY_PREFIX))\n .map((key) => {\n const rawPath = key.slice(ENTRY_PREFIX.length);\n const path = parseWorkspacePath(rawPath);\n if (path !== rawPath) throw corrupt(`Non-canonical v2 entry key: ${key}.`);\n return path;\n });\n}\n\nasync function listEntryPaths(tx: IndexedDBFileSystemTransaction): Promise<WorkspacePath[]> {\n return entryPathsFromKeys(await tx.keys());\n}\n\nasync function readEntry(\n tx: IndexedDBFileSystemTransaction,\n path: WorkspacePath,\n): Promise<PersistedEntry | null> {\n const raw = await tx.get<unknown>(entryKey(path));\n return raw === null ? null : validateEntry(raw, path);\n}\n\nasync function readRequiredEntry(\n tx: IndexedDBFileSystemTransaction,\n path: WorkspacePath,\n): Promise<PersistedEntry> {\n const entry = await readEntry(tx, path);\n if (!entry) throw corrupt(`Missing v2 entry record: ${path}.`, path);\n return entry;\n}\n\nfunction validateEntry(value: unknown, expectedPath: WorkspacePath): PersistedEntry {\n if (!isRecord(value)) throw corrupt(`Corrupt v2 entry record: ${expectedPath}.`, expectedPath);\n const path = parseWorkspacePath(readString(value.path, 'entry path'));\n if (path !== expectedPath) throw corrupt(`V2 entry path does not match key: ${expectedPath}.`);\n if (value.schemaVersion !== ENTRY_SCHEMA_VERSION) {\n throw corrupt(`Unsupported v2 entry schema at ${expectedPath}.`, expectedPath);\n }\n const version = parseFileSystemVersion(value.version);\n const lastModified = readString(value.lastModified, 'lastModified');\n if (value.kind === 'directory') {\n return { schemaVersion: ENTRY_SCHEMA_VERSION, kind: 'directory', path, version, lastModified };\n }\n if (value.kind !== 'file') throw corrupt(`Unknown entry kind at ${expectedPath}.`, expectedPath);\n return {\n schemaVersion: ENTRY_SCHEMA_VERSION,\n kind: 'file',\n path,\n version,\n lastModified,\n data: validateBytes(value.data, expectedPath),\n };\n}\n\nasync function readState(tx: IndexedDBFileSystemTransaction): Promise<PersistedState | null> {\n const raw = await tx.get<unknown>(STATE_KEY);\n return raw === null ? null : validateState(raw);\n}\n\nasync function readRequiredState(tx: IndexedDBFileSystemTransaction): Promise<PersistedState> {\n const state = await readState(tx);\n if (!state) throw corrupt('IndexedDB v2 state record is missing.');\n return state;\n}\n\nfunction validateState(value: unknown): PersistedState {\n if (\n !isRecord(value) ||\n value.schemaVersion !== STATE_SCHEMA_VERSION ||\n (value.migrationVersion !== 1 && value.migrationVersion !== 2) ||\n typeof value.mutationCounter !== 'number' ||\n !Number.isSafeInteger(value.mutationCounter) ||\n value.mutationCounter < 0\n ) {\n throw corrupt('IndexedDB v2 state record is corrupt.');\n }\n return {\n schemaVersion: STATE_SCHEMA_VERSION,\n migrationVersion: value.migrationVersion,\n mutationCounter: value.mutationCounter,\n treeVersion: parseFileSystemVersion(value.treeVersion),\n };\n}\n\nasync function readLegacyDirectories(tx: IndexedDBFileSystemTransaction): Promise<WorkspacePath[]> {\n const raw = await tx.get<unknown>(LEGACY_DIRS_KEY);\n if (raw === null) return [];\n if (!Array.isArray(raw)) throw corrupt('Legacy directory index is corrupt.');\n const directories: WorkspacePath[] = [];\n for (const value of raw) {\n if (typeof value !== 'string') throw corrupt('Legacy directory index is corrupt.');\n const path = parseWorkspacePath(value);\n if (path) directories.push(path);\n }\n return directories;\n}\n\nfunction legacyPathsFromKeys(keys: readonly string[]): WorkspacePath[] {\n const paths = new Set<WorkspacePath>();\n for (const key of keys) {\n if (!key.startsWith(LEGACY_PREFIX) || key === LEGACY_DIRS_KEY) continue;\n const suffix = [LEGACY_CONTENT_SUFFIX, LEGACY_BINARY_SUFFIX, LEGACY_META_SUFFIX].find(\n (candidate) => key.endsWith(candidate),\n );\n if (!suffix) continue;\n const rawPath = key.slice(LEGACY_PREFIX.length, -suffix.length);\n try {\n const path = parseWorkspacePath(rawPath);\n if (path) paths.add(path);\n } catch {\n // Invalid legacy keys remain untouched. They are not valid v2 paths.\n }\n }\n return [...paths];\n}\n\nasync function readLegacyFile(\n tx: IndexedDBFileSystemTransaction,\n path: WorkspacePath,\n): Promise<{ content: string | null; binary: ArrayBuffer | null; metadata: FileMeta | null }> {\n const [rawContent, rawBinary, rawMetadata] = await Promise.all([\n tx.get<unknown>(`${LEGACY_PREFIX}${path}${LEGACY_CONTENT_SUFFIX}`),\n tx.get<unknown>(`${LEGACY_PREFIX}${path}${LEGACY_BINARY_SUFFIX}`),\n tx.get<unknown>(`${LEGACY_PREFIX}${path}${LEGACY_META_SUFFIX}`),\n ]);\n if (rawContent !== null && typeof rawContent !== 'string') {\n throw corrupt(`Legacy text payload is corrupt: ${path}.`, path);\n }\n return {\n content: rawContent,\n binary: rawBinary === null ? null : validateBytes(rawBinary, path),\n metadata: validateLegacyMetadata(rawMetadata, path),\n };\n}\n\nasync function readMarkerPaths(\n transaction: IndexedDBFileSystemTransaction,\n keys: readonly string[],\n prefix: string,\n validate: (value: unknown) => WorkspacePath,\n): Promise<Set<WorkspacePath>> {\n const paths = new Set<WorkspacePath>();\n for (const key of keys) {\n if (!key.startsWith(prefix)) continue;\n const expectedPath = parseWorkspacePath(key.slice(prefix.length));\n if (!expectedPath) throw corrupt(`Recovery marker cannot target the workspace root: ${key}.`);\n const value = await transaction.get<unknown>(key);\n const path = validate(value);\n if (path !== expectedPath)\n throw corrupt(`Recovery marker path does not match its key: ${key}.`);\n paths.add(path);\n }\n return paths;\n}\n\nfunction validateIgnoredLegacyPath(value: unknown): WorkspacePath {\n if (!isRecord(value) || value.schemaVersion !== 1 || typeof value.ignoredAt !== 'string') {\n throw corrupt('Ignored legacy recovery marker is corrupt.');\n }\n const path = parseWorkspacePath(readString(value.path, 'ignored legacy path'));\n if (!path) throw corrupt('Ignored legacy recovery marker cannot target the workspace root.');\n return path;\n}\n\nasync function assertNoLegacyConflict(\n transaction: IndexedDBFileSystemTransaction,\n path: WorkspacePath,\n operation: FsOperation,\n): Promise<void> {\n if ((await transaction.get<unknown>(legacyConflictKey(path))) === null) return;\n throw legacyConflictBlocked(path, operation);\n}\n\n/**\n * Refuse an operation that would move or delete a subtree holding quarantined\n * legacy data.\n *\n * Conflict records are keyed by absolute path and nothing rewrites those keys,\n * so relocating or deleting an ancestor strands the record: resolving it later\n * restores the legacy bytes at a path the user no longer has, recreating the\n * old tree around it (`createParents: true`). Descendants therefore have to\n * block the same way the target path itself does, until the user resolves or\n * discards the conflict.\n */\nasync function assertNoLegacyConflictInSubtree(\n transaction: IndexedDBFileSystemTransaction,\n path: WorkspacePath,\n operation: FsOperation,\n): Promise<void> {\n for (const key of await transaction.keys()) {\n if (!key.startsWith(LEGACY_CONFLICT_PREFIX)) continue;\n const conflictPath = parseWorkspacePath(key.slice(LEGACY_CONFLICT_PREFIX.length));\n if (conflictPath === path || workspacePathContains(path, conflictPath, false)) {\n throw legacyConflictBlocked(conflictPath, operation);\n }\n }\n}\n\nfunction legacyConflictBlocked(path: WorkspacePath, operation: FsOperation): FsError {\n return new FsError(\n 'conflict',\n 'Resolve the legacy migration conflict before mutating this path.',\n {\n operation,\n path,\n retryable: false,\n },\n );\n}\n\nfunction validateLegacyMetadata(value: unknown, path: WorkspacePath): FileMeta | null {\n if (value === null) return null;\n if (\n !isRecord(value) ||\n typeof value.name !== 'string' ||\n typeof value.path !== 'string' ||\n typeof value.size !== 'number' ||\n !Number.isFinite(value.size) ||\n typeof value.lastModified !== 'string'\n ) {\n throw corrupt(`Legacy metadata is corrupt: ${path}.`, path);\n }\n return {\n name: value.name,\n path: value.path,\n size: value.size,\n lastModified: value.lastModified,\n };\n}\n\nfunction validateLegacyConflict(value: unknown): PersistedLegacyConflict {\n if (!isRecord(value)) {\n throw corrupt('Legacy migration conflict record is corrupt.');\n }\n const path = parseWorkspacePath(readString(value.path, 'legacy conflict path'));\n if (!path) throw corrupt('Legacy migration conflict cannot target the workspace root.');\n\n if (value.schemaVersion === LEGACY_CONFLICT_SCHEMA_VERSION_V1) {\n const reason = validateLegacyConflictReason(value.reason);\n const candidate: PersistedLegacyRecoveryCandidate = {\n kind: 'file',\n reason,\n text: value.text === null ? null : readString(value.text, 'legacy conflict text'),\n binary: value.binary === null ? null : validateBytes(value.binary, path),\n metadata: validateLegacyMetadata(value.metadata, path),\n detectedAt: readString(value.detectedAt, 'legacy conflict detectedAt'),\n };\n return {\n schemaVersion: LEGACY_CONFLICT_SCHEMA_VERSION,\n path,\n candidates: Object.freeze([candidate]),\n };\n }\n if (value.schemaVersion !== LEGACY_CONFLICT_SCHEMA_VERSION || !Array.isArray(value.candidates)) {\n throw corrupt('Legacy migration conflict record is corrupt.');\n }\n const candidates = value.candidates.map((candidate) =>\n validateLegacyRecoveryCandidate(candidate, path),\n );\n if (candidates.length === 0) throw corrupt('Legacy migration conflict has no candidates.', path);\n return {\n schemaVersion: LEGACY_CONFLICT_SCHEMA_VERSION,\n path,\n candidates: Object.freeze(candidates),\n };\n}\n\nfunction toPublicLegacyConflict(\n conflict: PersistedLegacyConflict,\n): IndexedDBLegacyMigrationConflict {\n const candidates = conflict.candidates.map(toPublicLegacyCandidate);\n const latest = candidates[candidates.length - 1]!;\n return Object.freeze({\n path: parseWorkspacePath(conflict.path),\n reason: latest.reason,\n kind: latest.kind,\n text: latest.text,\n binary: latest.binary,\n metadata: latest.metadata,\n detectedAt: latest.detectedAt,\n candidates: Object.freeze(candidates),\n });\n}\n\nfunction validateLegacyRecoveryCandidate(\n value: unknown,\n path: WorkspacePath,\n): PersistedLegacyRecoveryCandidate {\n if (!isRecord(value) || (value.kind !== 'file' && value.kind !== 'directory')) {\n throw corrupt('Legacy recovery candidate is corrupt.', path);\n }\n const kind = value.kind;\n const text = value.text === null ? null : readString(value.text, 'legacy recovery text');\n const binary = value.binary === null ? null : validateBytes(value.binary, path);\n const metadata = validateLegacyMetadata(value.metadata, path);\n if (kind === 'directory' && (text !== null || binary !== null || metadata !== null)) {\n throw corrupt('A legacy directory recovery candidate contains file data.', path);\n }\n return {\n kind,\n reason: validateLegacyConflictReason(value.reason),\n text,\n binary,\n metadata,\n detectedAt: readString(value.detectedAt, 'legacy recovery detectedAt'),\n };\n}\n\nfunction validateLegacyConflictReason(value: unknown): IndexedDBLegacyConflictReason {\n if (\n value === 'dual-payload' ||\n value === 'kind-collision' ||\n value === 'authority-collision' ||\n value === 'stale-client-write'\n ) {\n return value;\n }\n throw corrupt('Legacy recovery reason is invalid.');\n}\n\nfunction toPublicLegacyCandidate(\n candidate: PersistedLegacyRecoveryCandidate,\n): IndexedDBLegacyRecoveryCandidate {\n return Object.freeze({\n kind: candidate.kind,\n reason: candidate.reason,\n text: candidate.text,\n binary: candidate.binary ? copyBytes(candidate.binary) : null,\n metadata: candidate.metadata ? Object.freeze({ ...candidate.metadata }) : null,\n detectedAt: candidate.detectedAt,\n });\n}\n\nasync function appendLegacyConflict(\n transaction: IndexedDBFileSystemTransaction,\n path: WorkspacePath,\n candidate: PersistedLegacyRecoveryCandidate,\n): Promise<void> {\n const key = legacyConflictKey(path);\n const raw = await transaction.get<unknown>(key);\n const existing = raw === null ? null : validateLegacyConflict(raw);\n if (existing?.candidates.some((item) => recoveryCandidatesEqual(item, candidate))) return;\n const candidates = [...(existing?.candidates ?? []), copyRecoveryCandidate(candidate)];\n await transaction.put(key, {\n schemaVersion: LEGACY_CONFLICT_SCHEMA_VERSION,\n path,\n candidates,\n } satisfies PersistedLegacyConflict);\n}\n\nfunction fileRecoveryCandidate(\n legacy: { content: string | null; binary: ArrayBuffer | null; metadata: FileMeta | null },\n reason: IndexedDBLegacyConflictReason,\n detectedAt: string,\n): PersistedLegacyRecoveryCandidate {\n return {\n kind: 'file',\n reason,\n text: legacy.content,\n binary: legacy.binary ? copyBytes(legacy.binary) : null,\n metadata: legacy.metadata ? { ...legacy.metadata } : null,\n detectedAt,\n };\n}\n\nfunction directoryRecoveryCandidate(\n reason: IndexedDBLegacyConflictReason,\n detectedAt: string,\n): PersistedLegacyRecoveryCandidate {\n return { kind: 'directory', reason, text: null, binary: null, metadata: null, detectedAt };\n}\n\nfunction copyRecoveryCandidate(\n candidate: PersistedLegacyRecoveryCandidate,\n): PersistedLegacyRecoveryCandidate {\n return {\n ...candidate,\n binary: candidate.binary ? copyBytes(candidate.binary) : null,\n metadata: candidate.metadata ? { ...candidate.metadata } : null,\n };\n}\n\nfunction recoveryCandidatesEqual(\n left: PersistedLegacyRecoveryCandidate,\n right: PersistedLegacyRecoveryCandidate,\n): boolean {\n return (\n left.kind === right.kind &&\n left.text === right.text &&\n nullableBytesEqual(left.binary, right.binary) &&\n nullableMetadataEqual(left.metadata, right.metadata)\n );\n}\n\nfunction nullableBytesEqual(left: ArrayBuffer | null, right: ArrayBuffer | null): boolean {\n if (left === null || right === null) return left === right;\n return bytesEqual(left, right);\n}\n\nfunction nullableMetadataEqual(left: FileMeta | null, right: FileMeta | null): boolean {\n if (left === null || right === null) return left === right;\n return (\n left.name === right.name &&\n left.path === right.path &&\n left.size === right.size &&\n left.lastModified === right.lastModified\n );\n}\n\nfunction legacyPayloadsMatchEntry(\n legacy: { content: string | null; binary: ArrayBuffer | null; metadata: FileMeta | null },\n entry: PersistedFileEntry,\n): boolean {\n if (legacy.content === null && legacy.binary === null) return false;\n return (\n (legacy.content === null || bytesEqual(new TextEncoder().encode(legacy.content), entry.data)) &&\n (legacy.binary === null || bytesEqual(legacy.binary, entry.data))\n );\n}\n\nfunction hasFileAncestor(\n entries: ReadonlyMap<WorkspacePath, PersistedEntry>,\n path: WorkspacePath,\n): boolean {\n return parentChainWithRoot(path).some((parent) => entries.get(parent)?.kind === 'file');\n}\n\nfunction legacyOpaqueKey(key: string): string {\n return `${LEGACY_OPAQUE_PREFIX}${encodeURIComponent(key)}`;\n}\n\n/**\n * Read an archived opaque record, upgrading the untimestamped v1 shape.\n *\n * v1 recorded bare values with no archival time. Those values are still the\n * caller's data, so they are surfaced with a null `archivedAt` rather than\n * discarded or stamped with a time nobody observed.\n */\nfunction validateLegacyOpaqueRecord(\n value: unknown,\n archiveKey: string,\n): PersistedLegacyOpaqueRecord {\n if (!isRecord(value) || !Array.isArray(value.values)) {\n throw corrupt(`Archived legacy record is corrupt: ${archiveKey}.`);\n }\n const key = readString(value.key, 'archived legacy key');\n if (legacyOpaqueKey(key) !== archiveKey) {\n throw corrupt(`Archived legacy record key does not match its key: ${archiveKey}.`);\n }\n if (value.schemaVersion === LEGACY_OPAQUE_SCHEMA_VERSION_V1) {\n return {\n schemaVersion: LEGACY_OPAQUE_SCHEMA_VERSION,\n key,\n values: Object.freeze(\n value.values.map(\n (item) => ({ value: item, archivedAt: null }) satisfies PersistedLegacyOpaqueValue,\n ),\n ),\n };\n }\n if (value.schemaVersion !== LEGACY_OPAQUE_SCHEMA_VERSION) {\n throw corrupt(`Unsupported archived legacy record schema: ${archiveKey}.`);\n }\n const values = value.values.map((item) => {\n if (!isRecord(item)) throw corrupt(`Archived legacy value is corrupt: ${archiveKey}.`);\n return {\n value: item.value,\n // A v2 record legitimately carries null here for values it inherited from\n // the untimestamped v1 shape, so this must stay nullable on the way back\n // in or re-archiving a v1 record would make it permanently unreadable.\n archivedAt:\n item.archivedAt === null ? null : readString(item.archivedAt, 'archived legacy timestamp'),\n } satisfies PersistedLegacyOpaqueValue;\n });\n if (values.length === 0) throw corrupt(`Archived legacy record has no values: ${archiveKey}.`);\n return { schemaVersion: LEGACY_OPAQUE_SCHEMA_VERSION, key, values: Object.freeze(values) };\n}\n\n/** Best-effort size of an uninterpreted value; null when it is not sized. */\nfunction opaqueValueByteLength(value: unknown): number | null {\n if (value instanceof ArrayBuffer) return value.byteLength;\n if (ArrayBuffer.isView(value)) return value.byteLength;\n if (typeof value === 'string') return new TextEncoder().encode(value).byteLength;\n return null;\n}\n\nfunction toOpaqueSummary(record: PersistedLegacyOpaqueRecord): IndexedDBLegacyOpaqueRecordSummary {\n // A total that silently omitted unsized values would understate the quota\n // this record holds, so an unsized value makes the whole total unknown.\n let byteLength: number | null = 0;\n for (const item of record.values) {\n const size = opaqueValueByteLength(item.value);\n byteLength = size === null || byteLength === null ? null : byteLength + size;\n }\n const stamps = record.values.map((item) => item.archivedAt);\n return Object.freeze({\n key: record.key,\n valueCount: record.values.length,\n byteLength,\n firstArchivedAt: stamps[0] ?? null,\n lastArchivedAt: stamps[stamps.length - 1] ?? null,\n });\n}\n\nfunction toPublicOpaqueRecord(record: PersistedLegacyOpaqueRecord): IndexedDBLegacyOpaqueRecord {\n return Object.freeze({\n ...toOpaqueSummary(record),\n values: Object.freeze(\n record.values.map((item) =>\n Object.freeze({\n value: item.value instanceof ArrayBuffer ? copyBytes(item.value) : item.value,\n byteLength: opaqueValueByteLength(item.value),\n archivedAt: item.archivedAt,\n }),\n ),\n ),\n });\n}\n\nasync function deleteLegacyNamespace(\n transaction: IndexedDBFileSystemTransaction,\n keys: readonly string[],\n archivedAt: string,\n): Promise<void> {\n for (const key of keys) {\n if (key.startsWith(LEGACY_PREFIX) && !isRecognizedLegacyKey(key)) {\n const archiveKey = legacyOpaqueKey(key);\n const existing = await transaction.get<unknown>(archiveKey);\n const values =\n existing === null ? [] : validateLegacyOpaqueRecord(existing, archiveKey).values;\n await transaction.put(archiveKey, {\n schemaVersion: LEGACY_OPAQUE_SCHEMA_VERSION,\n key,\n values: [...values, { value: await transaction.get<unknown>(key), archivedAt }],\n } satisfies PersistedLegacyOpaqueRecord);\n }\n if (key.startsWith(LEGACY_PREFIX) || key.startsWith(LEGACY_IGNORED_PREFIX))\n await transaction.delete(key);\n }\n}\n\nfunction isRecognizedLegacyKey(key: string): boolean {\n if (key === LEGACY_DIRS_KEY) return true;\n const suffix = [LEGACY_CONTENT_SUFFIX, LEGACY_BINARY_SUFFIX, LEGACY_META_SUFFIX].find((item) =>\n key.endsWith(item),\n );\n if (!suffix) return false;\n const rawPath = key.slice(LEGACY_PREFIX.length, -suffix.length);\n try {\n const path = parseWorkspacePath(rawPath);\n return path !== WORKSPACE_ROOT && path === rawPath;\n } catch {\n return false;\n }\n}\n\nfunction selectLegacyPayload(\n conflict: PersistedLegacyConflict,\n resolution: Exclude<IndexedDBLegacyConflictResolution, 'v2'>,\n path: WorkspacePath,\n): { readonly kind: 'file'; readonly data: ArrayBuffer } | { readonly kind: 'directory' } {\n const payload = typeof resolution === 'string' ? resolution : resolution.payload;\n const eligible =\n typeof resolution === 'string'\n ? conflict.candidates.filter(\n (candidate) =>\n candidate.kind === 'file' &&\n (payload === 'text' ? candidate.text !== null : candidate.binary !== null),\n )\n : [conflict.candidates[resolution.candidate]].filter(\n (candidate): candidate is PersistedLegacyRecoveryCandidate => candidate !== undefined,\n );\n if (eligible.length !== 1) {\n throw new FsError(\n 'conflict',\n 'Choose an explicit recovery candidate because multiple legacy versions are quarantined.',\n { operation: 'write', path, retryable: false },\n );\n }\n const candidate = eligible[0]!;\n if (payload === 'directory') {\n if (candidate.kind !== 'directory') {\n throw new FsError('type-mismatch', 'The selected recovery candidate is not a directory.', {\n operation: 'write',\n path,\n });\n }\n return { kind: 'directory' };\n }\n if (candidate.kind !== 'file') {\n throw new FsError('type-mismatch', 'The selected recovery candidate is a directory.', {\n operation: 'write',\n path,\n });\n }\n const data =\n payload === 'text'\n ? candidate.text === null\n ? null\n : new TextEncoder().encode(candidate.text).buffer\n : candidate.binary;\n if (data === null) {\n throw new FsError('type-mismatch', `The selected candidate has no ${payload} payload.`, {\n operation: 'write',\n path,\n });\n }\n return { kind: 'file', data: copyBytes(data) };\n}\n\nfunction addParentDirectories(\n entries: Map<WorkspacePath, PersistedEntry>,\n path: WorkspacePath,\n version: FileSystemVersion,\n lastModified: string,\n): void {\n for (const parent of parentChainWithRoot(path)) {\n if (!entries.has(parent)) entries.set(parent, directoryRecord(parent, version, lastModified));\n }\n}\n\nfunction directoryRecord(\n path: WorkspacePath,\n version: FileSystemVersion,\n lastModified: string,\n): PersistedDirectoryEntry {\n return {\n schemaVersion: ENTRY_SCHEMA_VERSION,\n kind: 'directory',\n path,\n version,\n lastModified,\n };\n}\n\nfunction withPathAndVersion(\n entry: PersistedEntry,\n path: WorkspacePath,\n next: MutationVersion,\n): PersistedEntry {\n return entry.kind === 'file'\n ? {\n schemaVersion: ENTRY_SCHEMA_VERSION,\n kind: 'file',\n path,\n data: copyBytes(entry.data),\n version: next.version,\n lastModified: next.lastModified,\n }\n : directoryRecord(path, next.version, next.lastModified);\n}\n\nfunction copyEntry(entry: PersistedEntry): PersistedEntry {\n return entry.kind === 'file' ? { ...entry, data: copyBytes(entry.data) } : { ...entry };\n}\n\nfunction toEntrySnapshot(entry: PersistedEntry): FileSystemEntrySnapshot {\n return entry.kind === 'file' ? toFileSnapshot(entry) : toDirectorySnapshot(entry);\n}\n\nfunction toFileSnapshot(entry: PersistedFileEntry): FileSystemFileSnapshot {\n return Object.freeze({\n kind: 'file',\n path: parseWorkspacePath(entry.path),\n name: workspacePathBasename(parseWorkspacePath(entry.path)),\n size: entry.data.byteLength,\n version: parseFileSystemVersion(entry.version),\n lastModified: entry.lastModified,\n });\n}\n\nfunction toDirectorySnapshot(entry: PersistedDirectoryEntry): FileSystemDirectorySnapshot {\n const path = parseWorkspacePath(entry.path);\n return Object.freeze({\n kind: 'directory',\n path,\n name: workspacePathBasename(path),\n size: null,\n version: parseFileSystemVersion(entry.version),\n lastModified: entry.lastModified,\n });\n}\n\nfunction validateBytes(value: unknown, path: WorkspacePath): ArrayBuffer {\n if (value instanceof ArrayBuffer) return copyBytes(value);\n if (value instanceof Uint8Array) return copyBytes(value);\n throw corrupt(`Stored file bytes are corrupt: ${path}.`, path);\n}\n\nfunction readString(value: unknown, label: string): string {\n if (typeof value !== 'string') throw corrupt(`Invalid ${label}.`);\n return value;\n}\n\nfunction corrupt(message: string, path?: WorkspacePath): FsError {\n return new FsError('io', message, { operation: 'read', path, retryable: false });\n}\n","/**\n * Legacy FileSystemProvider facade over the revisioned IndexedDB authority.\n *\n * The old `fs:*` namespace is migration input only. Keeping this facade as an\n * adapter prevents current callers from recreating a second persistent source\n * of truth while the workspace moves to FileSystemProviderV2.\n */\n\nimport type { FileCommitResult, FileMeta, FileSystemEntry, FileSystemProvider } from './types.js';\nimport { FsError, type FsOperation } from './fs-error.js';\nimport { parseWorkspacePath, type WorkspacePath } from './workspace-path.js';\nimport {\n RawIndexedDBFileSystemStore,\n indexedDBWorkspaceDatabaseName,\n type IndexedDBFileSystemStore,\n} from './indexeddb-store.js';\nimport { IndexedDBFileSystemProviderV2 } from './indexeddb-provider-v2.js';\nimport { decodeUtf8Text } from './utf8.js';\n\nexport interface IndexedDBFileSystemProviderOptions {\n /** Injectable transaction store for deterministic fault/concurrency tests. */\n store?: IndexedDBFileSystemStore;\n /** Injectable metadata clock. */\n now?: () => Date;\n}\n\nexport class IndexedDBFileSystemProvider implements FileSystemProvider {\n public readonly id: string;\n public readonly label: string;\n public readonly v2: IndexedDBFileSystemProviderV2;\n\n private disposed = false;\n\n public constructor(id: string, label: string, options: IndexedDBFileSystemProviderOptions = {}) {\n this.id = id;\n this.label = label;\n const store =\n options.store ?? new RawIndexedDBFileSystemStore(indexedDBWorkspaceDatabaseName(id), 'files');\n this.v2 = new IndexedDBFileSystemProviderV2(id, label, {\n store,\n now: options.now,\n closeStoreOnDispose: true,\n });\n }\n\n /** Release the underlying database connection after accepted work settles. */\n public dispose(): Promise<void> {\n this.disposed = true;\n return this.v2.dispose();\n }\n\n public async readFile(path: string): Promise<string | null> {\n this.assertOpen('read');\n const canonical = this.path(path);\n const read = await this.v2.readFile(canonical);\n return read ? this.decode(read.data, canonical, 'read') : null;\n }\n\n public async writeFile(path: string, content: string): Promise<void> {\n this.assertOpen('write');\n await this.v2.writeFile(this.path(path), new TextEncoder().encode(content), {\n createParents: true,\n });\n }\n\n public async commitFile(\n path: string,\n content: string,\n expectedContent: string | null,\n ): Promise<FileCommitResult> {\n this.assertOpen('write');\n const canonical = this.path(path);\n const current = await this.v2.readFile(canonical);\n const currentContent = current ? this.decode(current.data, canonical, 'write') : null;\n if (currentContent !== expectedContent && currentContent !== content) {\n return {\n status: 'conflict',\n content: currentContent,\n version: current?.entry.version ?? null,\n };\n }\n\n try {\n const committed = await this.v2.writeFile(canonical, new TextEncoder().encode(content), {\n createParents: true,\n expectedVersion: current?.entry.version ?? null,\n });\n return { status: 'committed', version: committed.version };\n } catch (error: unknown) {\n if (!(error instanceof FsError) || error.code !== 'conflict') throw error;\n const latest = await this.v2.readFile(canonical);\n return {\n status: 'conflict',\n content: latest ? this.decode(latest.data, canonical, 'write') : null,\n version: latest?.entry.version ?? null,\n };\n }\n }\n\n public async delete(path: string): Promise<void> {\n this.assertOpen('remove');\n await this.v2.remove(this.path(path), {\n recursive: true,\n missing: 'ignore',\n });\n }\n\n public async rename(oldPath: string, newPath: string): Promise<void> {\n this.assertOpen('move');\n await this.v2.move(this.path(oldPath), this.path(newPath), {\n createParents: true,\n });\n }\n\n public async readDirectory(path: string): Promise<FileSystemEntry[]> {\n this.assertOpen('list');\n try {\n const entries = await this.v2.readDirectory(this.path(path));\n return entries.map((entry) => ({\n kind: entry.kind,\n name: entry.name,\n path: entry.path,\n }));\n } catch (error: unknown) {\n if (error instanceof FsError && error.code === 'not-found') return [];\n throw error;\n }\n }\n\n public async exists(path: string): Promise<boolean> {\n this.assertOpen('stat');\n return (await this.v2.stat(this.path(path))) !== null;\n }\n\n public async createDirectory(path: string): Promise<void> {\n this.assertOpen('create-directory');\n await this.v2.createDirectory(this.path(path), {\n createParents: true,\n mode: 'ensure',\n });\n }\n\n public async stat(path: string): Promise<FileMeta | null> {\n this.assertOpen('stat');\n const entry = await this.v2.stat(this.path(path));\n if (!entry || entry.kind !== 'file') return null;\n return {\n name: entry.name,\n path: entry.path,\n size: entry.size,\n lastModified: entry.lastModified,\n };\n }\n\n public async readBinary(path: string): Promise<ArrayBuffer | null> {\n this.assertOpen('read');\n return (await this.v2.readFile(this.path(path)))?.data ?? null;\n }\n\n public async writeBinary(path: string, data: ArrayBuffer | Uint8Array): Promise<void> {\n this.assertOpen('write');\n await this.v2.writeFile(this.path(path), data, { createParents: true });\n }\n\n /**\n * Canonicalize only. Root policy is the v2 authority's to state: it accepts\n * the root wherever the root is a legitimate target (`stat`, `readDirectory`,\n * `createDirectory`) and rejects it with one consistent code and message\n * everywhere else. Re-deriving that policy here is how this facade previously\n * drifted from both v2 and its sibling facades.\n */\n private path(path: string): WorkspacePath {\n return parseWorkspacePath(path);\n }\n\n /**\n * Byte-authoritative entries may hold payloads that are not valid UTF-8. A\n * lossy decode would hand the caller replacement characters that a later save\n * writes back over the user's original bytes, so surface the fault instead.\n */\n private decode(data: ArrayBuffer, path: WorkspacePath, operation: FsOperation): string {\n return decodeUtf8Text(data, { label: 'The file', operation, path });\n }\n\n private assertOpen(operation: FsOperation): void {\n if (!this.disposed) return;\n throw new FsError('disposed', 'Filesystem provider is disposed.', { operation });\n }\n}\n","/**\n * IndexedDBContentContainer — a ContentContainer backed by IndexedDB.\n *\n * Uses a dedicated IndexedDBFileSystemProvider instance (separate store)\n * to persist media files across page refreshes.\n */\n\nimport type { ContentContainer, ContentEntry } from '@bendyline/squisq/storage';\nimport { findDocumentPath } from '@bendyline/squisq/storage';\nimport { IndexedDBFileSystemProviderV2 } from './indexeddb-provider-v2.js';\nimport { parseWorkspacePath, WORKSPACE_ROOT } from './workspace-path.js';\nimport { guessMimeType } from './internal/mime.js';\n\n// ── Implementation ─────────────────────────────────────────────────\n\nexport class IndexedDBContentContainer implements ContentContainer {\n private readonly provider: IndexedDBFileSystemProviderV2;\n\n constructor(workspaceId: string) {\n this.provider = new IndexedDBFileSystemProviderV2(`${workspaceId}-media`, 'Media Storage');\n }\n\n async readFile(path: string): Promise<ArrayBuffer | null> {\n return (await this.provider.readFile(parseWorkspacePath(path)))?.data ?? null;\n }\n\n async writeFile(path: string, data: ArrayBuffer | Uint8Array, _mimeType?: string): Promise<void> {\n await this.provider.writeFile(parseWorkspacePath(path), data, {\n mode: 'upsert',\n createParents: true,\n });\n }\n\n async removeFile(path: string): Promise<void> {\n await this.provider.remove(parseWorkspacePath(path), { missing: 'ignore' });\n }\n\n async listFiles(prefix?: string): Promise<ContentEntry[]> {\n const entries: ContentEntry[] = [];\n const walk = async (dir: string) => {\n const children = await this.provider.readDirectory(parseWorkspacePath(dir));\n for (const child of children) {\n if (child.kind === 'directory') {\n await walk(child.path);\n } else {\n const filePath = child.path;\n if (prefix && !filePath.startsWith(prefix)) continue;\n entries.push({\n path: filePath,\n mimeType: guessMimeType(filePath),\n size: child.size,\n });\n }\n }\n };\n await walk(WORKSPACE_ROOT);\n return entries;\n }\n\n async exists(path: string): Promise<boolean> {\n return (await this.provider.stat(parseWorkspacePath(path))) !== null;\n }\n\n async getDocumentPath(): Promise<string | null> {\n return findDocumentPath(await this.listFiles());\n }\n\n async readDocument(): Promise<string | null> {\n const docPath = await this.getDocumentPath();\n if (!docPath) return null;\n const data = await this.readFile(docPath);\n if (!data) return null;\n return new TextDecoder().decode(data);\n }\n\n async writeDocument(markdown: string, filename?: string): Promise<void> {\n const name = filename ?? 'index.md';\n const data = new TextEncoder().encode(markdown);\n await this.writeFile(name, data, 'text/markdown');\n }\n\n /** Release the IndexedDB connection when a long-lived container is retired. */\n async dispose(): Promise<void> {\n await this.provider.dispose();\n }\n}\n","/**\n * Extension-to-MIME mapping shared by the ContentContainer implementations.\n *\n * Both containers describe the same workspace media files, so a format that\n * only one of them recognises would report a different `mimeType` depending on\n * whether the workspace happens to be IndexedDB- or filesystem-backed.\n */\n\nconst EXTENSION_MIME_MAP: Record<string, string> = {\n '.md': 'text/markdown',\n '.txt': 'text/plain',\n '.json': 'application/json',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.png': 'image/png',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.webp': 'image/webp',\n '.avif': 'image/avif',\n '.mp4': 'video/mp4',\n '.webm': 'video/webm',\n '.mp3': 'audio/mpeg',\n '.wav': 'audio/wav',\n '.ogg': 'audio/ogg',\n};\n\n/** Best-effort MIME type from a path's extension. */\nexport function guessMimeType(path: string): string {\n const dot = path.lastIndexOf('.');\n if (dot === -1) return 'application/octet-stream';\n const ext = path.slice(dot).toLowerCase();\n return EXTENSION_MIME_MAP[ext] ?? 'application/octet-stream';\n}\n"],"mappings":"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","names":["missingParents","next","candidate"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
tryParseWorkspacePath
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-JS6XFWQK.js";
|
|
4
4
|
|
|
5
5
|
// src/mcp/types.ts
|
|
6
6
|
var DOCBLOCKS_MCP_WIRE_VERSION = 1;
|
|
@@ -799,4 +799,4 @@ export {
|
|
|
799
799
|
parseComparisonResult,
|
|
800
800
|
parseMaterializationOptions
|
|
801
801
|
};
|
|
802
|
-
//# sourceMappingURL=chunk-
|
|
802
|
+
//# sourceMappingURL=chunk-B56KWCSE.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/host/filesystem-v2.ts","../src/host/index.ts"],"sourcesContent":["import type {\n FileSystemCreateDirectoryOptions,\n FileSystemDirectorySnapshot,\n FileSystemEntrySnapshot,\n FileSystemFileRead,\n FileSystemFileSnapshot,\n FileSystemMoveOptions,\n FileSystemProviderCapabilities,\n FileSystemRemoveOptions,\n FileSystemRemoveResult,\n FileSystemSnapshot,\n FileSystemWatchEvent,\n FileSystemWriteOptions,\n SerializedFsError,\n WorkspacePath,\n} from '../filesystem/index.js';\n\n/** Stable capabilities shared by the Electron v2 client and native backend. */\nexport const ELECTRON_FILE_SYSTEM_V2_CAPABILITIES: FileSystemProviderCapabilities = Object.freeze({\n writeAtomicity: 'process',\n moveAtomicity: 'process',\n snapshotAtomicity: 'process',\n conditionalWrite: 'process',\n recursiveRemove: true,\n watch: true,\n caseSensitivity: 'platform',\n symlinkPolicy: 'follow-contained',\n durability: 'best-effort',\n});\n\n/** Explicit result envelope; Electron does not preserve custom Error fields. */\nexport type HostFileSystemV2Result<T> =\n | { readonly ok: true; readonly value: T }\n | { readonly ok: false; readonly error: SerializedFsError };\n\nexport interface HostFileSystemV2OpenRequest {\n readonly instanceId: string;\n /** Main-owned persisted workspace authority, never an absolute path. */\n readonly providerId: string;\n readonly label: string;\n}\n\nexport type HostFileSystemV2WatchMessage =\n | {\n readonly instanceId: string;\n readonly subscriptionId: string;\n readonly kind: 'event';\n readonly event: FileSystemWatchEvent;\n }\n | {\n readonly instanceId: string;\n readonly subscriptionId: string;\n readonly kind: 'error';\n readonly error: SerializedFsError;\n };\n\n/** Wire-level filesystem v2 API exposed by preload. */\nexport interface DocBlocksHostFsV2API {\n open(\n request: HostFileSystemV2OpenRequest,\n ): Promise<HostFileSystemV2Result<FileSystemProviderCapabilities>>;\n stat(\n instanceId: string,\n path: WorkspacePath,\n ): Promise<HostFileSystemV2Result<FileSystemEntrySnapshot | null>>;\n readFile(\n instanceId: string,\n path: WorkspacePath,\n ): Promise<HostFileSystemV2Result<FileSystemFileRead | null>>;\n readDirectory(\n instanceId: string,\n path: WorkspacePath,\n ): Promise<HostFileSystemV2Result<readonly FileSystemEntrySnapshot[]>>;\n writeFile(\n instanceId: string,\n path: WorkspacePath,\n data: ArrayBuffer | Uint8Array,\n options?: FileSystemWriteOptions,\n ): Promise<HostFileSystemV2Result<FileSystemFileSnapshot>>;\n createDirectory(\n instanceId: string,\n path: WorkspacePath,\n options?: FileSystemCreateDirectoryOptions,\n ): Promise<HostFileSystemV2Result<FileSystemDirectorySnapshot>>;\n remove(\n instanceId: string,\n path: WorkspacePath,\n options?: FileSystemRemoveOptions,\n ): Promise<HostFileSystemV2Result<FileSystemRemoveResult>>;\n move(\n instanceId: string,\n oldPath: WorkspacePath,\n newPath: WorkspacePath,\n options?: FileSystemMoveOptions,\n ): Promise<HostFileSystemV2Result<FileSystemEntrySnapshot>>;\n snapshot(instanceId: string): Promise<HostFileSystemV2Result<FileSystemSnapshot>>;\n watchSubscribe(instanceId: string, subscriptionId: string): Promise<HostFileSystemV2Result<null>>;\n watchUnsubscribe(\n instanceId: string,\n subscriptionId: string,\n ): Promise<HostFileSystemV2Result<null>>;\n dispose(instanceId: string): Promise<HostFileSystemV2Result<null>>;\n onWatchMessage(listener: (message: HostFileSystemV2WatchMessage) => void): () => void;\n}\n","/**\n * Host bridge — shared types + runtime access for the Electron desktop\n * host. The renderer calls `getDocBlocksHost()` to reach the preload\n * contextBridge; `isElectronHost()` gates desktop-only UI branches.\n */\n\nexport type {\n DocBlocksHostAPI,\n DocBlocksHostFsAPI,\n DocBlocksHostExternalAPI,\n DocBlocksHostWorkspacesAPI,\n DocBlocksHostShellAPI,\n DocBlocksHostExportAPI,\n DocBlocksHostFfmpegAPI,\n DocBlocksHostUpdaterAPI,\n DocBlocksHostLifecycleAPI,\n ElectronWorkspaceInfo,\n ExternalBinaryCommitResult,\n HostCloseReason,\n HostEnvironment,\n HostExportTargetGrant,\n HostPrepareCloseRequest,\n HostPrepareCloseResult,\n MenuCommand,\n OpenRequest,\n UpdateInstallResult,\n UpdaterStatus,\n} from './types.js';\n\nexport type {\n DocBlocksHostGitAPI,\n GitBranchInfo,\n GitCapabilities,\n GitCloneHandle,\n GitCloneProgress,\n GitError,\n GitErrorCode,\n GitFileAtRevision,\n GitFileChange,\n GitFileStatusCode,\n GitLogEntry,\n GitLogOptions,\n GitRemoteInfo,\n GitRepoDetection,\n GitResult,\n GitRevision,\n GitStatus,\n} from './git.js';\n\nexport {\n ELECTRON_FILE_SYSTEM_V2_CAPABILITIES,\n type DocBlocksHostFsV2API,\n type HostFileSystemV2OpenRequest,\n type HostFileSystemV2Result,\n type HostFileSystemV2WatchMessage,\n} from './filesystem-v2.js';\n\nexport {\n HOST_WIRE_LIMITS,\n isBoundedBytePayload,\n isBoundedString,\n isTrustedRendererUrl,\n parseExternalHttpUrl,\n parseOpenRequest,\n} from './wire-policy.js';\n\nimport type { DocBlocksHostAPI } from './types.js';\n\n/** True when running inside the Electron desktop shell. */\nexport function isElectronHost(): boolean {\n if (typeof globalThis === 'undefined') return false;\n const host = (globalThis as { docBlocksHost?: unknown }).docBlocksHost;\n return (\n typeof host === 'object' &&\n host !== null &&\n typeof (host as { fs?: unknown }).fs === 'object' &&\n (host as { fs?: unknown }).fs !== null\n );\n}\n\n/** Return the host API, or throw if not running under Electron. */\nexport function getDocBlocksHost(): DocBlocksHostAPI {\n const host = (globalThis as { docBlocksHost?: DocBlocksHostAPI }).docBlocksHost;\n if (!host) {\n throw new Error('docBlocksHost is not available — not running under Electron?');\n }\n return host;\n}\n\n/** Return the host API, or null if not running under Electron. */\nexport function maybeGetDocBlocksHost(): DocBlocksHostAPI | null {\n return (globalThis as { docBlocksHost?: DocBlocksHostAPI }).docBlocksHost ?? null;\n}\n"],"mappings":";AAkBO,IAAM,uCAAuE,OAAO,OAAO;AAAA,EAChG,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,OAAO;AAAA,EACP,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,YAAY;AACd,CAAC;;;
|
|
1
|
+
{"version":3,"sources":["../src/host/filesystem-v2.ts","../src/host/index.ts"],"sourcesContent":["import type {\n FileSystemCreateDirectoryOptions,\n FileSystemDirectorySnapshot,\n FileSystemEntrySnapshot,\n FileSystemFileRead,\n FileSystemFileSnapshot,\n FileSystemMoveOptions,\n FileSystemProviderCapabilities,\n FileSystemRemoveOptions,\n FileSystemRemoveResult,\n FileSystemSnapshot,\n FileSystemWatchEvent,\n FileSystemWriteOptions,\n SerializedFsError,\n WorkspacePath,\n} from '../filesystem/index.js';\n\n/** Stable capabilities shared by the Electron v2 client and native backend. */\nexport const ELECTRON_FILE_SYSTEM_V2_CAPABILITIES: FileSystemProviderCapabilities = Object.freeze({\n writeAtomicity: 'process',\n moveAtomicity: 'process',\n snapshotAtomicity: 'process',\n conditionalWrite: 'process',\n recursiveRemove: true,\n watch: true,\n caseSensitivity: 'platform',\n symlinkPolicy: 'follow-contained',\n durability: 'best-effort',\n});\n\n/** Explicit result envelope; Electron does not preserve custom Error fields. */\nexport type HostFileSystemV2Result<T> =\n | { readonly ok: true; readonly value: T }\n | { readonly ok: false; readonly error: SerializedFsError };\n\nexport interface HostFileSystemV2OpenRequest {\n readonly instanceId: string;\n /** Main-owned persisted workspace authority, never an absolute path. */\n readonly providerId: string;\n readonly label: string;\n}\n\nexport type HostFileSystemV2WatchMessage =\n | {\n readonly instanceId: string;\n readonly subscriptionId: string;\n readonly kind: 'event';\n readonly event: FileSystemWatchEvent;\n }\n | {\n readonly instanceId: string;\n readonly subscriptionId: string;\n readonly kind: 'error';\n readonly error: SerializedFsError;\n };\n\n/** Wire-level filesystem v2 API exposed by preload. */\nexport interface DocBlocksHostFsV2API {\n open(\n request: HostFileSystemV2OpenRequest,\n ): Promise<HostFileSystemV2Result<FileSystemProviderCapabilities>>;\n stat(\n instanceId: string,\n path: WorkspacePath,\n ): Promise<HostFileSystemV2Result<FileSystemEntrySnapshot | null>>;\n readFile(\n instanceId: string,\n path: WorkspacePath,\n ): Promise<HostFileSystemV2Result<FileSystemFileRead | null>>;\n readDirectory(\n instanceId: string,\n path: WorkspacePath,\n ): Promise<HostFileSystemV2Result<readonly FileSystemEntrySnapshot[]>>;\n writeFile(\n instanceId: string,\n path: WorkspacePath,\n data: ArrayBuffer | Uint8Array,\n options?: FileSystemWriteOptions,\n ): Promise<HostFileSystemV2Result<FileSystemFileSnapshot>>;\n createDirectory(\n instanceId: string,\n path: WorkspacePath,\n options?: FileSystemCreateDirectoryOptions,\n ): Promise<HostFileSystemV2Result<FileSystemDirectorySnapshot>>;\n remove(\n instanceId: string,\n path: WorkspacePath,\n options?: FileSystemRemoveOptions,\n ): Promise<HostFileSystemV2Result<FileSystemRemoveResult>>;\n move(\n instanceId: string,\n oldPath: WorkspacePath,\n newPath: WorkspacePath,\n options?: FileSystemMoveOptions,\n ): Promise<HostFileSystemV2Result<FileSystemEntrySnapshot>>;\n snapshot(instanceId: string): Promise<HostFileSystemV2Result<FileSystemSnapshot>>;\n watchSubscribe(instanceId: string, subscriptionId: string): Promise<HostFileSystemV2Result<null>>;\n watchUnsubscribe(\n instanceId: string,\n subscriptionId: string,\n ): Promise<HostFileSystemV2Result<null>>;\n dispose(instanceId: string): Promise<HostFileSystemV2Result<null>>;\n onWatchMessage(listener: (message: HostFileSystemV2WatchMessage) => void): () => void;\n}\n","/**\n * Host bridge — shared types + runtime access for the Electron desktop\n * host. The renderer calls `getDocBlocksHost()` to reach the preload\n * contextBridge; `isElectronHost()` gates desktop-only UI branches.\n */\n\nexport type {\n DocBlocksHostAPI,\n DocBlocksHostFsAPI,\n DocBlocksHostExternalAPI,\n DocBlocksHostWorkspacesAPI,\n DocBlocksHostShellAPI,\n DocBlocksHostExportAPI,\n DocBlocksHostFfmpegAPI,\n DocBlocksHostUpdaterAPI,\n DocBlocksHostLifecycleAPI,\n ElectronWorkspaceInfo,\n ExternalBinaryCommitResult,\n HostCloseReason,\n HostEnvironment,\n HostExportTargetGrant,\n HostPrepareCloseRequest,\n HostPrepareCloseResult,\n MenuCommand,\n OpenRequest,\n UpdateCheckResult,\n UpdateInstallResult,\n UpdaterStatus,\n} from './types.js';\n\nexport type {\n DocBlocksHostGitAPI,\n GitBranchInfo,\n GitCapabilities,\n GitCloneHandle,\n GitCloneProgress,\n GitError,\n GitErrorCode,\n GitFileAtRevision,\n GitFileChange,\n GitFileStatusCode,\n GitLogEntry,\n GitLogOptions,\n GitRemoteInfo,\n GitRepoDetection,\n GitResult,\n GitRevision,\n GitStatus,\n} from './git.js';\n\nexport {\n ELECTRON_FILE_SYSTEM_V2_CAPABILITIES,\n type DocBlocksHostFsV2API,\n type HostFileSystemV2OpenRequest,\n type HostFileSystemV2Result,\n type HostFileSystemV2WatchMessage,\n} from './filesystem-v2.js';\n\nexport {\n HOST_WIRE_LIMITS,\n isBoundedBytePayload,\n isBoundedString,\n isTrustedRendererUrl,\n parseExternalHttpUrl,\n parseOpenRequest,\n} from './wire-policy.js';\n\nimport type { DocBlocksHostAPI } from './types.js';\n\n/** True when running inside the Electron desktop shell. */\nexport function isElectronHost(): boolean {\n if (typeof globalThis === 'undefined') return false;\n const host = (globalThis as { docBlocksHost?: unknown }).docBlocksHost;\n return (\n typeof host === 'object' &&\n host !== null &&\n typeof (host as { fs?: unknown }).fs === 'object' &&\n (host as { fs?: unknown }).fs !== null\n );\n}\n\n/** Return the host API, or throw if not running under Electron. */\nexport function getDocBlocksHost(): DocBlocksHostAPI {\n const host = (globalThis as { docBlocksHost?: DocBlocksHostAPI }).docBlocksHost;\n if (!host) {\n throw new Error('docBlocksHost is not available — not running under Electron?');\n }\n return host;\n}\n\n/** Return the host API, or null if not running under Electron. */\nexport function maybeGetDocBlocksHost(): DocBlocksHostAPI | null {\n return (globalThis as { docBlocksHost?: DocBlocksHostAPI }).docBlocksHost ?? null;\n}\n"],"mappings":";AAkBO,IAAM,uCAAuE,OAAO,OAAO;AAAA,EAChG,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,OAAO;AAAA,EACP,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,YAAY;AACd,CAAC;;;AC0CM,SAAS,iBAA0B;AACxC,MAAI,OAAO,eAAe,YAAa,QAAO;AAC9C,QAAM,OAAQ,WAA2C;AACzD,SACE,OAAO,SAAS,YAChB,SAAS,QACT,OAAQ,KAA0B,OAAO,YACxC,KAA0B,OAAO;AAEtC;AAGO,SAAS,mBAAqC;AACnD,QAAM,OAAQ,WAAoD;AAClE,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,MAAM,mEAA8D;AAAA,EAChF;AACA,SAAO;AACT;AAGO,SAAS,wBAAiD;AAC/D,SAAQ,WAAoD,iBAAiB;AAC/E;","names":[]}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// src/share/index.ts
|
|
2
|
+
var SHARED_DOCUMENT_LIMITS = Object.freeze({
|
|
3
|
+
/** A conservative interoperability threshold, not a universal browser limit. */
|
|
4
|
+
portableUrlCharacters: 4096,
|
|
5
|
+
/** Hard cap applied before a hash is copied or decoded. */
|
|
6
|
+
urlCharacters: 32768,
|
|
7
|
+
/** Maximum UTF-8 Markdown accepted by the first-party link generator. */
|
|
8
|
+
markdownBytes: 20 * 1024,
|
|
9
|
+
/** Maximum compressed DBK bytes carried by the versioned envelope. */
|
|
10
|
+
archiveBytes: 23 * 1024
|
|
11
|
+
});
|
|
12
|
+
var BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
13
|
+
var HASH_PREFIX = "#shared(";
|
|
14
|
+
var MAGIC = new Uint8Array([68, 66, 83, 72, 65, 82, 69]);
|
|
15
|
+
var VERSION = 1;
|
|
16
|
+
var HEADER_BYTES = MAGIC.byteLength + 2;
|
|
17
|
+
var MODE_TO_CODE = Object.freeze({
|
|
18
|
+
slideshow: 1,
|
|
19
|
+
video: 2,
|
|
20
|
+
page: 3,
|
|
21
|
+
document: 4,
|
|
22
|
+
narrate: 5
|
|
23
|
+
});
|
|
24
|
+
var CODE_TO_MODE = Object.freeze({
|
|
25
|
+
1: "slideshow",
|
|
26
|
+
2: "video",
|
|
27
|
+
3: "page",
|
|
28
|
+
4: "document",
|
|
29
|
+
5: "narrate"
|
|
30
|
+
});
|
|
31
|
+
function createSharedDocumentHash(archive, mode = null) {
|
|
32
|
+
assertArchive(archive);
|
|
33
|
+
const bytes = new Uint8Array(HEADER_BYTES + archive.byteLength);
|
|
34
|
+
bytes.set(MAGIC, 0);
|
|
35
|
+
bytes[MAGIC.byteLength] = VERSION;
|
|
36
|
+
bytes[MAGIC.byteLength + 1] = mode === null ? 0 : MODE_TO_CODE[mode];
|
|
37
|
+
bytes.set(archive, HEADER_BYTES);
|
|
38
|
+
const hash = `${HASH_PREFIX}${encodeBase64(bytes)})`;
|
|
39
|
+
if (hash.length > SHARED_DOCUMENT_LIMITS.urlCharacters) {
|
|
40
|
+
throw new Error("The shared document payload exceeds the URL length limit.");
|
|
41
|
+
}
|
|
42
|
+
return hash;
|
|
43
|
+
}
|
|
44
|
+
function createSharedDocumentUrl(baseUrl, archive, mode = null) {
|
|
45
|
+
const url = new URL(baseUrl);
|
|
46
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
47
|
+
throw new Error("Shared document links require an HTTP(S) DocBlocks URL.");
|
|
48
|
+
}
|
|
49
|
+
url.hash = createSharedDocumentHash(archive, mode);
|
|
50
|
+
const result = url.toString();
|
|
51
|
+
if (result.length > SHARED_DOCUMENT_LIMITS.urlCharacters) {
|
|
52
|
+
throw new Error("The shared document link exceeds the URL length limit.");
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
function parseSharedDocumentHash(hash) {
|
|
57
|
+
if (!hash.startsWith("#shared")) return { kind: "none" };
|
|
58
|
+
if (hash.length > SHARED_DOCUMENT_LIMITS.urlCharacters || !hash.startsWith(HASH_PREFIX) || !hash.endsWith(")")) {
|
|
59
|
+
return invalid("This shared document link is malformed or too long.");
|
|
60
|
+
}
|
|
61
|
+
const encoded = hash.slice(HASH_PREFIX.length, -1);
|
|
62
|
+
const maximumPayloadBytes = HEADER_BYTES + SHARED_DOCUMENT_LIMITS.archiveBytes;
|
|
63
|
+
const maximumBase64Characters = Math.ceil(maximumPayloadBytes / 3) * 4;
|
|
64
|
+
if (encoded.length === 0 || encoded.length > maximumBase64Characters) {
|
|
65
|
+
return invalid("This shared document payload is empty or too large.");
|
|
66
|
+
}
|
|
67
|
+
const bytes = decodeBase64(encoded, maximumPayloadBytes);
|
|
68
|
+
if (!bytes || bytes.byteLength <= HEADER_BYTES) {
|
|
69
|
+
return invalid("This shared document payload is not valid base64 data.");
|
|
70
|
+
}
|
|
71
|
+
for (let index = 0; index < MAGIC.byteLength; index += 1) {
|
|
72
|
+
if (bytes[index] !== MAGIC[index]) {
|
|
73
|
+
return invalid("This shared document payload has an unknown format.");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (bytes[MAGIC.byteLength] !== VERSION) {
|
|
77
|
+
return invalid("This shared document link uses an unsupported version.");
|
|
78
|
+
}
|
|
79
|
+
const modeCode = bytes[MAGIC.byteLength + 1] ?? 0;
|
|
80
|
+
const mode = modeCode === 0 ? null : CODE_TO_MODE[modeCode];
|
|
81
|
+
if (modeCode !== 0 && !mode) {
|
|
82
|
+
return invalid("This shared document link has an unsupported launch mode.");
|
|
83
|
+
}
|
|
84
|
+
const archive = bytes.slice(HEADER_BYTES);
|
|
85
|
+
if (!hasZipSignature(archive)) {
|
|
86
|
+
return invalid("This shared document payload does not contain a DBK archive.");
|
|
87
|
+
}
|
|
88
|
+
return { kind: "valid", payload: { archive, mode } };
|
|
89
|
+
}
|
|
90
|
+
function assertArchive(archive) {
|
|
91
|
+
if (archive.byteLength === 0 || archive.byteLength > SHARED_DOCUMENT_LIMITS.archiveBytes) {
|
|
92
|
+
throw new Error("The shared document archive exceeds the URL payload limit.");
|
|
93
|
+
}
|
|
94
|
+
if (!hasZipSignature(archive)) {
|
|
95
|
+
throw new Error("A shared document payload must contain a DBK ZIP archive.");
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function hasZipSignature(bytes) {
|
|
99
|
+
return bytes.byteLength >= 4 && bytes[0] === 80 && bytes[1] === 75 && bytes[2] === 3 && bytes[3] === 4;
|
|
100
|
+
}
|
|
101
|
+
function invalid(message) {
|
|
102
|
+
return { kind: "invalid", message };
|
|
103
|
+
}
|
|
104
|
+
function encodeBase64(bytes) {
|
|
105
|
+
let result = "";
|
|
106
|
+
for (let index = 0; index < bytes.byteLength; index += 3) {
|
|
107
|
+
const first = bytes[index] ?? 0;
|
|
108
|
+
const hasSecond = index + 1 < bytes.byteLength;
|
|
109
|
+
const hasThird = index + 2 < bytes.byteLength;
|
|
110
|
+
const second = bytes[index + 1] ?? 0;
|
|
111
|
+
const third = bytes[index + 2] ?? 0;
|
|
112
|
+
const value = first << 16 | second << 8 | third;
|
|
113
|
+
result += BASE64_ALPHABET[value >>> 18 & 63];
|
|
114
|
+
result += BASE64_ALPHABET[value >>> 12 & 63];
|
|
115
|
+
result += hasSecond ? BASE64_ALPHABET[value >>> 6 & 63] : "=";
|
|
116
|
+
result += hasThird ? BASE64_ALPHABET[value & 63] : "=";
|
|
117
|
+
}
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
120
|
+
function decodeBase64(value, maximumBytes) {
|
|
121
|
+
if (value.length % 4 !== 0 || !/^[A-Za-z0-9+/]*={0,2}$/u.test(value) || value.slice(0, -2).includes("=")) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
const padding = value.endsWith("==") ? 2 : value.endsWith("=") ? 1 : 0;
|
|
125
|
+
const byteLength = value.length / 4 * 3 - padding;
|
|
126
|
+
if (byteLength <= 0 || byteLength > maximumBytes) return null;
|
|
127
|
+
const result = new Uint8Array(byteLength);
|
|
128
|
+
let outputIndex = 0;
|
|
129
|
+
for (let index = 0; index < value.length; index += 4) {
|
|
130
|
+
const a = BASE64_ALPHABET.indexOf(value[index] ?? "");
|
|
131
|
+
const b = BASE64_ALPHABET.indexOf(value[index + 1] ?? "");
|
|
132
|
+
const c = value[index + 2] === "=" ? 0 : BASE64_ALPHABET.indexOf(value[index + 2] ?? "");
|
|
133
|
+
const d = value[index + 3] === "=" ? 0 : BASE64_ALPHABET.indexOf(value[index + 3] ?? "");
|
|
134
|
+
if (a < 0 || b < 0 || c < 0 || d < 0) return null;
|
|
135
|
+
const combined = a << 18 | b << 12 | c << 6 | d;
|
|
136
|
+
if (outputIndex < byteLength) result[outputIndex++] = combined >>> 16 & 255;
|
|
137
|
+
if (outputIndex < byteLength) result[outputIndex++] = combined >>> 8 & 255;
|
|
138
|
+
if (outputIndex < byteLength) result[outputIndex++] = combined & 255;
|
|
139
|
+
}
|
|
140
|
+
return encodeBase64(result) === value ? result : null;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export {
|
|
144
|
+
SHARED_DOCUMENT_LIMITS,
|
|
145
|
+
createSharedDocumentHash,
|
|
146
|
+
createSharedDocumentUrl,
|
|
147
|
+
parseSharedDocumentHash
|
|
148
|
+
};
|
|
149
|
+
//# sourceMappingURL=chunk-BXMF5YQJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/share/index.ts"],"sourcesContent":["/**\n * Canonical wire format for a document embedded in a DocBlocks URL hash.\n *\n * The base64 payload is deliberately small and versioned:\n *\n * \"DBSHARE\" + version byte + mode byte + bounded DBK bytes\n *\n * The DBK itself is validated at the filesystem import boundary. Keeping the\n * launch mode outside the archive means the copied Markdown is never mutated\n * merely to choose its initial presentation.\n */\n\nexport type SharedDocumentMode = 'slideshow' | 'video' | 'page' | 'document' | 'narrate';\n\nexport interface SharedDocumentPayload {\n readonly archive: Uint8Array;\n readonly mode: SharedDocumentMode | null;\n}\n\nexport type SharedDocumentHashParseResult =\n | { readonly kind: 'none' }\n | { readonly kind: 'valid'; readonly payload: SharedDocumentPayload }\n | { readonly kind: 'invalid'; readonly message: string };\n\nexport const SHARED_DOCUMENT_LIMITS = Object.freeze({\n /** A conservative interoperability threshold, not a universal browser limit. */\n portableUrlCharacters: 4_096,\n /** Hard cap applied before a hash is copied or decoded. */\n urlCharacters: 32_768,\n /** Maximum UTF-8 Markdown accepted by the first-party link generator. */\n markdownBytes: 20 * 1024,\n /** Maximum compressed DBK bytes carried by the versioned envelope. */\n archiveBytes: 23 * 1024,\n});\n\nconst BASE64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\nconst HASH_PREFIX = '#shared(';\nconst MAGIC = new Uint8Array([0x44, 0x42, 0x53, 0x48, 0x41, 0x52, 0x45]); // DBSHARE\nconst VERSION = 1;\nconst HEADER_BYTES = MAGIC.byteLength + 2;\n\nconst MODE_TO_CODE: Readonly<Record<SharedDocumentMode, number>> = Object.freeze({\n slideshow: 1,\n video: 2,\n page: 3,\n document: 4,\n narrate: 5,\n});\n\nconst CODE_TO_MODE: Readonly<Record<number, SharedDocumentMode>> = Object.freeze({\n 1: 'slideshow',\n 2: 'video',\n 3: 'page',\n 4: 'document',\n 5: 'narrate',\n});\n\n/** Build the exact `#shared(<base64>)` fragment for a bounded DBK archive. */\nexport function createSharedDocumentHash(\n archive: Uint8Array,\n mode: SharedDocumentMode | null = null,\n): string {\n assertArchive(archive);\n const bytes = new Uint8Array(HEADER_BYTES + archive.byteLength);\n bytes.set(MAGIC, 0);\n bytes[MAGIC.byteLength] = VERSION;\n bytes[MAGIC.byteLength + 1] = mode === null ? 0 : MODE_TO_CODE[mode];\n bytes.set(archive, HEADER_BYTES);\n\n const hash = `${HASH_PREFIX}${encodeBase64(bytes)})`;\n if (hash.length > SHARED_DOCUMENT_LIMITS.urlCharacters) {\n throw new Error('The shared document payload exceeds the URL length limit.');\n }\n return hash;\n}\n\n/** Replace any existing hash on a base URL with a validated shared payload. */\nexport function createSharedDocumentUrl(\n baseUrl: string,\n archive: Uint8Array,\n mode: SharedDocumentMode | null = null,\n): string {\n const url = new URL(baseUrl);\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n throw new Error('Shared document links require an HTTP(S) DocBlocks URL.');\n }\n url.hash = createSharedDocumentHash(archive, mode);\n const result = url.toString();\n if (result.length > SHARED_DOCUMENT_LIMITS.urlCharacters) {\n throw new Error('The shared document link exceeds the URL length limit.');\n }\n return result;\n}\n\n/** Parse a hash without ever treating malformed shared input as workspace routing. */\nexport function parseSharedDocumentHash(hash: string): SharedDocumentHashParseResult {\n if (!hash.startsWith('#shared')) return { kind: 'none' };\n if (\n hash.length > SHARED_DOCUMENT_LIMITS.urlCharacters ||\n !hash.startsWith(HASH_PREFIX) ||\n !hash.endsWith(')')\n ) {\n return invalid('This shared document link is malformed or too long.');\n }\n\n const encoded = hash.slice(HASH_PREFIX.length, -1);\n const maximumPayloadBytes = HEADER_BYTES + SHARED_DOCUMENT_LIMITS.archiveBytes;\n const maximumBase64Characters = Math.ceil(maximumPayloadBytes / 3) * 4;\n if (encoded.length === 0 || encoded.length > maximumBase64Characters) {\n return invalid('This shared document payload is empty or too large.');\n }\n\n const bytes = decodeBase64(encoded, maximumPayloadBytes);\n if (!bytes || bytes.byteLength <= HEADER_BYTES) {\n return invalid('This shared document payload is not valid base64 data.');\n }\n for (let index = 0; index < MAGIC.byteLength; index += 1) {\n if (bytes[index] !== MAGIC[index]) {\n return invalid('This shared document payload has an unknown format.');\n }\n }\n if (bytes[MAGIC.byteLength] !== VERSION) {\n return invalid('This shared document link uses an unsupported version.');\n }\n\n const modeCode = bytes[MAGIC.byteLength + 1] ?? 0;\n const mode = modeCode === 0 ? null : CODE_TO_MODE[modeCode];\n if (modeCode !== 0 && !mode) {\n return invalid('This shared document link has an unsupported launch mode.');\n }\n\n const archive = bytes.slice(HEADER_BYTES);\n if (!hasZipSignature(archive)) {\n return invalid('This shared document payload does not contain a DBK archive.');\n }\n return { kind: 'valid', payload: { archive, mode } };\n}\n\nfunction assertArchive(archive: Uint8Array): void {\n if (archive.byteLength === 0 || archive.byteLength > SHARED_DOCUMENT_LIMITS.archiveBytes) {\n throw new Error('The shared document archive exceeds the URL payload limit.');\n }\n if (!hasZipSignature(archive)) {\n throw new Error('A shared document payload must contain a DBK ZIP archive.');\n }\n}\n\nfunction hasZipSignature(bytes: Uint8Array): boolean {\n return (\n bytes.byteLength >= 4 &&\n bytes[0] === 0x50 &&\n bytes[1] === 0x4b &&\n bytes[2] === 0x03 &&\n bytes[3] === 0x04\n );\n}\n\nfunction invalid(message: string): SharedDocumentHashParseResult {\n return { kind: 'invalid', message };\n}\n\nfunction encodeBase64(bytes: Uint8Array): string {\n let result = '';\n for (let index = 0; index < bytes.byteLength; index += 3) {\n const first = bytes[index] ?? 0;\n const hasSecond = index + 1 < bytes.byteLength;\n const hasThird = index + 2 < bytes.byteLength;\n const second = bytes[index + 1] ?? 0;\n const third = bytes[index + 2] ?? 0;\n const value = (first << 16) | (second << 8) | third;\n result += BASE64_ALPHABET[(value >>> 18) & 63];\n result += BASE64_ALPHABET[(value >>> 12) & 63];\n result += hasSecond ? BASE64_ALPHABET[(value >>> 6) & 63] : '=';\n result += hasThird ? BASE64_ALPHABET[value & 63] : '=';\n }\n return result;\n}\n\nfunction decodeBase64(value: string, maximumBytes: number): Uint8Array | null {\n if (\n value.length % 4 !== 0 ||\n !/^[A-Za-z0-9+/]*={0,2}$/u.test(value) ||\n value.slice(0, -2).includes('=')\n ) {\n return null;\n }\n\n const padding = value.endsWith('==') ? 2 : value.endsWith('=') ? 1 : 0;\n const byteLength = (value.length / 4) * 3 - padding;\n if (byteLength <= 0 || byteLength > maximumBytes) return null;\n\n const result = new Uint8Array(byteLength);\n let outputIndex = 0;\n for (let index = 0; index < value.length; index += 4) {\n const a = BASE64_ALPHABET.indexOf(value[index] ?? '');\n const b = BASE64_ALPHABET.indexOf(value[index + 1] ?? '');\n const c = value[index + 2] === '=' ? 0 : BASE64_ALPHABET.indexOf(value[index + 2] ?? '');\n const d = value[index + 3] === '=' ? 0 : BASE64_ALPHABET.indexOf(value[index + 3] ?? '');\n if (a < 0 || b < 0 || c < 0 || d < 0) return null;\n const combined = (a << 18) | (b << 12) | (c << 6) | d;\n if (outputIndex < byteLength) result[outputIndex++] = (combined >>> 16) & 0xff;\n if (outputIndex < byteLength) result[outputIndex++] = (combined >>> 8) & 0xff;\n if (outputIndex < byteLength) result[outputIndex++] = combined & 0xff;\n }\n\n // Reject non-canonical encodings with non-zero unused bits.\n return encodeBase64(result) === value ? result : null;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isFileSystemMoveStateError
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-MNSZ7EZN.js";
|
|
4
|
+
import {
|
|
5
|
+
decodeUtf8Text
|
|
6
|
+
} from "./chunk-FA7UNOXK.js";
|
|
4
7
|
import {
|
|
5
8
|
FsError,
|
|
6
9
|
parseWorkspacePath
|
|
7
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-JS6XFWQK.js";
|
|
8
11
|
import {
|
|
9
12
|
getFileSystemProviderV2
|
|
10
13
|
} from "./chunk-EZKJZUNJ.js";
|
|
@@ -668,7 +671,10 @@ function createFileSystemDocumentTarget(provider, path, options = {}) {
|
|
|
668
671
|
async commit(request) {
|
|
669
672
|
if (providerV2 && providerV2.capabilities.conditionalWrite !== "none") {
|
|
670
673
|
const current = await providerV2.readFile(canonicalPath);
|
|
671
|
-
const currentContent = current ?
|
|
674
|
+
const currentContent = current ? decodeUtf8Text(current.data, {
|
|
675
|
+
label: "The external document",
|
|
676
|
+
path: canonicalPath
|
|
677
|
+
}) : null;
|
|
672
678
|
if (currentContent !== request.persistedContent && currentContent !== request.content) {
|
|
673
679
|
throw new DocumentCommitConflictError(
|
|
674
680
|
"The document changed outside DocBlocks: " + path,
|
|
@@ -697,7 +703,10 @@ function createFileSystemDocumentTarget(provider, path, options = {}) {
|
|
|
697
703
|
const external = await providerV2.readFile(canonicalPath);
|
|
698
704
|
throw new DocumentCommitConflictError(
|
|
699
705
|
"The document changed outside DocBlocks: " + path,
|
|
700
|
-
external ?
|
|
706
|
+
external ? decodeUtf8Text(external.data, {
|
|
707
|
+
label: "The external document",
|
|
708
|
+
path: canonicalPath
|
|
709
|
+
}) : null,
|
|
701
710
|
external?.entry.version ?? null
|
|
702
711
|
);
|
|
703
712
|
}
|
|
@@ -1059,4 +1068,4 @@ export {
|
|
|
1059
1068
|
DocumentRecoveryJournal,
|
|
1060
1069
|
getDefaultDocumentRecoveryStorage
|
|
1061
1070
|
};
|
|
1062
|
-
//# sourceMappingURL=chunk-
|
|
1071
|
+
//# sourceMappingURL=chunk-COYQXQK3.js.map
|