@bendyline/docblocks 1.1.2 → 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.
Files changed (149) hide show
  1. package/README.md +76 -11
  2. package/dist/chunk-6IYMTYMQ.js +1692 -0
  3. package/dist/chunk-6IYMTYMQ.js.map +1 -0
  4. package/dist/chunk-AEHCVWU5.js +25 -0
  5. package/dist/chunk-AEHCVWU5.js.map +1 -0
  6. package/dist/chunk-B56KWCSE.js +802 -0
  7. package/dist/chunk-B56KWCSE.js.map +1 -0
  8. package/dist/{chunk-ME76RUMR.js → chunk-BNKV7MTO.js} +15 -1
  9. package/dist/chunk-BNKV7MTO.js.map +1 -0
  10. package/dist/chunk-BXMF5YQJ.js +149 -0
  11. package/dist/chunk-BXMF5YQJ.js.map +1 -0
  12. package/dist/chunk-COYQXQK3.js +1071 -0
  13. package/dist/chunk-COYQXQK3.js.map +1 -0
  14. package/dist/chunk-DN7A33LL.js +780 -0
  15. package/dist/chunk-DN7A33LL.js.map +1 -0
  16. package/dist/chunk-EZKJZUNJ.js +13 -0
  17. package/dist/chunk-EZKJZUNJ.js.map +1 -0
  18. package/dist/chunk-FA7UNOXK.js +20 -0
  19. package/dist/chunk-FA7UNOXK.js.map +1 -0
  20. package/dist/chunk-FNW556FN.js +75 -0
  21. package/dist/chunk-FNW556FN.js.map +1 -0
  22. package/dist/chunk-GM5YXU4L.js +29 -0
  23. package/dist/chunk-GM5YXU4L.js.map +1 -0
  24. package/dist/chunk-JS6XFWQK.js +225 -0
  25. package/dist/chunk-JS6XFWQK.js.map +1 -0
  26. package/dist/chunk-MNSZ7EZN.js +111 -0
  27. package/dist/chunk-MNSZ7EZN.js.map +1 -0
  28. package/dist/chunk-P3DVZQ6S.js +228 -0
  29. package/dist/chunk-P3DVZQ6S.js.map +1 -0
  30. package/dist/chunk-P4WATND4.js +52 -0
  31. package/dist/chunk-P4WATND4.js.map +1 -0
  32. package/dist/chunk-RVPGQBWR.js +169 -0
  33. package/dist/chunk-RVPGQBWR.js.map +1 -0
  34. package/dist/chunk-U722UUFN.js +9 -0
  35. package/dist/chunk-U722UUFN.js.map +1 -0
  36. package/dist/chunk-VTCSF7VS.js +553 -0
  37. package/dist/chunk-VTCSF7VS.js.map +1 -0
  38. package/dist/chunk-WJKYY5QR.js +1350 -0
  39. package/dist/chunk-WJKYY5QR.js.map +1 -0
  40. package/dist/chunk-XUML3MKV.js +945 -0
  41. package/dist/chunk-XUML3MKV.js.map +1 -0
  42. package/dist/document/index.d.ts +358 -0
  43. package/dist/document/index.js +25 -0
  44. package/dist/document/index.js.map +1 -0
  45. package/dist/filesystem/electron.d.ts +73 -0
  46. package/dist/filesystem/electron.js +17 -0
  47. package/dist/filesystem/electron.js.map +1 -0
  48. package/dist/filesystem/index.d.ts +228 -8
  49. package/dist/filesystem/index.js +133 -6
  50. package/dist/filesystem/index.js.map +1 -1
  51. package/dist/filesystem/indexeddb.d.ts +284 -0
  52. package/dist/filesystem/indexeddb.js +23 -0
  53. package/dist/filesystem/indexeddb.js.map +1 -0
  54. package/dist/filesystem/memory.d.ts +152 -0
  55. package/dist/filesystem/memory.js +13 -0
  56. package/dist/filesystem/memory.js.map +1 -0
  57. package/dist/filesystem/native.d.ts +136 -0
  58. package/dist/filesystem/native.js +28 -0
  59. package/dist/filesystem/native.js.map +1 -0
  60. package/dist/host/index.d.ts +32 -6
  61. package/dist/host/index.js +26 -27
  62. package/dist/host/index.js.map +1 -1
  63. package/dist/index.d.ts +14 -9
  64. package/dist/index.js +204 -8
  65. package/dist/index.js.map +1 -1
  66. package/dist/mcp/index.d.ts +33 -0
  67. package/dist/mcp/index.js +32 -0
  68. package/dist/mcp/index.js.map +1 -0
  69. package/dist/mcp/zod.d.ts +5765 -0
  70. package/dist/mcp/zod.js +724 -0
  71. package/dist/mcp/zod.js.map +1 -0
  72. package/dist/share/index.d.ts +43 -0
  73. package/dist/share/index.js +13 -0
  74. package/dist/share/index.js.map +1 -0
  75. package/dist/types-BEg5SQ1_.d.ts +301 -0
  76. package/dist/types-CX893hgH.d.ts +468 -0
  77. package/dist/types-CueK0tvU.d.ts +501 -0
  78. package/dist/vscode/index.d.ts +220 -0
  79. package/dist/vscode/index.js +383 -0
  80. package/dist/vscode/index.js.map +1 -0
  81. package/dist/workspace/index.d.ts +141 -3
  82. package/dist/workspace/index.js +28 -1
  83. package/dist/workspace/index.js.map +1 -1
  84. package/dist/workspace-path-CWVrcuPL.d.ts +21 -0
  85. package/package.json +50 -5
  86. package/dist/chunk-GUNM43XZ.js +0 -63
  87. package/dist/chunk-GUNM43XZ.js.map +0 -1
  88. package/dist/chunk-IM7LCQJ6.js +0 -850
  89. package/dist/chunk-IM7LCQJ6.js.map +0 -1
  90. package/dist/chunk-ME76RUMR.js.map +0 -1
  91. package/dist/filesystem/electron-provider.d.ts +0 -32
  92. package/dist/filesystem/electron-provider.d.ts.map +0 -1
  93. package/dist/filesystem/electron-provider.js +0 -64
  94. package/dist/filesystem/electron-provider.js.map +0 -1
  95. package/dist/filesystem/file-media-provider.d.ts +0 -23
  96. package/dist/filesystem/file-media-provider.d.ts.map +0 -1
  97. package/dist/filesystem/file-media-provider.js +0 -85
  98. package/dist/filesystem/file-media-provider.js.map +0 -1
  99. package/dist/filesystem/filesystem-content-container.d.ts +0 -24
  100. package/dist/filesystem/filesystem-content-container.d.ts.map +0 -1
  101. package/dist/filesystem/filesystem-content-container.js +0 -116
  102. package/dist/filesystem/filesystem-content-container.js.map +0 -1
  103. package/dist/filesystem/index.d.ts.map +0 -1
  104. package/dist/filesystem/indexeddb-content-container.d.ts +0 -20
  105. package/dist/filesystem/indexeddb-content-container.d.ts.map +0 -1
  106. package/dist/filesystem/indexeddb-content-container.js +0 -93
  107. package/dist/filesystem/indexeddb-content-container.js.map +0 -1
  108. package/dist/filesystem/indexeddb-provider.d.ts +0 -32
  109. package/dist/filesystem/indexeddb-provider.d.ts.map +0 -1
  110. package/dist/filesystem/indexeddb-provider.js +0 -295
  111. package/dist/filesystem/indexeddb-provider.js.map +0 -1
  112. package/dist/filesystem/native-provider.d.ts +0 -45
  113. package/dist/filesystem/native-provider.d.ts.map +0 -1
  114. package/dist/filesystem/native-provider.js +0 -336
  115. package/dist/filesystem/native-provider.js.map +0 -1
  116. package/dist/filesystem/types.d.ts +0 -50
  117. package/dist/filesystem/types.d.ts.map +0 -1
  118. package/dist/filesystem/types.js +0 -8
  119. package/dist/filesystem/types.js.map +0 -1
  120. package/dist/host/index.d.ts.map +0 -1
  121. package/dist/host/types.d.ts +0 -149
  122. package/dist/host/types.d.ts.map +0 -1
  123. package/dist/host/types.js +0 -10
  124. package/dist/host/types.js.map +0 -1
  125. package/dist/index-pgBHBQ9G.d.ts +0 -213
  126. package/dist/index.d.ts.map +0 -1
  127. package/dist/workspace/index.d.ts.map +0 -1
  128. package/dist/workspace/types.d.ts +0 -29
  129. package/dist/workspace/types.d.ts.map +0 -1
  130. package/dist/workspace/types.js +0 -6
  131. package/dist/workspace/types.js.map +0 -1
  132. package/dist/workspace/workspace-manager.d.ts +0 -35
  133. package/dist/workspace/workspace-manager.d.ts.map +0 -1
  134. package/dist/workspace/workspace-manager.js +0 -82
  135. package/dist/workspace/workspace-manager.js.map +0 -1
  136. package/src/filesystem/electron-provider.ts +0 -88
  137. package/src/filesystem/file-media-provider.ts +0 -103
  138. package/src/filesystem/filesystem-content-container.ts +0 -126
  139. package/src/filesystem/index.ts +0 -24
  140. package/src/filesystem/indexeddb-content-container.ts +0 -104
  141. package/src/filesystem/indexeddb-provider.ts +0 -345
  142. package/src/filesystem/native-provider.ts +0 -384
  143. package/src/filesystem/types.ts +0 -69
  144. package/src/host/index.ts +0 -47
  145. package/src/host/types.ts +0 -153
  146. package/src/index.ts +0 -9
  147. package/src/workspace/index.ts +0 -10
  148. package/src/workspace/types.ts +0 -29
  149. package/src/workspace/workspace-manager.ts +0 -90
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/filesystem/memory-provider-v2.ts","../src/filesystem/memory-provider.ts"],"sourcesContent":["import { FsError, type FsOperation } from './fs-error.js';\nimport type { FileCommitResult } from './types.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 FileSystemWatchEvent,\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 { copyBytes } from './internal/bytes.js';\nimport { compareSnapshotsByName, compareText } from './internal/entry-order.js';\nimport { parentChainWithRoot } from './internal/parent-chain.js';\nimport { decodeUtf8Text } from './utf8.js';\n\ninterface MemoryEntryBase {\n readonly version: FileSystemVersion;\n readonly lastModified: string;\n}\n\ninterface MemoryFileEntry extends MemoryEntryBase {\n readonly kind: 'file';\n readonly data: ArrayBuffer;\n /** Compatibility metadata only; v2 always treats the payload as bytes. */\n readonly payloadKind: MemoryFilePayloadKind;\n}\n\ninterface MemoryDirectoryEntry extends MemoryEntryBase {\n readonly kind: 'directory';\n}\n\ntype MemoryEntry = MemoryFileEntry | MemoryDirectoryEntry;\n\nexport type MemoryFilePayloadKind = 'text' | 'binary';\n\nexport interface MemoryFileSystemV2StateFile {\n readonly path: WorkspacePath;\n readonly data: ArrayBuffer;\n readonly payloadKind: MemoryFilePayloadKind;\n}\n\nexport interface MemoryFileSystemV2CompatibilityFile {\n readonly data: ArrayBuffer;\n readonly payloadKind: MemoryFilePayloadKind;\n}\n\nexport interface MemoryFileSystemV2State {\n readonly revision: number;\n readonly files: readonly MemoryFileSystemV2StateFile[];\n readonly directories: readonly WorkspacePath[];\n}\n\nexport interface MemoryFileSystemV2ReplacementFile {\n readonly path: WorkspacePath;\n readonly data: ArrayBuffer | Uint8Array;\n readonly payloadKind: MemoryFilePayloadKind;\n}\n\nexport interface MemoryFileSystemV2Replacement {\n readonly files: readonly MemoryFileSystemV2ReplacementFile[];\n readonly directories?: readonly WorkspacePath[];\n}\n\ninterface MemoryWatcher {\n readonly listener: FileSystemWatchListener;\n readonly onError: FileSystemWatchOptions['onError'];\n}\n\ntype MemoryWatchEventInput = FileSystemWatchEvent extends infer Event\n ? Event extends FileSystemWatchEvent\n ? Omit<Event, 'sequence' | 'origin'>\n : never\n : never;\n\nconst MEMORY_CAPABILITIES: FileSystemProviderCapabilities = Object.freeze({\n writeAtomicity: 'process',\n moveAtomicity: 'process',\n snapshotAtomicity: 'process',\n conditionalWrite: 'process',\n recursiveRemove: true,\n watch: true,\n caseSensitivity: 'sensitive',\n symlinkPolicy: 'unsupported',\n durability: 'volatile',\n});\n\n/**\n * Correctness reference for FileSystemProviderV2.\n *\n * Every mutation validates first, stages a fresh map, swaps it once, and only\n * then emits notifications. File buffers are owned by the provider and every\n * read/snapshot returns a defensive copy.\n */\nexport class MemoryFileSystemProviderV2 implements FileSystemProviderV2 {\n public readonly id: string;\n public readonly label: string;\n public readonly capabilities = MEMORY_CAPABILITIES;\n\n private entries: Map<WorkspacePath, MemoryEntry>;\n private readonly watchers = new Set<MemoryWatcher>();\n private readonly subscriptions = new Set<FileSystemWatchSubscription>();\n private readonly pendingEvents: FileSystemWatchEvent[] = [];\n private emittingEvents = false;\n private mutationCounter = 0;\n private eventSequence = 0;\n private treeVersion: FileSystemVersion;\n private disposed = false;\n private disposePromise: Promise<void> | null = null;\n\n public constructor(id: string, label: string) {\n this.id = id;\n this.label = label;\n this.treeVersion = parseFileSystemVersion(`${id}:0`);\n const now = new Date().toISOString();\n this.entries = new Map([\n [WORKSPACE_ROOT, { kind: 'directory', version: this.treeVersion, lastModified: now }],\n ]);\n }\n\n /** Monotonic in-process revision used by synchronous transient-workspace staging. */\n public get mutationRevision(): number {\n return this.mutationCounter;\n }\n\n /** @internal Atomically couple owned bytes to their v1 compatibility kind. */\n public readCompatibilityFile(path: WorkspacePath): MemoryFileSystemV2CompatibilityFile | null {\n this.assertOpen('read');\n const canonical = this.canonical(path);\n const entry = this.entries.get(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({ data: entry.data.slice(0), payloadKind: entry.payloadKind });\n }\n\n /** @internal Capture an owned synchronous copy for DBK whole-tree staging. */\n public captureState(): MemoryFileSystemV2State {\n this.assertOpen('snapshot');\n const files: MemoryFileSystemV2StateFile[] = [];\n const directories: WorkspacePath[] = [];\n for (const [path, entry] of [...this.entries].sort(([left], [right]) =>\n compareText(left, right),\n )) {\n if (!path) continue;\n if (entry.kind === 'directory') directories.push(path);\n else {\n files.push(\n Object.freeze({ path, data: entry.data.slice(0), payloadKind: entry.payloadKind }),\n );\n }\n }\n return Object.freeze({\n revision: this.mutationCounter,\n files: Object.freeze(files),\n directories: Object.freeze(directories),\n });\n }\n\n /** @internal Atomically replace a transient workspace after complete validation. */\n public replaceState(replacement: MemoryFileSystemV2Replacement, expectedRevision?: number): void {\n this.assertOpen('write');\n const stagedFiles = new Map<\n WorkspacePath,\n { readonly data: ArrayBuffer; readonly payloadKind: MemoryFilePayloadKind }\n >();\n const stagedDirectories = new Set<WorkspacePath>();\n const explicitDirectories = new Set<WorkspacePath>();\n\n for (const rawDirectory of replacement.directories ?? []) {\n const directory = this.canonicalNonRoot(rawDirectory, 'create-directory');\n if (explicitDirectories.has(directory)) {\n throw this.error(\n 'already-exists',\n 'create-directory',\n directory,\n 'Duplicate replacement directory.',\n );\n }\n explicitDirectories.add(directory);\n stagedDirectories.add(directory);\n addParentPaths(stagedDirectories, directory);\n }\n for (const rawFile of replacement.files) {\n const path = this.canonicalNonRoot(rawFile.path, 'write');\n if (stagedFiles.has(path)) {\n throw this.error('already-exists', 'write', path, 'Duplicate replacement file.');\n }\n if (!isMemoryFilePayloadKind(rawFile.payloadKind)) {\n throw this.error('type-mismatch', 'write', path, 'Invalid replacement payload kind.');\n }\n stagedFiles.set(path, {\n data: copyBytes(rawFile.data),\n payloadKind: rawFile.payloadKind,\n });\n addParentPaths(stagedDirectories, path);\n }\n for (const path of stagedFiles.keys()) {\n if (stagedDirectories.has(path)) {\n throw this.error(\n 'type-mismatch',\n 'write',\n path,\n 'Replacement path has conflicting file and directory kinds.',\n );\n }\n for (const parent of parentChainWithRoot(path)) {\n if (parent && stagedFiles.has(parent)) {\n throw this.error('type-mismatch', 'write', parent, 'A replacement parent is a file.');\n }\n }\n }\n if (expectedRevision !== undefined && expectedRevision !== this.mutationCounter) {\n throw this.error(\n 'conflict',\n 'write',\n WORKSPACE_ROOT,\n 'Memory filesystem changed while replacement contents were staged.',\n );\n }\n\n const version = this.nextVersion();\n const now = new Date().toISOString();\n const next = new Map<WorkspacePath, MemoryEntry>([\n [WORKSPACE_ROOT, { kind: 'directory', version, lastModified: now }],\n ]);\n this.addDirectories(next, [...stagedDirectories], version, now);\n for (const [path, file] of stagedFiles) {\n next.set(path, {\n kind: 'file',\n data: file.data,\n payloadKind: file.payloadKind,\n version,\n lastModified: now,\n });\n }\n this.entries = next;\n this.emit({\n type: 'overflow',\n kind: null,\n path: WORKSPACE_ROOT,\n destinationPath: null,\n version: null,\n previousVersion: null,\n });\n }\n\n /** @internal Synchronous setup hook used before a transient provider is published. */\n public seedText(path: WorkspacePath, content: string): void {\n this.writeFileNow(path, new TextEncoder().encode(content), { createParents: true }, 'text');\n }\n\n /** @internal Legacy text write that preserves text/binary compatibility metadata. */\n public async writeText(\n path: WorkspacePath,\n content: string,\n options: FileSystemWriteOptions = {},\n ): Promise<FileSystemFileSnapshot> {\n return this.writeFileNow(path, new TextEncoder().encode(content), options, 'text');\n }\n\n /** @internal Legacy binary write that explicitly changes compatibility payload kind. */\n public async writeBinary(\n path: WorkspacePath,\n data: ArrayBuffer | Uint8Array,\n options: FileSystemWriteOptions = {},\n ): Promise<FileSystemFileSnapshot> {\n return this.writeFileNow(path, data, options, 'binary');\n }\n\n /** @internal Atomic legacy compare-and-write over the authoritative v2 entry. */\n public async commitText(\n path: WorkspacePath,\n content: string,\n expectedContent: string | null,\n ): Promise<FileCommitResult> {\n this.assertOpen('write');\n const canonical = this.canonicalNonRoot(path, 'write');\n const existing = this.entries.get(canonical);\n if (existing?.kind === 'directory') {\n throw this.error('type-mismatch', 'write', canonical, 'Cannot replace a directory.');\n }\n // Every file is bytes, so the baseline is decided by the bytes, not by the\n // compatibility kind. Gating on `payloadKind === 'binary'` reported\n // `conflict` with a null `content`, which callers read as \"deleted\n // externally\" — a phantom deletion for a file that is plainly still there.\n // Undecodable bytes are a real fault and are raised as one, matching the\n // IndexedDB facade and the v2 commit target.\n const currentContent =\n existing?.kind === 'file'\n ? decodeUtf8Text(existing.data, {\n label: 'The stored file',\n operation: 'write',\n path: canonical,\n })\n : null;\n if (currentContent !== expectedContent && currentContent !== content) {\n return {\n status: 'conflict',\n content: currentContent,\n version: existing?.version ?? null,\n };\n }\n const written = this.writeFileNow(\n canonical,\n new TextEncoder().encode(content),\n { createParents: true, expectedVersion: existing?.version ?? null },\n 'text',\n );\n return { status: 'committed', version: written.version };\n }\n\n public async stat(path: WorkspacePath): Promise<FileSystemEntrySnapshot | null> {\n this.assertOpen('stat');\n const canonical = this.canonical(path);\n const entry = this.entries.get(canonical);\n return entry ? this.toEntrySnapshot(canonical, entry) : null;\n }\n\n public async readFile(path: WorkspacePath): Promise<FileSystemFileRead | null> {\n this.assertOpen('read');\n const canonical = this.canonical(path);\n const entry = this.entries.get(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({\n entry: this.toFileSnapshot(canonical, entry),\n data: entry.data.slice(0),\n });\n }\n\n public async readDirectory(path: WorkspacePath): Promise<readonly FileSystemEntrySnapshot[]> {\n this.assertOpen('list');\n const canonical = this.canonical(path);\n const directory = this.entries.get(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\n const children: FileSystemEntrySnapshot[] = [];\n for (const [entryPath, entry] of this.entries) {\n if (entryPath && workspacePathDirname(entryPath) === canonical) {\n children.push(this.toEntrySnapshot(entryPath, entry));\n }\n }\n children.sort(compareSnapshotsByName);\n return Object.freeze(children);\n }\n\n public async writeFile(\n path: WorkspacePath,\n data: ArrayBuffer | Uint8Array,\n options: FileSystemWriteOptions = {},\n ): Promise<FileSystemFileSnapshot> {\n return this.writeFileNow(path, data, options);\n }\n\n private writeFileNow(\n path: WorkspacePath,\n data: ArrayBuffer | Uint8Array,\n options: FileSystemWriteOptions,\n payloadKind?: MemoryFilePayloadKind,\n ): FileSystemFileSnapshot {\n this.assertOpen('write');\n const canonical = this.canonicalNonRoot(path, 'write');\n const existing = this.entries.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\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\n const missingParents = this.planParents(canonical, options.createParents ?? false, 'write');\n const ownedData = copyBytes(data);\n const version = this.nextVersion();\n const now = new Date().toISOString();\n const next = new Map(this.entries);\n this.addDirectories(next, missingParents, version, now);\n next.set(canonical, {\n kind: 'file',\n data: ownedData,\n payloadKind: payloadKind ?? (existing?.kind === 'file' ? existing.payloadKind : 'binary'),\n version,\n lastModified: now,\n });\n this.touchParents(next, canonical, version, now);\n this.entries = next;\n\n for (const directoryPath of missingParents) {\n this.emit({\n type: 'created',\n kind: 'directory',\n path: directoryPath,\n destinationPath: null,\n version,\n previousVersion: null,\n });\n }\n this.emit({\n type: existing ? 'modified' : 'created',\n kind: 'file',\n path: canonical,\n destinationPath: null,\n version,\n previousVersion: existing?.version ?? null,\n });\n return this.toFileSnapshot(canonical, next.get(canonical) as MemoryFileEntry);\n }\n\n public async createDirectory(\n path: WorkspacePath,\n options: FileSystemCreateDirectoryOptions = {},\n ): Promise<FileSystemDirectorySnapshot> {\n this.assertOpen('create-directory');\n const canonical = this.canonical(path);\n const existing = this.entries.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 this.toDirectorySnapshot(canonical, existing);\n }\n\n const missingParents = this.planParents(\n canonical,\n options.createParents ?? false,\n 'create-directory',\n );\n const version = this.nextVersion();\n const now = new Date().toISOString();\n const next = new Map(this.entries);\n const created = [...missingParents, canonical];\n this.addDirectories(next, created, version, now);\n this.touchParents(next, canonical, version, now);\n this.entries = next;\n\n for (const directoryPath of created) {\n this.emit({\n type: 'created',\n kind: 'directory',\n path: directoryPath,\n destinationPath: null,\n version,\n previousVersion: null,\n });\n }\n return this.toDirectorySnapshot(canonical, next.get(canonical) as MemoryDirectoryEntry);\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 const existing = this.entries.get(canonical);\n if (!existing) {\n if ((options.missing ?? 'error') === 'ignore') {\n return Object.freeze({ removed: false, version: this.treeVersion });\n }\n throw this.error('not-found', 'remove', canonical, 'Entry does not exist.');\n }\n this.assertExpectedVersion(existing, options.expectedVersion, 'remove', canonical);\n\n const descendants = [...this.entries.keys()].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\n const version = this.nextVersion();\n const now = new Date().toISOString();\n const next = new Map(this.entries);\n next.delete(canonical);\n if (existing.kind === 'directory') {\n for (const descendant of descendants) next.delete(descendant);\n }\n this.touchParents(next, canonical, version, now);\n this.entries = next;\n\n this.emit({\n type: 'removed',\n kind: existing.kind,\n path: canonical,\n destinationPath: null,\n version: null,\n previousVersion: existing.version,\n });\n return Object.freeze({ removed: true, version });\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 const source = this.entries.get(sourcePath);\n if (!source) throw this.error('not-found', 'move', sourcePath, 'Source does not exist.');\n this.assertExpectedVersion(source, options.expectedVersion, 'move', sourcePath);\n if (sourcePath === destinationPath) return this.toEntrySnapshot(sourcePath, source);\n if (this.entries.has(destinationPath)) {\n throw new FsError('already-exists', 'Destination already exists.', {\n operation: 'move',\n path: sourcePath,\n destinationPath,\n });\n }\n if (source.kind === 'directory' && workspacePathContains(sourcePath, destinationPath, false)) {\n throw new FsError('invalid-path', 'Cannot move a directory into itself.', {\n operation: 'move',\n path: sourcePath,\n destinationPath,\n });\n }\n\n const missingParents = this.planParents(\n destinationPath,\n options.createParents ?? false,\n 'move',\n );\n const sourcePaths = [...this.entries.keys()].filter((candidate) =>\n workspacePathContains(sourcePath, candidate),\n );\n const sourceSet = new Set(sourcePaths);\n const remapped = sourcePaths.map((currentPath) => {\n const suffix = currentPath.slice(sourcePath.length);\n const target = parseWorkspacePath(`${destinationPath}${suffix}`);\n if (this.entries.has(target) && !sourceSet.has(target)) {\n throw new FsError('already-exists', 'A destination descendant already exists.', {\n operation: 'move',\n path: currentPath,\n destinationPath: target,\n });\n }\n return [currentPath, target] as const;\n });\n\n const version = this.nextVersion();\n const now = new Date().toISOString();\n const next = new Map(this.entries);\n for (const currentPath of sourcePaths) next.delete(currentPath);\n this.addDirectories(next, missingParents, version, now);\n for (const [currentPath, targetPath] of remapped) {\n const current = this.entries.get(currentPath)!;\n next.set(targetPath, this.withVersion(current, version, now));\n }\n this.touchParents(next, sourcePath, version, now);\n this.touchParents(next, destinationPath, version, now);\n this.entries = next;\n\n for (const directoryPath of missingParents) {\n this.emit({\n type: 'created',\n kind: 'directory',\n path: directoryPath,\n destinationPath: null,\n version,\n previousVersion: null,\n });\n }\n this.emit({\n type: 'moved',\n kind: source.kind,\n path: sourcePath,\n destinationPath,\n version,\n previousVersion: source.version,\n });\n return this.toEntrySnapshot(destinationPath, next.get(destinationPath)!);\n }\n\n public async snapshot(): Promise<FileSystemSnapshot> {\n this.assertOpen('snapshot');\n const entries: FileSystemSnapshotEntry[] = [...this.entries.entries()]\n .sort(([left], [right]) => compareText(left, right))\n .map(([path, entry]) => {\n if (entry.kind === 'file') {\n return Object.freeze({ ...this.toFileSnapshot(path, entry), data: entry.data.slice(0) });\n }\n return this.toDirectorySnapshot(path, entry);\n });\n return Object.freeze({ version: this.treeVersion, entries: Object.freeze(entries) });\n }\n\n public watch(\n listener: FileSystemWatchListener,\n options: FileSystemWatchOptions = {},\n ): FileSystemWatchSubscription {\n this.assertOpen('watch');\n const watcher: MemoryWatcher = { listener, onError: options.onError };\n this.watchers.add(watcher);\n let closed = false;\n let disposePromise: Promise<void> | null = null;\n const subscription: FileSystemWatchSubscription = {\n get closed() {\n return closed;\n },\n ready: Promise.resolve(),\n dispose: () => {\n if (disposePromise) return disposePromise;\n closed = true;\n this.watchers.delete(watcher);\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 = Promise.all(\n [...this.subscriptions].map((subscription) => subscription.dispose()),\n ).then(() => undefined);\n return this.disposePromise;\n }\n\n private canonical(path: WorkspacePath): WorkspacePath {\n return parseWorkspacePath(path);\n }\n\n private canonicalNonRoot(path: WorkspacePath, operation: FsOperation): WorkspacePath {\n const canonical = this.canonical(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 assertOpen(operation: FsOperation): void {\n if (!this.disposed) return;\n throw new FsError('disposed', 'Filesystem provider is disposed.', { operation });\n }\n\n private assertExpectedVersion(\n entry: MemoryEntry | undefined,\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 planParents(\n path: WorkspacePath,\n createParents: boolean,\n operation: FsOperation,\n ): WorkspacePath[] {\n const missing: WorkspacePath[] = [];\n for (const parent of parentChainWithRoot(path)) {\n if (!parent) continue;\n const entry = this.entries.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 target: Map<WorkspacePath, MemoryEntry>,\n paths: readonly WorkspacePath[],\n version: FileSystemVersion,\n lastModified: string,\n ): void {\n for (const path of paths) {\n target.set(path, { kind: 'directory', version, lastModified });\n }\n }\n\n private touchParents(\n target: Map<WorkspacePath, MemoryEntry>,\n path: WorkspacePath,\n version: FileSystemVersion,\n lastModified: string,\n ): void {\n for (const parent of parentChainWithRoot(path)) {\n const entry = target.get(parent);\n if (entry?.kind === 'directory') {\n target.set(parent, { kind: 'directory', version, lastModified });\n }\n }\n }\n\n private withVersion(\n entry: MemoryEntry,\n version: FileSystemVersion,\n lastModified: string,\n ): MemoryEntry {\n return entry.kind === 'file'\n ? {\n kind: 'file',\n data: entry.data,\n payloadKind: entry.payloadKind,\n version,\n lastModified,\n }\n : { kind: 'directory', version, lastModified };\n }\n\n private nextVersion(): FileSystemVersion {\n this.mutationCounter += 1;\n this.treeVersion = parseFileSystemVersion(`${this.id}:${this.mutationCounter}`);\n return this.treeVersion;\n }\n\n private toEntrySnapshot(path: WorkspacePath, entry: MemoryEntry): FileSystemEntrySnapshot {\n return entry.kind === 'file'\n ? this.toFileSnapshot(path, entry)\n : this.toDirectorySnapshot(path, entry);\n }\n\n private toFileSnapshot(path: WorkspacePath, entry: MemoryFileEntry): FileSystemFileSnapshot {\n return Object.freeze({\n kind: 'file',\n path,\n name: workspacePathBasename(path),\n size: entry.data.byteLength,\n version: entry.version,\n lastModified: entry.lastModified,\n });\n }\n\n private toDirectorySnapshot(\n path: WorkspacePath,\n entry: MemoryDirectoryEntry,\n ): FileSystemDirectorySnapshot {\n return Object.freeze({\n kind: 'directory',\n path,\n name: workspacePathBasename(path),\n size: null,\n version: entry.version,\n lastModified: entry.lastModified,\n });\n }\n\n private emit(event: MemoryWatchEventInput): void {\n const complete: FileSystemWatchEvent = Object.freeze({\n ...event,\n sequence: ++this.eventSequence,\n origin: 'local',\n });\n this.pendingEvents.push(complete);\n if (this.emittingEvents) return;\n\n this.emittingEvents = true;\n try {\n while (this.pendingEvents.length > 0) {\n const pending = this.pendingEvents.shift();\n if (!pending) continue;\n for (const watcher of [...this.watchers]) {\n try {\n watcher.listener(pending);\n } catch {\n // A watcher is observational; it cannot roll back a completed mutation.\n }\n }\n }\n } finally {\n this.emittingEvents = false;\n }\n }\n\n private error(\n code: ConstructorParameters<typeof FsError>[0],\n operation: FsOperation,\n path: WorkspacePath,\n message: string,\n ): FsError {\n return new FsError(code, message, { operation, path });\n }\n}\n\nfunction addParentPaths(target: Set<WorkspacePath>, path: WorkspacePath): void {\n for (const parent of parentChainWithRoot(path)) {\n if (parent) target.add(parent);\n }\n}\n\nfunction isMemoryFilePayloadKind(value: unknown): value is MemoryFilePayloadKind {\n return value === 'text' || value === 'binary';\n}\n","/**\n * In-memory filesystem used by transient loose-file and DBK workspaces.\n *\n * MemoryFileSystemProviderV2 is authoritative. This class is the temporary\n * text-oriented v1 facade retained while callers migrate to the byte contract.\n */\n\nimport { FsError, type FsOperation } from './fs-error.js';\nimport {\n MemoryFileSystemProviderV2,\n type MemoryFileSystemV2ReplacementFile,\n} from './memory-provider-v2.js';\nimport type { FileCommitResult, FileSystemEntry, FileSystemProvider, FileMeta } from './types.js';\nimport { parseWorkspacePath, type WorkspacePath } from './workspace-path.js';\nimport { decodeUtf8Text } from './utf8.js';\n\nexport type MemoryFileSystemSnapshotFile =\n | {\n readonly kind: 'text';\n readonly path: string;\n readonly content: string;\n }\n | {\n readonly kind: 'binary';\n readonly path: string;\n readonly data: ArrayBuffer | Uint8Array;\n };\n\n/** Complete provider-relative state for a transient memory workspace. */\nexport interface MemoryFileSystemSnapshot {\n readonly files: readonly MemoryFileSystemSnapshotFile[];\n readonly directories?: readonly string[];\n}\n\nfunction canonicalPath(path: string): WorkspacePath {\n return parseWorkspacePath(path);\n}\n\n/**\n * Canonicalize and reject the root eagerly.\n *\n * Only the synchronous staging entry points need this: they must validate every\n * input before `replaceState` swaps the tree, so they cannot rely on the v2\n * authority to reject the root mid-swap. The async provider methods pass paths\n * straight through, letting v2 state root policy once for every facade.\n */\nfunction entryPath(path: string, operation: FsOperation): WorkspacePath {\n const canonical = canonicalPath(path);\n if (!canonical) {\n throw new FsError('invalid-path', 'The workspace root is not a file entry.', {\n operation,\n path,\n });\n }\n return canonical;\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 */\nfunction decode(data: ArrayBuffer, path?: WorkspacePath): string {\n return decodeUtf8Text(data, { label: 'The file', operation: 'read', path });\n}\n\n/**\n * Legacy facade over the correctness-first memory provider.\n *\n * Synchronous seed/snapshot replacement methods remain because DBK import\n * fully stages external bytes before publishing one atomic in-memory swap.\n */\nexport class MemoryFileSystemProvider implements FileSystemProvider {\n public readonly id: string;\n public readonly label: string;\n public readonly v2: MemoryFileSystemProviderV2;\n\n public constructor(id: string, label: string) {\n this.id = id;\n this.label = label;\n this.v2 = new MemoryFileSystemProviderV2(id, label);\n }\n\n /** Monotonic version of the complete in-memory tree. */\n public get treeVersion(): number {\n return this.v2.mutationRevision;\n }\n\n /** Capture an owned deterministic copy of the complete transient tree. */\n public captureContents(): MemoryFileSystemSnapshot {\n const state = this.v2.captureState();\n return {\n files: state.files.map((file) =>\n file.payloadKind === 'text'\n ? { kind: 'text' as const, path: file.path, content: decode(file.data, file.path) }\n : { kind: 'binary' as const, path: file.path, data: file.data.slice(0) },\n ),\n directories: [...state.directories],\n };\n }\n\n /** Atomically replace the complete tree after validating and owning all input. */\n public replaceContents(snapshot: MemoryFileSystemSnapshot, expectedTreeVersion?: number): void {\n const files: MemoryFileSystemV2ReplacementFile[] = snapshot.files.map((file) => ({\n path: entryPath(file.path, 'write'),\n payloadKind: file.kind,\n data: file.kind === 'text' ? new TextEncoder().encode(file.content) : file.data,\n }));\n const directories = (snapshot.directories ?? []).map((path) =>\n entryPath(path, 'create-directory'),\n );\n this.v2.replaceState({ files, directories }, expectedTreeVersion);\n }\n\n /** Seed synchronously before publishing a transient provider to consumers. */\n public seedText(path: string, content: string): void {\n this.v2.seedText(entryPath(path, 'write'), content);\n }\n\n public async readFile(path: string): Promise<string | null> {\n const canonical = canonicalPath(path);\n const file = await this.v2.readFile(canonical);\n return file ? decode(file.data, canonical) : null;\n }\n\n public async writeFile(path: string, content: string): Promise<void> {\n await this.v2.writeText(canonicalPath(path), content, { createParents: true });\n }\n\n public commitFile(\n path: string,\n content: string,\n expectedContent: string | null,\n ): Promise<FileCommitResult> {\n return this.v2.commitText(canonicalPath(path), content, expectedContent);\n }\n\n public async delete(path: string): Promise<void> {\n await this.v2.remove(canonicalPath(path), { recursive: true, missing: 'ignore' });\n }\n\n public async rename(oldPath: string, newPath: string): Promise<void> {\n await this.v2.move(canonicalPath(oldPath), canonicalPath(newPath), {\n createParents: true,\n });\n }\n\n public async readDirectory(path: string): Promise<FileSystemEntry[]> {\n const canonical = canonicalPath(path);\n try {\n const entries = await this.v2.readDirectory(canonical);\n return entries.map((entry) => ({\n kind: entry.kind,\n name: entry.name,\n path: entry.path,\n }));\n } catch (error: unknown) {\n // Preserve the v1 missing-directory behavior only on the compatibility facade.\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 return (await this.v2.stat(canonicalPath(path))) !== null;\n }\n\n public async createDirectory(path: string): Promise<void> {\n await this.v2.createDirectory(canonicalPath(path), { createParents: true });\n }\n\n public async stat(path: string): Promise<FileMeta | null> {\n const entry = await this.v2.stat(canonicalPath(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 /**\n * Every stored file is bytes, so every stored file is readable as binary.\n * `payloadKind` records how a file was written for DBK export fidelity; it is\n * not a filter. Gating on it made `readBinary` report an existing text file as\n * missing, which no other provider does and which callers read as \"no file\".\n */\n public async readBinary(path: string): Promise<ArrayBuffer | null> {\n return this.v2.readCompatibilityFile(canonicalPath(path))?.data ?? null;\n }\n\n public async writeBinary(path: string, data: ArrayBuffer | Uint8Array): Promise<void> {\n await this.v2.writeBinary(canonicalPath(path), data, { createParents: true });\n }\n}\n"],"mappings":"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","names":["entryPath"]}
@@ -0,0 +1,13 @@
1
+ // src/filesystem/types.ts
2
+ function hasFileSystemProviderV2(provider) {
3
+ return provider.v2 !== void 0 && provider.v2 !== null;
4
+ }
5
+ function getFileSystemProviderV2(provider) {
6
+ return provider.v2 ?? null;
7
+ }
8
+
9
+ export {
10
+ hasFileSystemProviderV2,
11
+ getFileSystemProviderV2
12
+ };
13
+ //# sourceMappingURL=chunk-EZKJZUNJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/filesystem/types.ts"],"sourcesContent":["/**\n * FileSystemProvider — abstract interface for a virtual filesystem.\n *\n * Legacy text-oriented facade retained while consumers migrate to\n * FileSystemProviderV2. New persistence code must use the provider's `v2`\n * contract so paths, errors, operation modes, and capabilities are explicit.\n */\n\n// ── Entry types ────────────────────────────────────────────────────\n\nimport type { FileSystemProviderV2 } from './v2.js';\n\nexport interface FileEntry {\n kind: 'file';\n name: string;\n path: string;\n}\n\nexport interface FolderEntry {\n kind: 'directory';\n name: string;\n path: string;\n}\n\nexport type FileSystemEntry = FileEntry | FolderEntry;\n\nexport interface FileMeta {\n name: string;\n path: string;\n size: number;\n lastModified: string;\n}\n\nexport type FileCommitResult =\n | { status: 'committed'; version: string | null }\n | { status: 'conflict'; content: string | null; version: string | null };\n\n// ── Provider interface ─────────────────────────────────────────────\n\n/**\n * @deprecated Compatibility facade for external providers and older callers.\n * Implement new backends with `FileSystemProviderV2`; built-in facades expose\n * their authoritative implementation through `v2`.\n */\nexport interface FileSystemProvider {\n /** Unique identifier for this provider instance. */\n readonly id: string;\n\n /** Human-readable label (e.g., folder name or \"Browser Storage\"). */\n readonly label: string;\n\n /** Optional correctness-first implementation exposed during the v1-to-v2 migration. */\n readonly v2?: FileSystemProviderV2;\n\n /** Read the text content of a file. Returns null if the file doesn't exist. */\n readFile(path: string): Promise<string | null>;\n\n /** Write text content to a file, creating it (and parent dirs) if needed. */\n writeFile(path: string, content: string): Promise<void>;\n\n /**\n * Conditionally replace a text file when it still matches the caller's\n * persisted baseline. Production providers implement this at their\n * strongest available serialization boundary.\n */\n commitFile?(\n path: string,\n content: string,\n expectedContent: string | null,\n ): Promise<FileCommitResult>;\n\n /**\n * Legacy recursive removal of a file or directory subtree. Workspace root\n * deletion is forbidden. Prefer v2 `remove({ recursive })`.\n */\n delete(path: string): Promise<void>;\n\n /** Rename or move an entry. Rejects missing sources and existing destinations. */\n rename(oldPath: string, newPath: string): Promise<void>;\n\n /** List immediate children of a directory. */\n readDirectory(path: string): Promise<FileSystemEntry[]>;\n\n /** Check whether a path exists. */\n exists(path: string): Promise<boolean>;\n\n /** Create a directory (and parents if needed). */\n createDirectory(path: string): Promise<void>;\n\n /** Get metadata for a file. Returns null if not found. */\n stat(path: string): Promise<FileMeta | null>;\n\n /** Read raw binary content. Returns null if not found. */\n readBinary(path: string): Promise<ArrayBuffer | null>;\n\n /** Write raw binary content. */\n writeBinary(path: string, data: ArrayBuffer | Uint8Array): Promise<void>;\n}\n\nexport type FileSystemProviderWithV2 = FileSystemProvider & {\n readonly v2: FileSystemProviderV2;\n};\n\n/** Discover a provider-owned v2 implementation without coupling consumers to a concrete class. */\nexport function hasFileSystemProviderV2(\n provider: FileSystemProvider,\n): provider is FileSystemProviderWithV2 {\n return provider.v2 !== undefined && provider.v2 !== null;\n}\n\n/** Return the provider-owned v2 implementation when migration support is available. */\nexport function getFileSystemProviderV2(provider: FileSystemProvider): FileSystemProviderV2 | null {\n return provider.v2 ?? null;\n}\n"],"mappings":";AAwGO,SAAS,wBACd,UACsC;AACtC,SAAO,SAAS,OAAO,UAAa,SAAS,OAAO;AACtD;AAGO,SAAS,wBAAwB,UAA2D;AACjG,SAAO,SAAS,MAAM;AACxB;","names":[]}
@@ -0,0 +1,20 @@
1
+ import {
2
+ FsError
3
+ } from "./chunk-JS6XFWQK.js";
4
+
5
+ // src/filesystem/utf8.ts
6
+ function decodeUtf8Text(data, options = {}) {
7
+ try {
8
+ return new TextDecoder("utf-8", { fatal: true }).decode(data);
9
+ } catch {
10
+ throw new FsError("corrupt", `${options.label ?? "Text content"} is not valid UTF-8.`, {
11
+ operation: options.operation ?? "read",
12
+ path: options.path
13
+ });
14
+ }
15
+ }
16
+
17
+ export {
18
+ decodeUtf8Text
19
+ };
20
+ //# sourceMappingURL=chunk-FA7UNOXK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/filesystem/utf8.ts"],"sourcesContent":["import { FsError, type FsOperation } from './fs-error.js';\n\nexport interface DecodeUtf8TextOptions {\n /** User-facing description of the payload being decoded. */\n readonly label?: string;\n /** Filesystem operation that produced the bytes. */\n readonly operation?: FsOperation;\n /** Canonical or display path associated with the payload. */\n readonly path?: string;\n}\n\n/**\n * Decode byte-authoritative text without silently replacing malformed input.\n * Replacement characters are unsafe at persistence boundaries because a later\n * save can permanently overwrite the original bytes with altered content.\n */\nexport function decodeUtf8Text(\n data: ArrayBuffer | ArrayBufferView,\n options: DecodeUtf8TextOptions = {},\n): string {\n try {\n return new TextDecoder('utf-8', { fatal: true }).decode(data);\n } catch {\n throw new FsError('corrupt', `${options.label ?? 'Text content'} is not valid UTF-8.`, {\n operation: options.operation ?? 'read',\n path: options.path,\n });\n }\n}\n"],"mappings":";;;;;AAgBO,SAAS,eACd,MACA,UAAiC,CAAC,GAC1B;AACR,MAAI;AACF,WAAO,IAAI,YAAY,SAAS,EAAE,OAAO,KAAK,CAAC,EAAE,OAAO,IAAI;AAAA,EAC9D,QAAQ;AACN,UAAM,IAAI,QAAQ,WAAW,GAAG,QAAQ,SAAS,cAAc,wBAAwB;AAAA,MACrF,WAAW,QAAQ,aAAa;AAAA,MAChC,MAAM,QAAQ;AAAA,IAChB,CAAC;AAAA,EACH;AACF;","names":[]}
@@ -0,0 +1,75 @@
1
+ // src/host/wire-policy.ts
2
+ var HOST_WIRE_LIMITS = Object.freeze({
3
+ identifierCharacters: 256,
4
+ labelCharacters: 1024,
5
+ pathCharacters: 4096,
6
+ urlCharacters: 8192,
7
+ messageCharacters: 2e3,
8
+ documentCharacters: 20 * 1024 * 1024,
9
+ binaryBytes: 100 * 1024 * 1024,
10
+ base64Characters: 140 * 1024 * 1024,
11
+ arrayEntries: 1e4
12
+ });
13
+ function hasExactKeys(value, keys) {
14
+ const actual = Object.keys(value);
15
+ return actual.length === keys.length && keys.every((key) => Object.prototype.hasOwnProperty.call(value, key));
16
+ }
17
+ function isBoundedString(value, maximumCharacters, minimumCharacters = 0) {
18
+ return typeof value === "string" && value.length >= minimumCharacters && value.length <= maximumCharacters && !value.includes("\0");
19
+ }
20
+ function isBoundedBytePayload(value, maximumBytes = HOST_WIRE_LIMITS.binaryBytes) {
21
+ return (value instanceof ArrayBuffer || value instanceof Uint8Array) && value.byteLength <= maximumBytes;
22
+ }
23
+ function parseOpenRequest(value) {
24
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
25
+ const record = value;
26
+ if (record.kind === "workspace-file") {
27
+ if (!hasExactKeys(record, ["kind", "workspaceId", "path"])) return null;
28
+ if (!isBoundedString(record.workspaceId, HOST_WIRE_LIMITS.identifierCharacters, 1)) return null;
29
+ if (!isBoundedString(record.path, HOST_WIRE_LIMITS.pathCharacters, 1)) return null;
30
+ return { kind: "workspace-file", workspaceId: record.workspaceId, path: record.path };
31
+ }
32
+ if (record.kind === "external-file" || record.kind === "external-bundle") {
33
+ if (!hasExactKeys(record, ["kind", "resourceId", "name"])) return null;
34
+ if (!isBoundedString(record.resourceId, HOST_WIRE_LIMITS.identifierCharacters, 1)) return null;
35
+ if (!isBoundedString(record.name, HOST_WIRE_LIMITS.labelCharacters, 1)) return null;
36
+ return { kind: record.kind, resourceId: record.resourceId, name: record.name };
37
+ }
38
+ return null;
39
+ }
40
+ function parseExternalHttpUrl(value) {
41
+ if (!isBoundedString(value, HOST_WIRE_LIMITS.urlCharacters, 1)) return null;
42
+ try {
43
+ const url = new URL(value);
44
+ if (url.protocol !== "http:" && url.protocol !== "https:") return null;
45
+ if (url.username || url.password) return null;
46
+ const canonical = url.href;
47
+ return canonical.length <= HOST_WIRE_LIMITS.urlCharacters ? canonical : null;
48
+ } catch {
49
+ return null;
50
+ }
51
+ }
52
+ function isTrustedRendererUrl(value, developmentOrigin) {
53
+ if (!isBoundedString(value, HOST_WIRE_LIMITS.urlCharacters, 1)) return false;
54
+ try {
55
+ const url = new URL(value);
56
+ if (url.protocol === "app:" && url.hostname === "docblocks" && url.port === "" && url.username === "" && url.password === "") {
57
+ return true;
58
+ }
59
+ if (!developmentOrigin) return false;
60
+ const trustedDevelopmentOrigin = new URL(developmentOrigin);
61
+ return url.origin === trustedDevelopmentOrigin.origin;
62
+ } catch {
63
+ return false;
64
+ }
65
+ }
66
+
67
+ export {
68
+ HOST_WIRE_LIMITS,
69
+ isBoundedString,
70
+ isBoundedBytePayload,
71
+ parseOpenRequest,
72
+ parseExternalHttpUrl,
73
+ isTrustedRendererUrl
74
+ };
75
+ //# sourceMappingURL=chunk-FNW556FN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/host/wire-policy.ts"],"sourcesContent":["import type { OpenRequest } from './types.js';\n\n/** Quantitative limits shared by privileged host boundaries. */\nexport const HOST_WIRE_LIMITS = Object.freeze({\n identifierCharacters: 256,\n labelCharacters: 1_024,\n pathCharacters: 4_096,\n urlCharacters: 8_192,\n messageCharacters: 2_000,\n documentCharacters: 20 * 1024 * 1024,\n binaryBytes: 100 * 1024 * 1024,\n base64Characters: 140 * 1024 * 1024,\n arrayEntries: 10_000,\n});\n\nfunction hasExactKeys(value: Record<string, unknown>, keys: readonly string[]): boolean {\n const actual = Object.keys(value);\n return (\n actual.length === keys.length &&\n keys.every((key) => Object.prototype.hasOwnProperty.call(value, key))\n );\n}\n\nexport function isBoundedString(\n value: unknown,\n maximumCharacters: number,\n minimumCharacters = 0,\n): value is string {\n return (\n typeof value === 'string' &&\n value.length >= minimumCharacters &&\n value.length <= maximumCharacters &&\n !value.includes('\\0')\n );\n}\n\nexport function isBoundedBytePayload(\n value: unknown,\n maximumBytes = HOST_WIRE_LIMITS.binaryBytes,\n): value is ArrayBuffer | Uint8Array {\n return (\n (value instanceof ArrayBuffer || value instanceof Uint8Array) &&\n value.byteLength <= maximumBytes\n );\n}\n\n/** Parse one exact, bounded main-to-renderer open request. */\nexport function parseOpenRequest(value: unknown): OpenRequest | null {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return null;\n const record = value as Record<string, unknown>;\n\n if (record.kind === 'workspace-file') {\n if (!hasExactKeys(record, ['kind', 'workspaceId', 'path'])) return null;\n if (!isBoundedString(record.workspaceId, HOST_WIRE_LIMITS.identifierCharacters, 1)) return null;\n if (!isBoundedString(record.path, HOST_WIRE_LIMITS.pathCharacters, 1)) return null;\n return { kind: 'workspace-file', workspaceId: record.workspaceId, path: record.path };\n }\n\n if (record.kind === 'external-file' || record.kind === 'external-bundle') {\n if (!hasExactKeys(record, ['kind', 'resourceId', 'name'])) return null;\n if (!isBoundedString(record.resourceId, HOST_WIRE_LIMITS.identifierCharacters, 1)) return null;\n if (!isBoundedString(record.name, HOST_WIRE_LIMITS.labelCharacters, 1)) return null;\n return { kind: record.kind, resourceId: record.resourceId, name: record.name };\n }\n\n return null;\n}\n\n/** Return one canonical HTTP(S) URL, or null when external navigation is unsafe. */\nexport function parseExternalHttpUrl(value: unknown): string | null {\n if (!isBoundedString(value, HOST_WIRE_LIMITS.urlCharacters, 1)) return null;\n try {\n const url = new URL(value);\n if (url.protocol !== 'http:' && url.protocol !== 'https:') return null;\n if (url.username || url.password) return null;\n const canonical = url.href;\n return canonical.length <= HOST_WIRE_LIMITS.urlCharacters ? canonical : null;\n } catch {\n return null;\n }\n}\n\n/** True only for the packaged renderer origin or the exact configured dev origin. */\nexport function isTrustedRendererUrl(value: unknown, developmentOrigin?: string): boolean {\n if (!isBoundedString(value, HOST_WIRE_LIMITS.urlCharacters, 1)) return false;\n try {\n const url = new URL(value);\n if (\n url.protocol === 'app:' &&\n url.hostname === 'docblocks' &&\n url.port === '' &&\n url.username === '' &&\n url.password === ''\n ) {\n return true;\n }\n if (!developmentOrigin) return false;\n const trustedDevelopmentOrigin = new URL(developmentOrigin);\n return url.origin === trustedDevelopmentOrigin.origin;\n } catch {\n return false;\n }\n}\n"],"mappings":";AAGO,IAAM,mBAAmB,OAAO,OAAO;AAAA,EAC5C,sBAAsB;AAAA,EACtB,iBAAiB;AAAA,EACjB,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,oBAAoB,KAAK,OAAO;AAAA,EAChC,aAAa,MAAM,OAAO;AAAA,EAC1B,kBAAkB,MAAM,OAAO;AAAA,EAC/B,cAAc;AAChB,CAAC;AAED,SAAS,aAAa,OAAgC,MAAkC;AACtF,QAAM,SAAS,OAAO,KAAK,KAAK;AAChC,SACE,OAAO,WAAW,KAAK,UACvB,KAAK,MAAM,CAAC,QAAQ,OAAO,UAAU,eAAe,KAAK,OAAO,GAAG,CAAC;AAExE;AAEO,SAAS,gBACd,OACA,mBACA,oBAAoB,GACH;AACjB,SACE,OAAO,UAAU,YACjB,MAAM,UAAU,qBAChB,MAAM,UAAU,qBAChB,CAAC,MAAM,SAAS,IAAI;AAExB;AAEO,SAAS,qBACd,OACA,eAAe,iBAAiB,aACG;AACnC,UACG,iBAAiB,eAAe,iBAAiB,eAClD,MAAM,cAAc;AAExB;AAGO,SAAS,iBAAiB,OAAoC;AACnE,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,QAAM,SAAS;AAEf,MAAI,OAAO,SAAS,kBAAkB;AACpC,QAAI,CAAC,aAAa,QAAQ,CAAC,QAAQ,eAAe,MAAM,CAAC,EAAG,QAAO;AACnE,QAAI,CAAC,gBAAgB,OAAO,aAAa,iBAAiB,sBAAsB,CAAC,EAAG,QAAO;AAC3F,QAAI,CAAC,gBAAgB,OAAO,MAAM,iBAAiB,gBAAgB,CAAC,EAAG,QAAO;AAC9E,WAAO,EAAE,MAAM,kBAAkB,aAAa,OAAO,aAAa,MAAM,OAAO,KAAK;AAAA,EACtF;AAEA,MAAI,OAAO,SAAS,mBAAmB,OAAO,SAAS,mBAAmB;AACxE,QAAI,CAAC,aAAa,QAAQ,CAAC,QAAQ,cAAc,MAAM,CAAC,EAAG,QAAO;AAClE,QAAI,CAAC,gBAAgB,OAAO,YAAY,iBAAiB,sBAAsB,CAAC,EAAG,QAAO;AAC1F,QAAI,CAAC,gBAAgB,OAAO,MAAM,iBAAiB,iBAAiB,CAAC,EAAG,QAAO;AAC/E,WAAO,EAAE,MAAM,OAAO,MAAM,YAAY,OAAO,YAAY,MAAM,OAAO,KAAK;AAAA,EAC/E;AAEA,SAAO;AACT;AAGO,SAAS,qBAAqB,OAA+B;AAClE,MAAI,CAAC,gBAAgB,OAAO,iBAAiB,eAAe,CAAC,EAAG,QAAO;AACvE,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,KAAK;AACzB,QAAI,IAAI,aAAa,WAAW,IAAI,aAAa,SAAU,QAAO;AAClE,QAAI,IAAI,YAAY,IAAI,SAAU,QAAO;AACzC,UAAM,YAAY,IAAI;AACtB,WAAO,UAAU,UAAU,iBAAiB,gBAAgB,YAAY;AAAA,EAC1E,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,qBAAqB,OAAgB,mBAAqC;AACxF,MAAI,CAAC,gBAAgB,OAAO,iBAAiB,eAAe,CAAC,EAAG,QAAO;AACvE,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,KAAK;AACzB,QACE,IAAI,aAAa,UACjB,IAAI,aAAa,eACjB,IAAI,SAAS,MACb,IAAI,aAAa,MACjB,IAAI,aAAa,IACjB;AACA,aAAO;AAAA,IACT;AACA,QAAI,CAAC,kBAAmB,QAAO;AAC/B,UAAM,2BAA2B,IAAI,IAAI,iBAAiB;AAC1D,WAAO,IAAI,WAAW,yBAAyB;AAAA,EACjD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
@@ -0,0 +1,29 @@
1
+ import {
2
+ workspacePathDirname
3
+ } from "./chunk-JS6XFWQK.js";
4
+
5
+ // src/filesystem/internal/parent-chain.ts
6
+ function parentChain(path) {
7
+ const parents = [];
8
+ let current = workspacePathDirname(path);
9
+ while (current) {
10
+ parents.unshift(current);
11
+ current = workspacePathDirname(current);
12
+ }
13
+ return parents;
14
+ }
15
+ function parentChainWithRoot(path) {
16
+ const parents = [];
17
+ let current = workspacePathDirname(path);
18
+ while (true) {
19
+ parents.unshift(current);
20
+ if (!current) return parents;
21
+ current = workspacePathDirname(current);
22
+ }
23
+ }
24
+
25
+ export {
26
+ parentChain,
27
+ parentChainWithRoot
28
+ };
29
+ //# sourceMappingURL=chunk-GM5YXU4L.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/filesystem/internal/parent-chain.ts"],"sourcesContent":["/**\n * Ancestor enumeration shared by every filesystem provider.\n *\n * Two variants exist because backends genuinely disagree about whether the\n * workspace root is an *entry*, and that difference is real rather than\n * accidental:\n *\n * - IndexedDB and memory store the root as a first-class directory record\n * (IndexedDB initialization fails with `corrupt` if the root record is\n * missing). Their parent walks must visit the root so it is version-bumped\n * and kind-checked like any other directory.\n * - Native (File System Access) has no root record — the root *is* the\n * directory handle the user granted, always present and never created.\n * Visiting it would be a guaranteed no-op.\n *\n * Both orderings are root-most first, so callers that create missing parents\n * create them top-down.\n */\n\nimport { workspacePathDirname, type WorkspacePath } from '../workspace-path.js';\n\n/**\n * Strict ancestors of `path`, excluding the workspace root.\n *\n * Use when the root is implicit and always exists.\n */\nexport function parentChain(path: WorkspacePath): WorkspacePath[] {\n const parents: WorkspacePath[] = [];\n let current = workspacePathDirname(path);\n while (current) {\n parents.unshift(current);\n current = workspacePathDirname(current);\n }\n return parents;\n}\n\n/**\n * Strict ancestors of `path`, including the workspace root as the first entry.\n *\n * Use when the root is a stored entry that participates in kind checks and\n * version bumps.\n */\nexport function parentChainWithRoot(path: WorkspacePath): WorkspacePath[] {\n const parents: WorkspacePath[] = [];\n let current = workspacePathDirname(path);\n while (true) {\n parents.unshift(current);\n if (!current) return parents;\n current = workspacePathDirname(current);\n }\n}\n"],"mappings":";;;;;AA0BO,SAAS,YAAY,MAAsC;AAChE,QAAM,UAA2B,CAAC;AAClC,MAAI,UAAU,qBAAqB,IAAI;AACvC,SAAO,SAAS;AACd,YAAQ,QAAQ,OAAO;AACvB,cAAU,qBAAqB,OAAO;AAAA,EACxC;AACA,SAAO;AACT;AAQO,SAAS,oBAAoB,MAAsC;AACxE,QAAM,UAA2B,CAAC;AAClC,MAAI,UAAU,qBAAqB,IAAI;AACvC,SAAO,MAAM;AACX,YAAQ,QAAQ,OAAO;AACvB,QAAI,CAAC,QAAS,QAAO;AACrB,cAAU,qBAAqB,OAAO;AAAA,EACxC;AACF;","names":[]}
@@ -0,0 +1,225 @@
1
+ // src/filesystem/fs-error.ts
2
+ var FS_ERROR_CODES = /* @__PURE__ */ new Set([
3
+ "invalid-path",
4
+ "path-escape",
5
+ "not-found",
6
+ "already-exists",
7
+ "type-mismatch",
8
+ "not-empty",
9
+ "permission-denied",
10
+ "conflict",
11
+ "corrupt",
12
+ "quota-exceeded",
13
+ "not-supported",
14
+ "busy",
15
+ "disposed",
16
+ "closed",
17
+ "aborted",
18
+ "io"
19
+ ]);
20
+ var FS_OPERATIONS = /* @__PURE__ */ new Set([
21
+ "parse-path",
22
+ "read",
23
+ "stat",
24
+ "list",
25
+ "write",
26
+ "create-directory",
27
+ "remove",
28
+ "move",
29
+ "snapshot",
30
+ "watch",
31
+ "dispose"
32
+ ]);
33
+ var FsError = class extends Error {
34
+ constructor(code, message, context = {}) {
35
+ super(message);
36
+ this.name = "FsError";
37
+ this.code = code;
38
+ this.operation = context.operation ?? null;
39
+ this.path = context.path ?? null;
40
+ this.destinationPath = context.destinationPath ?? null;
41
+ this.retryable = context.retryable ?? (code === "io" || code === "aborted" || code === "busy");
42
+ }
43
+ toJSON() {
44
+ return {
45
+ name: "FsError",
46
+ code: this.code,
47
+ message: this.message,
48
+ operation: this.operation,
49
+ path: this.path,
50
+ destinationPath: this.destinationPath,
51
+ retryable: this.retryable
52
+ };
53
+ }
54
+ };
55
+ function mapDomExceptionToFsErrorCode(name) {
56
+ switch (name) {
57
+ case "NotFoundError":
58
+ return "not-found";
59
+ case "ConstraintError":
60
+ return "already-exists";
61
+ case "TypeMismatchError":
62
+ return "type-mismatch";
63
+ case "InvalidModificationError":
64
+ return "not-empty";
65
+ case "NotAllowedError":
66
+ case "SecurityError":
67
+ case "NoModificationAllowedError":
68
+ return "permission-denied";
69
+ case "QuotaExceededError":
70
+ return "quota-exceeded";
71
+ case "NotSupportedError":
72
+ return "not-supported";
73
+ case "InvalidStateError":
74
+ return "disposed";
75
+ case "AbortError":
76
+ return "aborted";
77
+ default:
78
+ return "io";
79
+ }
80
+ }
81
+ function mapNodeErrorCodeToFsErrorCode(code) {
82
+ switch (code) {
83
+ case "ENOENT":
84
+ return "not-found";
85
+ case "ENOTDIR":
86
+ return "type-mismatch";
87
+ case "EEXIST":
88
+ return "already-exists";
89
+ case "EISDIR":
90
+ return "type-mismatch";
91
+ case "ENOTEMPTY":
92
+ return "not-empty";
93
+ case "EACCES":
94
+ case "EPERM":
95
+ return "permission-denied";
96
+ case "ENOSPC":
97
+ case "EDQUOT":
98
+ return "quota-exceeded";
99
+ case "EBUSY":
100
+ return "busy";
101
+ case "EXDEV":
102
+ case "ENOTSUP":
103
+ case "EOPNOTSUPP":
104
+ return "not-supported";
105
+ default:
106
+ return "io";
107
+ }
108
+ }
109
+ function isSerializedFsError(value) {
110
+ if (!value || typeof value !== "object") return false;
111
+ const candidate = value;
112
+ return candidate.name === "FsError" && typeof candidate.code === "string" && FS_ERROR_CODES.has(candidate.code) && typeof candidate.message === "string" && (candidate.operation === null || typeof candidate.operation === "string" && FS_OPERATIONS.has(candidate.operation)) && (candidate.path === null || typeof candidate.path === "string") && (candidate.destinationPath === null || typeof candidate.destinationPath === "string") && typeof candidate.retryable === "boolean";
113
+ }
114
+ function deserializeFsError(value) {
115
+ return new FsError(value.code, value.message, {
116
+ operation: value.operation ?? void 0,
117
+ path: value.path ?? void 0,
118
+ destinationPath: value.destinationPath ?? void 0,
119
+ retryable: value.retryable
120
+ });
121
+ }
122
+ function fsErrorFromUnknown(error, context = {}) {
123
+ if (error instanceof FsError) return error;
124
+ if (isSerializedFsError(error)) return deserializeFsError(error);
125
+ const name = getErrorStringField(error, "name");
126
+ const nodeCode = getErrorStringField(error, "code");
127
+ const message = getErrorStringField(error, "message") ?? String(error);
128
+ const code = context.defaultCode ?? (nodeCode ? mapNodeErrorCodeToFsErrorCode(nodeCode) : name ? mapDomExceptionToFsErrorCode(name) : "io");
129
+ return new FsError(code, message, context);
130
+ }
131
+ function serializeFsError(error, context = {}) {
132
+ return fsErrorFromUnknown(error, context).toJSON();
133
+ }
134
+ function isQuotaExceededError(error) {
135
+ if (error instanceof FsError) return error.code === "quota-exceeded";
136
+ if (isSerializedFsError(error)) return error.code === "quota-exceeded";
137
+ return getErrorStringField(error, "name") === "QuotaExceededError";
138
+ }
139
+ function getErrorStringField(error, key) {
140
+ if (!error || typeof error !== "object") return null;
141
+ const value = error[key];
142
+ return typeof value === "string" ? value : null;
143
+ }
144
+
145
+ // src/filesystem/workspace-path.ts
146
+ var WORKSPACE_ROOT = "";
147
+ function parseWorkspacePath(input) {
148
+ if ([...input].some((character) => {
149
+ const codePoint = character.codePointAt(0) ?? 0;
150
+ return codePoint <= 31 || codePoint === 127;
151
+ })) {
152
+ throw invalidPath(input, "Workspace paths must not contain NUL or other control characters.");
153
+ }
154
+ if (/^[a-zA-Z]:/u.test(input)) {
155
+ throw new FsError("path-escape", "Workspace paths must not be OS drive-qualified paths.", {
156
+ operation: "parse-path",
157
+ path: input
158
+ });
159
+ }
160
+ const normalized = input.replace(/\\/g, "/").replace(/\/+/g, "/").replace(/^\/|\/$/g, "");
161
+ if (!normalized) return WORKSPACE_ROOT;
162
+ const segments = normalized.split("/");
163
+ if (segments.some((segment) => segment === "." || segment === "..")) {
164
+ throw new FsError("path-escape", 'Workspace paths must not contain "." or ".." segments.', {
165
+ operation: "parse-path",
166
+ path: input
167
+ });
168
+ }
169
+ return normalized;
170
+ }
171
+ function tryParseWorkspacePath(input) {
172
+ if (typeof input !== "string") return null;
173
+ try {
174
+ return parseWorkspacePath(input);
175
+ } catch {
176
+ return null;
177
+ }
178
+ }
179
+ function workspacePathToLegacy(path) {
180
+ return path ? `/${path}` : "/";
181
+ }
182
+ function workspacePathJoin(parent, child) {
183
+ const childPath = parseWorkspacePath(child);
184
+ if (!parent) return childPath;
185
+ if (!childPath) return parent;
186
+ return parseWorkspacePath(`${parent}/${childPath}`);
187
+ }
188
+ function workspacePathDirname(path) {
189
+ if (!path) return WORKSPACE_ROOT;
190
+ const slash = path.lastIndexOf("/");
191
+ return slash < 0 ? WORKSPACE_ROOT : path.slice(0, slash);
192
+ }
193
+ function workspacePathBasename(path) {
194
+ if (!path) return "";
195
+ const slash = path.lastIndexOf("/");
196
+ return slash < 0 ? path : path.slice(slash + 1);
197
+ }
198
+ function workspacePathContains(parent, candidate, inclusive = true) {
199
+ if (parent === candidate) return inclusive;
200
+ if (!parent) return candidate !== WORKSPACE_ROOT;
201
+ return candidate.startsWith(`${parent}/`);
202
+ }
203
+ function invalidPath(path, message) {
204
+ return new FsError("invalid-path", message, { operation: "parse-path", path });
205
+ }
206
+
207
+ export {
208
+ FsError,
209
+ mapDomExceptionToFsErrorCode,
210
+ mapNodeErrorCodeToFsErrorCode,
211
+ isSerializedFsError,
212
+ deserializeFsError,
213
+ fsErrorFromUnknown,
214
+ serializeFsError,
215
+ isQuotaExceededError,
216
+ WORKSPACE_ROOT,
217
+ parseWorkspacePath,
218
+ tryParseWorkspacePath,
219
+ workspacePathToLegacy,
220
+ workspacePathJoin,
221
+ workspacePathDirname,
222
+ workspacePathBasename,
223
+ workspacePathContains
224
+ };
225
+ //# sourceMappingURL=chunk-JS6XFWQK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/filesystem/fs-error.ts","../src/filesystem/workspace-path.ts"],"sourcesContent":["/** Stable error codes shared by every filesystem transport and backend. */\nexport type FsErrorCode =\n | 'invalid-path'\n | 'path-escape'\n | 'not-found'\n | 'already-exists'\n | 'type-mismatch'\n | 'not-empty'\n | 'permission-denied'\n | 'conflict'\n | 'corrupt'\n | 'quota-exceeded'\n | 'not-supported'\n | 'busy'\n | 'disposed'\n | 'closed'\n | 'aborted'\n | 'io';\n\nexport type FsOperation =\n | 'parse-path'\n | 'read'\n | 'stat'\n | 'list'\n | 'write'\n | 'create-directory'\n | 'remove'\n | 'move'\n | 'snapshot'\n | 'watch'\n | 'dispose';\n\n/** Plain-data form safe to send over IPC, postMessage, or JSON. */\nexport interface SerializedFsError {\n readonly name: 'FsError';\n readonly code: FsErrorCode;\n readonly message: string;\n readonly operation: FsOperation | null;\n readonly path: string | null;\n readonly destinationPath: string | null;\n readonly retryable: boolean;\n}\n\nexport interface FsErrorContext {\n readonly operation?: FsOperation;\n readonly path?: string;\n readonly destinationPath?: string;\n readonly retryable?: boolean;\n readonly defaultCode?: FsErrorCode;\n}\n\nconst FS_ERROR_CODES: ReadonlySet<string> = new Set<FsErrorCode>([\n 'invalid-path',\n 'path-escape',\n 'not-found',\n 'already-exists',\n 'type-mismatch',\n 'not-empty',\n 'permission-denied',\n 'conflict',\n 'corrupt',\n 'quota-exceeded',\n 'not-supported',\n 'busy',\n 'disposed',\n 'closed',\n 'aborted',\n 'io',\n]);\n\nconst FS_OPERATIONS: ReadonlySet<string> = new Set<FsOperation>([\n 'parse-path',\n 'read',\n 'stat',\n 'list',\n 'write',\n 'create-directory',\n 'remove',\n 'move',\n 'snapshot',\n 'watch',\n 'dispose',\n]);\n\n/** Error with a stable code and a deliberately serializable public shape. */\nexport class FsError extends Error {\n public readonly code: FsErrorCode;\n public readonly operation: FsOperation | null;\n public readonly path: string | null;\n public readonly destinationPath: string | null;\n public readonly retryable: boolean;\n\n public constructor(code: FsErrorCode, message: string, context: FsErrorContext = {}) {\n super(message);\n this.name = 'FsError';\n this.code = code;\n this.operation = context.operation ?? null;\n this.path = context.path ?? null;\n this.destinationPath = context.destinationPath ?? null;\n this.retryable = context.retryable ?? (code === 'io' || code === 'aborted' || code === 'busy');\n }\n\n public toJSON(): SerializedFsError {\n return {\n name: 'FsError',\n code: this.code,\n message: this.message,\n operation: this.operation,\n path: this.path,\n destinationPath: this.destinationPath,\n retryable: this.retryable,\n };\n }\n}\n\nexport function mapDomExceptionToFsErrorCode(name: string): FsErrorCode {\n switch (name) {\n case 'NotFoundError':\n return 'not-found';\n case 'ConstraintError':\n return 'already-exists';\n case 'TypeMismatchError':\n return 'type-mismatch';\n case 'InvalidModificationError':\n return 'not-empty';\n case 'NotAllowedError':\n case 'SecurityError':\n case 'NoModificationAllowedError':\n return 'permission-denied';\n case 'QuotaExceededError':\n return 'quota-exceeded';\n case 'NotSupportedError':\n return 'not-supported';\n case 'InvalidStateError':\n return 'disposed';\n case 'AbortError':\n return 'aborted';\n default:\n return 'io';\n }\n}\n\nexport function mapNodeErrorCodeToFsErrorCode(code: string): FsErrorCode {\n switch (code) {\n case 'ENOENT':\n return 'not-found';\n case 'ENOTDIR':\n return 'type-mismatch';\n case 'EEXIST':\n return 'already-exists';\n case 'EISDIR':\n return 'type-mismatch';\n case 'ENOTEMPTY':\n return 'not-empty';\n case 'EACCES':\n case 'EPERM':\n return 'permission-denied';\n case 'ENOSPC':\n case 'EDQUOT':\n return 'quota-exceeded';\n case 'EBUSY':\n return 'busy';\n case 'EXDEV':\n case 'ENOTSUP':\n case 'EOPNOTSUPP':\n return 'not-supported';\n default:\n return 'io';\n }\n}\n\nexport function isSerializedFsError(value: unknown): value is SerializedFsError {\n if (!value || typeof value !== 'object') return false;\n const candidate = value as Partial<Record<keyof SerializedFsError, unknown>>;\n return (\n candidate.name === 'FsError' &&\n typeof candidate.code === 'string' &&\n FS_ERROR_CODES.has(candidate.code) &&\n typeof candidate.message === 'string' &&\n (candidate.operation === null ||\n (typeof candidate.operation === 'string' && FS_OPERATIONS.has(candidate.operation))) &&\n (candidate.path === null || typeof candidate.path === 'string') &&\n (candidate.destinationPath === null || typeof candidate.destinationPath === 'string') &&\n typeof candidate.retryable === 'boolean'\n );\n}\n\nexport function deserializeFsError(value: SerializedFsError): FsError {\n return new FsError(value.code, value.message, {\n operation: value.operation ?? undefined,\n path: value.path ?? undefined,\n destinationPath: value.destinationPath ?? undefined,\n retryable: value.retryable,\n });\n}\n\nexport function fsErrorFromUnknown(error: unknown, context: FsErrorContext = {}): FsError {\n if (error instanceof FsError) return error;\n if (isSerializedFsError(error)) return deserializeFsError(error);\n\n const name = getErrorStringField(error, 'name');\n const nodeCode = getErrorStringField(error, 'code');\n const message = getErrorStringField(error, 'message') ?? String(error);\n const code =\n context.defaultCode ??\n (nodeCode\n ? mapNodeErrorCodeToFsErrorCode(nodeCode)\n : name\n ? mapDomExceptionToFsErrorCode(name)\n : 'io');\n return new FsError(code, message, context);\n}\n\nexport function serializeFsError(error: unknown, context: FsErrorContext = {}): SerializedFsError {\n return fsErrorFromUnknown(error, context).toJSON();\n}\n\n/**\n * True when a storage backend rejected an operation because the origin or\n * device is out of space. Covers typed `FsError`s (`'quota-exceeded'`, from\n * DOMException `QuotaExceededError` or Node `ENOSPC`/`EDQUOT`), serialized\n * transport copies, and raw DOMExceptions from backends that do not wrap\n * their errors (e.g. the File System Access API) — including cross-realm\n * instances where `instanceof DOMException` would fail.\n */\nexport function isQuotaExceededError(error: unknown): boolean {\n if (error instanceof FsError) return error.code === 'quota-exceeded';\n if (isSerializedFsError(error)) return error.code === 'quota-exceeded';\n return getErrorStringField(error, 'name') === 'QuotaExceededError';\n}\n\nfunction getErrorStringField(error: unknown, key: 'name' | 'message' | 'code'): string | null {\n if (!error || typeof error !== 'object') return null;\n const value = (error as Record<string, unknown>)[key];\n return typeof value === 'string' ? value : null;\n}\n","import { FsError } from './fs-error.js';\n\ndeclare const workspacePathBrand: unique symbol;\n\n/** Canonical, root-relative, forward-slash path within one workspace. */\nexport type WorkspacePath = string & { readonly [workspacePathBrand]: 'WorkspacePath' };\n\nexport const WORKSPACE_ROOT = '' as WorkspacePath;\n\n/**\n * Parse a legacy/user path into its one canonical workspace representation.\n * Leading/trailing and repeated separators are normalized; traversal and NUL\n * segments are rejected rather than resolved.\n */\nexport function parseWorkspacePath(input: string): WorkspacePath {\n if (\n [...input].some((character) => {\n const codePoint = character.codePointAt(0) ?? 0;\n return codePoint <= 0x1f || codePoint === 0x7f;\n })\n ) {\n throw invalidPath(input, 'Workspace paths must not contain NUL or other control characters.');\n }\n if (/^[a-zA-Z]:/u.test(input)) {\n throw new FsError('path-escape', 'Workspace paths must not be OS drive-qualified paths.', {\n operation: 'parse-path',\n path: input,\n });\n }\n\n const normalized = input\n .replace(/\\\\/g, '/')\n .replace(/\\/+/g, '/')\n .replace(/^\\/|\\/$/g, '');\n if (!normalized) return WORKSPACE_ROOT;\n\n const segments = normalized.split('/');\n if (segments.some((segment) => segment === '.' || segment === '..')) {\n throw new FsError('path-escape', 'Workspace paths must not contain \".\" or \"..\" segments.', {\n operation: 'parse-path',\n path: input,\n });\n }\n return normalized as WorkspacePath;\n}\n\nexport function tryParseWorkspacePath(input: unknown): WorkspacePath | null {\n if (typeof input !== 'string') return null;\n try {\n return parseWorkspacePath(input);\n } catch {\n return null;\n }\n}\n\n/** Convert a canonical path to the slash-prefixed form accepted by v1 providers. */\nexport function workspacePathToLegacy(path: WorkspacePath): string {\n return path ? `/${path}` : '/';\n}\n\nexport function workspacePathJoin(parent: WorkspacePath, child: string): WorkspacePath {\n const childPath = parseWorkspacePath(child);\n if (!parent) return childPath;\n if (!childPath) return parent;\n return parseWorkspacePath(`${parent}/${childPath}`);\n}\n\nexport function workspacePathDirname(path: WorkspacePath): WorkspacePath {\n if (!path) return WORKSPACE_ROOT;\n const slash = path.lastIndexOf('/');\n return slash < 0 ? WORKSPACE_ROOT : (path.slice(0, slash) as WorkspacePath);\n}\n\nexport function workspacePathBasename(path: WorkspacePath): string {\n if (!path) return '';\n const slash = path.lastIndexOf('/');\n return slash < 0 ? path : path.slice(slash + 1);\n}\n\nexport function workspacePathContains(\n parent: WorkspacePath,\n candidate: WorkspacePath,\n inclusive = true,\n): boolean {\n if (parent === candidate) return inclusive;\n if (!parent) return candidate !== WORKSPACE_ROOT;\n return candidate.startsWith(`${parent}/`);\n}\n\nfunction invalidPath(path: string, message: string): FsError {\n return new FsError('invalid-path', message, { operation: 'parse-path', path });\n}\n"],"mappings":"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","names":[]}