shell-dsl 0.0.34 → 0.0.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -3
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/src/fs/memfs-adapter.cjs +56 -2
- package/dist/cjs/src/fs/memfs-adapter.cjs.map +3 -3
- package/dist/cjs/src/fs/real-fs.cjs +134 -3
- package/dist/cjs/src/fs/real-fs.cjs.map +3 -3
- package/dist/cjs/src/fs/special-files.cjs +3 -2
- package/dist/cjs/src/fs/special-files.cjs.map +3 -3
- package/dist/cjs/src/fs/web-fs.cjs +72 -3
- package/dist/cjs/src/fs/web-fs.cjs.map +3 -3
- package/dist/cjs/src/index.cjs.map +2 -2
- package/dist/cjs/src/types.cjs.map +2 -2
- package/dist/cjs/src/vcs/content.cjs +106 -0
- package/dist/cjs/src/vcs/content.cjs.map +10 -0
- package/dist/cjs/src/vcs/diff.cjs +72 -28
- package/dist/cjs/src/vcs/diff.cjs.map +3 -3
- package/dist/cjs/src/vcs/index.cjs.map +1 -1
- package/dist/cjs/src/vcs/objects.cjs +141 -0
- package/dist/cjs/src/vcs/objects.cjs.map +10 -0
- package/dist/cjs/src/vcs/rules.cjs +6 -3
- package/dist/cjs/src/vcs/rules.cjs.map +3 -3
- package/dist/cjs/src/vcs/snapshot.cjs +89 -39
- package/dist/cjs/src/vcs/snapshot.cjs.map +3 -3
- package/dist/cjs/src/vcs/storage.cjs +44 -3
- package/dist/cjs/src/vcs/storage.cjs.map +3 -3
- package/dist/cjs/src/vcs/text-diff.cjs +219 -0
- package/dist/cjs/src/vcs/text-diff.cjs.map +10 -0
- package/dist/cjs/src/vcs/vcs.cjs +108 -61
- package/dist/cjs/src/vcs/vcs.cjs.map +3 -3
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/src/fs/memfs-adapter.mjs +57 -2
- package/dist/mjs/src/fs/memfs-adapter.mjs.map +3 -3
- package/dist/mjs/src/fs/real-fs.mjs +135 -3
- package/dist/mjs/src/fs/real-fs.mjs.map +3 -3
- package/dist/mjs/src/fs/special-files.mjs +3 -2
- package/dist/mjs/src/fs/special-files.mjs.map +3 -3
- package/dist/mjs/src/fs/web-fs.mjs +72 -3
- package/dist/mjs/src/fs/web-fs.mjs.map +3 -3
- package/dist/mjs/src/index.mjs.map +2 -2
- package/dist/mjs/src/types.mjs.map +2 -2
- package/dist/mjs/src/vcs/content.mjs +66 -0
- package/dist/mjs/src/vcs/content.mjs.map +10 -0
- package/dist/mjs/src/vcs/diff.mjs +72 -28
- package/dist/mjs/src/vcs/diff.mjs.map +3 -3
- package/dist/mjs/src/vcs/index.mjs.map +1 -1
- package/dist/mjs/src/vcs/objects.mjs +106 -0
- package/dist/mjs/src/vcs/objects.mjs.map +10 -0
- package/dist/mjs/src/vcs/rules.mjs +6 -3
- package/dist/mjs/src/vcs/rules.mjs.map +3 -3
- package/dist/mjs/src/vcs/snapshot.mjs +89 -39
- package/dist/mjs/src/vcs/snapshot.mjs.map +3 -3
- package/dist/mjs/src/vcs/storage.mjs +45 -3
- package/dist/mjs/src/vcs/storage.mjs.map +3 -3
- package/dist/mjs/src/vcs/text-diff.mjs +179 -0
- package/dist/mjs/src/vcs/text-diff.mjs.map +10 -0
- package/dist/mjs/src/vcs/vcs.mjs +115 -63
- package/dist/mjs/src/vcs/vcs.mjs.map +3 -3
- package/dist/types/src/fs/real-fs.d.ts +12 -1
- package/dist/types/src/index.d.ts +2 -2
- package/dist/types/src/types.d.ts +10 -0
- package/dist/types/src/vcs/content.d.ts +6 -0
- package/dist/types/src/vcs/diff.d.ts +10 -7
- package/dist/types/src/vcs/index.d.ts +1 -1
- package/dist/types/src/vcs/objects.d.ts +22 -0
- package/dist/types/src/vcs/snapshot.d.ts +13 -8
- package/dist/types/src/vcs/storage.d.ts +7 -1
- package/dist/types/src/vcs/text-diff.d.ts +1 -0
- package/dist/types/src/vcs/types.d.ts +20 -5
- package/dist/types/src/vcs/vcs.d.ts +6 -0
- package/package.json +7 -2
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/fs/web-fs.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import { FileSystem, type PathOps, type PermissionRules, type UnderlyingFS } from \"./real-fs.cjs\";\n\nconst DIRECTORY_MTIME = new Date(0);\nconst WEB_PATH_OPS: PathOps = {\n separator: \"/\",\n resolve(...paths: string[]): string {\n return normalizeWebPath(paths.join(\"/\"));\n },\n normalize: normalizeWebPath,\n join(...paths: string[]): string {\n const nonEmpty = paths.filter((segment) => segment.length > 0);\n if (nonEmpty.length === 0) {\n return \".\";\n }\n return normalizeWebPath(nonEmpty.join(\"/\"));\n },\n relative(from: string, to: string): string {\n const fromSegments = getPathSegments(from);\n const toSegments = getPathSegments(to);\n let shared = 0;\n\n while (\n shared < fromSegments.length &&\n shared < toSegments.length &&\n fromSegments[shared] === toSegments[shared]\n ) {\n shared++;\n }\n\n const up = new Array(fromSegments.length - shared).fill(\"..\");\n const down = toSegments.slice(shared);\n return [...up, ...down].join(\"/\");\n },\n isAbsolute(path: string): boolean {\n return path.startsWith(\"/\");\n },\n dirname(path: string): string {\n const normalized = normalizeWebPath(path);\n if (normalized === \"/\") {\n return \"/\";\n }\n\n const segments = getPathSegments(normalized);\n if (segments.length <= 1) {\n return \"/\";\n }\n\n return `/${segments.slice(0, -1).join(\"/\")}`;\n },\n basename(path: string): string {\n const normalized = normalizeWebPath(path);\n if (normalized === \"/\") {\n return \"\";\n }\n\n const segments = getPathSegments(normalized);\n return segments[segments.length - 1] ?? \"\";\n },\n};\n\nexport function createWebUnderlyingFS(root: FileSystemDirectoryHandle): UnderlyingFS {\n return {\n pathOps: WEB_PATH_OPS,\n promises: {\n async readFile(path: string): Promise<Buffer> {\n const { parentSegments, name } = splitParent(path);\n const parent = await walkDirectory(root, parentSegments, false);\n const fileHandle = await parent.getFileHandle(name, { create: false });\n const file = await fileHandle.getFile();\n return Buffer.from(await file.arrayBuffer());\n },\n\n async readdir(path: string): Promise<string[]> {\n const dir = await walkDirectory(root, getPathSegments(path), false);\n const entries: string[] = [];\n for await (const [name] of dir.entries()) {\n entries.push(name);\n }\n return entries;\n },\n\n async stat(path: string): Promise<{\n isFile(): boolean;\n isDirectory(): boolean;\n size: number;\n mtime: Date;\n }> {\n const segments = getPathSegments(path);\n\n if (segments.length === 0) {\n return createDirectoryStat();\n }\n\n const { parentSegments, name } = splitParent(path);\n const parent = await walkDirectory(root, parentSegments, false);\n\n try {\n const fileHandle = await parent.getFileHandle(name, { create: false });\n const file = await fileHandle.getFile();\n return {\n isFile: () => true,\n isDirectory: () => false,\n size: file.size,\n mtime: new Date(file.lastModified ?? 0),\n };\n } catch (error) {\n if (!isNotFoundOrTypeMismatch(error)) throw error;\n }\n\n try {\n await parent.getDirectoryHandle(name, { create: false });\n return createDirectoryStat();\n } catch (error) {\n if (!isNotFoundOrTypeMismatch(error)) throw error;\n throw error;\n }\n },\n\n async writeFile(path: string, data: Buffer | string): Promise<void> {\n const { parentSegments, name } = splitParent(path);\n const parent = await walkDirectory(root, parentSegments, false);\n const fileHandle = await parent.getFileHandle(name, { create: true });\n const writable = await fileHandle.createWritable();\n await writable.write(toWritableData(data));\n await writable.close();\n },\n\n async appendFile(path: string, data: Buffer | string): Promise<void> {\n const { parentSegments, name } = splitParent(path);\n const parent = await walkDirectory(root, parentSegments, false);\n const fileHandle = await parent.getFileHandle(name, { create: true });\n const file = await fileHandle.getFile();\n const writable = await fileHandle.createWritable({ keepExistingData: true });\n await writable.write({\n type: \"write\",\n position: file.size,\n data: toWritableData(data),\n });\n await writable.close();\n },\n\n async mkdir(path: string, opts?: { recursive?: boolean }): Promise<void> {\n const segments = getPathSegments(path);\n if (segments.length === 0) {\n return;\n }\n\n if (opts?.recursive) {\n await walkDirectory(root, segments, true);\n return;\n }\n\n const parent = await walkDirectory(root, segments.slice(0, -1), false);\n const name = segments[segments.length - 1]!;\n const exists = await entryExists(parent, name);\n if (exists) {\n throw new Error(`EEXIST: file already exists, mkdir '${normalizeWebPath(path)}'`);\n }\n await parent.getDirectoryHandle(name, { create: true });\n },\n\n async rm(path: string, opts?: { recursive?: boolean; force?: boolean }): Promise<void> {\n const segments = getPathSegments(path);\n if (segments.length === 0) {\n throw new Error(\"EPERM: operation not permitted, rm '/'\");\n }\n\n const parent = await walkDirectory(root, segments.slice(0, -1), false);\n const name = segments[segments.length - 1]!;\n try {\n await parent.removeEntry(name, { recursive: opts?.recursive });\n } catch (error) {\n if (opts?.force && isNotFoundError(error)) {\n return;\n }\n throw error;\n }\n },\n },\n };\n}\n\nexport class WebFileSystem extends FileSystem {\n constructor(root: FileSystemDirectoryHandle, permissions?: PermissionRules) {\n super(\"/\", permissions, createWebUnderlyingFS(root));\n }\n}\n\nfunction createDirectoryStat() {\n return {\n isFile: () => false,\n isDirectory: () => true,\n size: 0,\n mtime: DIRECTORY_MTIME,\n };\n}\n\nfunction normalizeWebPath(path: string): string {\n const normalized = path.replace(/\\\\/g, \"/\");\n const rawSegments = (normalized.startsWith(\"/\") ? normalized : `/${normalized}`)\n .split(\"/\")\n .filter(Boolean);\n\n const segments: string[] = [];\n for (const segment of rawSegments) {\n if (segment === \".\") continue;\n if (segment === \"..\") {\n segments.pop();\n continue;\n }\n segments.push(segment);\n }\n\n return `/${segments.join(\"/\")}`;\n}\n\nfunction getPathSegments(path: string): string[] {\n const normalized = normalizeWebPath(path);\n return normalized.split(\"/\").filter(Boolean);\n}\n\nfunction splitParent(path: string): { parentSegments: string[]; name: string } {\n const segments = getPathSegments(path);\n if (segments.length === 0) {\n throw new Error(`Invalid file path: \"${path}\"`);\n }\n return {\n parentSegments: segments.slice(0, -1),\n name: segments[segments.length - 1]!,\n };\n}\n\nasync function walkDirectory(\n root: FileSystemDirectoryHandle,\n segments: string[],\n create: boolean\n): Promise<FileSystemDirectoryHandle> {\n let current = root;\n for (const segment of segments) {\n current = await current.getDirectoryHandle(segment, { create });\n }\n return current;\n}\n\nasync function entryExists(dir: FileSystemDirectoryHandle, name: string): Promise<boolean> {\n try {\n await dir.getFileHandle(name, { create: false });\n return true;\n } catch (error) {\n if (isTypeMismatchError(error)) return true;\n if (!isNotFoundError(error)) throw error;\n }\n\n try {\n await dir.getDirectoryHandle(name, { create: false });\n return true;\n } catch (error) {\n if (isTypeMismatchError(error)) return true;\n if (!isNotFoundError(error)) throw error;\n return false;\n }\n}\n\nfunction isNotFoundOrTypeMismatch(error: unknown): boolean {\n return isNotFoundError(error) || isTypeMismatchError(error);\n}\n\nfunction isNotFoundError(error: unknown): boolean {\n return getErrorName(error) === \"NotFoundError\";\n}\n\nfunction isTypeMismatchError(error: unknown): boolean {\n return getErrorName(error) === \"TypeMismatchError\";\n}\n\nfunction getErrorName(error: unknown): string | undefined {\n if (!error || typeof error !== \"object\") return undefined;\n const named = error as { name?: unknown };\n return typeof named.name === \"string\" ? named.name : undefined;\n}\n\nfunction toWritableData(data: Buffer | string): string | ArrayBuffer {\n if (typeof data === \"string\") {\n return data;\n }\n const out = new Uint8Array(data.length);\n out.set(data);\n return out.buffer;\n}\n"
|
|
5
|
+
"import type { VirtualFSWritable } from \"../types.cjs\";\nimport { FileSystem, type PathOps, type PermissionRules, type UnderlyingFS } from \"./real-fs.cjs\";\n\nconst DIRECTORY_MTIME = new Date(0);\nconst WEB_PATH_OPS: PathOps = {\n separator: \"/\",\n resolve(...paths: string[]): string {\n return normalizeWebPath(paths.join(\"/\"));\n },\n normalize: normalizeWebPath,\n join(...paths: string[]): string {\n const nonEmpty = paths.filter((segment) => segment.length > 0);\n if (nonEmpty.length === 0) {\n return \".\";\n }\n return normalizeWebPath(nonEmpty.join(\"/\"));\n },\n relative(from: string, to: string): string {\n const fromSegments = getPathSegments(from);\n const toSegments = getPathSegments(to);\n let shared = 0;\n\n while (\n shared < fromSegments.length &&\n shared < toSegments.length &&\n fromSegments[shared] === toSegments[shared]\n ) {\n shared++;\n }\n\n const up = new Array(fromSegments.length - shared).fill(\"..\");\n const down = toSegments.slice(shared);\n return [...up, ...down].join(\"/\");\n },\n isAbsolute(path: string): boolean {\n return path.startsWith(\"/\");\n },\n dirname(path: string): string {\n const normalized = normalizeWebPath(path);\n if (normalized === \"/\") {\n return \"/\";\n }\n\n const segments = getPathSegments(normalized);\n if (segments.length <= 1) {\n return \"/\";\n }\n\n return `/${segments.slice(0, -1).join(\"/\")}`;\n },\n basename(path: string): string {\n const normalized = normalizeWebPath(path);\n if (normalized === \"/\") {\n return \"\";\n }\n\n const segments = getPathSegments(normalized);\n return segments[segments.length - 1] ?? \"\";\n },\n};\n\nexport function createWebUnderlyingFS(root: FileSystemDirectoryHandle): UnderlyingFS {\n return {\n pathOps: WEB_PATH_OPS,\n promises: {\n async readFile(path: string): Promise<Buffer> {\n const { parentSegments, name } = splitParent(path);\n const parent = await walkDirectory(root, parentSegments, false);\n const fileHandle = await parent.getFileHandle(name, { create: false });\n const file = await fileHandle.getFile();\n return Buffer.from(await file.arrayBuffer());\n },\n\n async readdir(path: string): Promise<string[]> {\n const dir = await walkDirectory(root, getPathSegments(path), false);\n const entries: string[] = [];\n for await (const [name] of dir.entries()) {\n entries.push(name);\n }\n return entries;\n },\n\n async stat(path: string): Promise<{\n isFile(): boolean;\n isDirectory(): boolean;\n size: number;\n mtime: Date;\n mtimeMs: number;\n }> {\n const segments = getPathSegments(path);\n\n if (segments.length === 0) {\n return createDirectoryStat();\n }\n\n const { parentSegments, name } = splitParent(path);\n const parent = await walkDirectory(root, parentSegments, false);\n\n try {\n const fileHandle = await parent.getFileHandle(name, { create: false });\n const file = await fileHandle.getFile();\n return {\n isFile: () => true,\n isDirectory: () => false,\n size: file.size,\n mtime: new Date(file.lastModified ?? 0),\n mtimeMs: file.lastModified ?? 0,\n };\n } catch (error) {\n if (!isNotFoundOrTypeMismatch(error)) throw error;\n }\n\n try {\n await parent.getDirectoryHandle(name, { create: false });\n return createDirectoryStat();\n } catch (error) {\n if (!isNotFoundOrTypeMismatch(error)) throw error;\n throw error;\n }\n },\n\n async writeFile(path: string, data: Buffer | string): Promise<void> {\n const { parentSegments, name } = splitParent(path);\n const parent = await walkDirectory(root, parentSegments, false);\n const fileHandle = await parent.getFileHandle(name, { create: true });\n const writable = await fileHandle.createWritable();\n await writable.write(toWritableData(data));\n await writable.close();\n },\n\n async appendFile(path: string, data: Buffer | string): Promise<void> {\n const { parentSegments, name } = splitParent(path);\n const parent = await walkDirectory(root, parentSegments, false);\n const fileHandle = await parent.getFileHandle(name, { create: true });\n const file = await fileHandle.getFile();\n const writable = await fileHandle.createWritable({ keepExistingData: true });\n await writable.write({\n type: \"write\",\n position: file.size,\n data: toWritableData(data),\n });\n await writable.close();\n },\n\n async mkdir(path: string, opts?: { recursive?: boolean }): Promise<void> {\n const segments = getPathSegments(path);\n if (segments.length === 0) {\n return;\n }\n\n if (opts?.recursive) {\n await walkDirectory(root, segments, true);\n return;\n }\n\n const parent = await walkDirectory(root, segments.slice(0, -1), false);\n const name = segments[segments.length - 1]!;\n const exists = await entryExists(parent, name);\n if (exists) {\n throw new Error(`EEXIST: file already exists, mkdir '${normalizeWebPath(path)}'`);\n }\n await parent.getDirectoryHandle(name, { create: true });\n },\n\n async rm(path: string, opts?: { recursive?: boolean; force?: boolean }): Promise<void> {\n const segments = getPathSegments(path);\n if (segments.length === 0) {\n throw new Error(\"EPERM: operation not permitted, rm '/'\");\n }\n\n const parent = await walkDirectory(root, segments.slice(0, -1), false);\n const name = segments[segments.length - 1]!;\n try {\n await parent.removeEntry(name, { recursive: opts?.recursive });\n } catch (error) {\n if (opts?.force && isNotFoundError(error)) {\n return;\n }\n throw error;\n }\n },\n },\n streams: {\n createReadStream(path: string): AsyncIterable<Uint8Array> {\n return {\n async *[Symbol.asyncIterator]() {\n const { parentSegments, name } = splitParent(path);\n const parent = await walkDirectory(root, parentSegments, false);\n const fileHandle = await parent.getFileHandle(name, { create: false });\n const file = await fileHandle.getFile();\n for await (const chunk of streamToAsyncIterable(file.stream())) {\n yield chunk;\n }\n },\n };\n },\n async createWriteStream(path: string, opts?: { append?: boolean }): Promise<VirtualFSWritable> {\n const { parentSegments, name } = splitParent(path);\n const parent = await walkDirectory(root, parentSegments, false);\n const fileHandle = await parent.getFileHandle(name, { create: true });\n const existingFile = opts?.append ? await fileHandle.getFile() : null;\n const writable = await fileHandle.createWritable({ keepExistingData: !!opts?.append });\n let position = opts?.append ? existingFile?.size ?? 0 : 0;\n let closed = false;\n\n return {\n async write(chunk: Uint8Array): Promise<void> {\n if (closed) {\n throw new Error(\"stream is closed\");\n }\n const bytes = new Uint8Array(chunk.byteLength);\n bytes.set(chunk, 0);\n await writable.write({\n type: \"write\",\n position,\n data: bytes,\n });\n position += bytes.byteLength;\n },\n async close(): Promise<void> {\n if (closed) return;\n closed = true;\n await writable.close();\n },\n async abort(_reason?: unknown): Promise<void> {\n if (closed) return;\n closed = true;\n await writable.abort?.();\n },\n };\n },\n },\n };\n}\n\nexport class WebFileSystem extends FileSystem {\n constructor(root: FileSystemDirectoryHandle, permissions?: PermissionRules) {\n super(\"/\", permissions, createWebUnderlyingFS(root));\n }\n}\n\nfunction createDirectoryStat() {\n return {\n isFile: () => false,\n isDirectory: () => true,\n size: 0,\n mtime: DIRECTORY_MTIME,\n mtimeMs: DIRECTORY_MTIME.getTime(),\n };\n}\n\nfunction normalizeWebPath(path: string): string {\n const normalized = path.replace(/\\\\/g, \"/\");\n const rawSegments = (normalized.startsWith(\"/\") ? normalized : `/${normalized}`)\n .split(\"/\")\n .filter(Boolean);\n\n const segments: string[] = [];\n for (const segment of rawSegments) {\n if (segment === \".\") continue;\n if (segment === \"..\") {\n segments.pop();\n continue;\n }\n segments.push(segment);\n }\n\n return `/${segments.join(\"/\")}`;\n}\n\nfunction getPathSegments(path: string): string[] {\n const normalized = normalizeWebPath(path);\n return normalized.split(\"/\").filter(Boolean);\n}\n\nfunction splitParent(path: string): { parentSegments: string[]; name: string } {\n const segments = getPathSegments(path);\n if (segments.length === 0) {\n throw new Error(`Invalid file path: \"${path}\"`);\n }\n return {\n parentSegments: segments.slice(0, -1),\n name: segments[segments.length - 1]!,\n };\n}\n\nasync function walkDirectory(\n root: FileSystemDirectoryHandle,\n segments: string[],\n create: boolean\n): Promise<FileSystemDirectoryHandle> {\n let current = root;\n for (const segment of segments) {\n current = await current.getDirectoryHandle(segment, { create });\n }\n return current;\n}\n\nasync function entryExists(dir: FileSystemDirectoryHandle, name: string): Promise<boolean> {\n try {\n await dir.getFileHandle(name, { create: false });\n return true;\n } catch (error) {\n if (isTypeMismatchError(error)) return true;\n if (!isNotFoundError(error)) throw error;\n }\n\n try {\n await dir.getDirectoryHandle(name, { create: false });\n return true;\n } catch (error) {\n if (isTypeMismatchError(error)) return true;\n if (!isNotFoundError(error)) throw error;\n return false;\n }\n}\n\nasync function* streamToAsyncIterable(\n stream: ReadableStream<Uint8Array>,\n): AsyncIterable<Uint8Array> {\n const reader = stream.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n return;\n }\n if (value) {\n yield value;\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n\nfunction isNotFoundOrTypeMismatch(error: unknown): boolean {\n return isNotFoundError(error) || isTypeMismatchError(error);\n}\n\nfunction isNotFoundError(error: unknown): boolean {\n return getErrorName(error) === \"NotFoundError\";\n}\n\nfunction isTypeMismatchError(error: unknown): boolean {\n return getErrorName(error) === \"TypeMismatchError\";\n}\n\nfunction getErrorName(error: unknown): string | undefined {\n if (!error || typeof error !== \"object\") return undefined;\n const named = error as { name?: unknown };\n return typeof named.name === \"string\" ? named.name : undefined;\n}\n\nfunction toWritableData(data: Buffer | string): string | ArrayBuffer {\n if (typeof data === \"string\") {\n return data;\n }\n const out = new Uint8Array(data.length);\n out.set(data);\n return out.buffer;\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "87CE1021E696ED8364756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"// Main class exports\nexport { ShellDSL, createShellDSL, type Program } from \"./shell-dsl.cjs\";\nexport { ShellPromise, type ShellPromiseOptions } from \"./shell-promise.cjs\";\n\n// Types\nexport type {\n VirtualFS,\n FileStat,\n Command,\n CommandContext,\n Stdin,\n Stdout,\n Stderr,\n OutputCollector,\n ExecResult,\n ShellConfig,\n RawValue,\n} from \"./types.cjs\";\nexport { isRawValue } from \"./types.cjs\";\n\n// Errors\nexport { ShellError, LexError, ParseError } from \"./errors.cjs\";\n\n// Lexer\nexport { Lexer, lex, tokenToString } from \"./lexer/index.cjs\";\nexport type { Token, RedirectMode } from \"./lexer/index.cjs\";\n\n// Parser\nexport { Parser, parse } from \"./parser/index.cjs\";\nexport type {\n ASTNode,\n Redirect,\n CommandNode,\n PipelineNode,\n AndNode,\n OrNode,\n SequenceNode,\n LiteralNode,\n VariableNode,\n SubstitutionNode,\n GlobNode,\n ConcatNode,\n IfNode,\n ForNode,\n WhileNode,\n UntilNode,\n CaseNode,\n CaseClause,\n ArithmeticNode,\n} from \"./parser/index.cjs\";\nexport {\n isCommandNode,\n isPipelineNode,\n isAndNode,\n isOrNode,\n isSequenceNode,\n isLiteralNode,\n isVariableNode,\n isSubstitutionNode,\n isGlobNode,\n isConcatNode,\n isIfNode,\n isForNode,\n isWhileNode,\n isUntilNode,\n isCaseNode,\n isArithmeticNode,\n} from \"./parser/index.cjs\";\n\n// Interpreter\nexport { Interpreter, type InterpreterOptions, BreakException, ContinueException } from \"./interpreter/index.cjs\";\n\n// Filesystem\nexport { createVirtualFS } from \"./fs/index.cjs\";\nexport {\n FileSystem,\n ReadOnlyFileSystem,\n WebFileSystem,\n createWebUnderlyingFS,\n type PathOps,\n type Permission,\n type PermissionRules,\n type UnderlyingFS,\n} from \"./fs/index.cjs\";\n\n// I/O\nexport { createStdin, StdinImpl } from \"./io/index.cjs\";\nexport { createStdout, createStderr, createPipe, OutputCollectorImpl, PipeBuffer } from \"./io/index.cjs\";\n\n// Utilities\nexport { escape, escapeForInterpolation, globVirtualFS } from \"./utils/index.cjs\";\nexport type { GlobVirtualFS, GlobOptions } from \"./utils/index.cjs\";\n\n// Version Control\nexport { VersionControlSystem } from \"./vcs/index.cjs\";\nexport type {\n VCSConfig,\n VCSAttributeRule,\n VCSResolvedAttributes,\n VCSDiffMode,\n Revision,\n DiffEntry,\n TreeManifest,\n TreeEntry,\n FileEntry,\n DirectoryEntry,\n CommitOptions,\n CheckoutOptions,\n LogOptions,\n LogEntry,\n BranchInfo,\n} from \"./vcs/index.cjs\";\n"
|
|
5
|
+
"// Main class exports\nexport { ShellDSL, createShellDSL, type Program } from \"./shell-dsl.cjs\";\nexport { ShellPromise, type ShellPromiseOptions } from \"./shell-promise.cjs\";\n\n// Types\nexport type {\n VirtualFS,\n VirtualFSWritable,\n FileStat,\n Command,\n CommandContext,\n Stdin,\n Stdout,\n Stderr,\n OutputCollector,\n ExecResult,\n ShellConfig,\n RawValue,\n} from \"./types.cjs\";\nexport { isRawValue } from \"./types.cjs\";\n\n// Errors\nexport { ShellError, LexError, ParseError } from \"./errors.cjs\";\n\n// Lexer\nexport { Lexer, lex, tokenToString } from \"./lexer/index.cjs\";\nexport type { Token, RedirectMode } from \"./lexer/index.cjs\";\n\n// Parser\nexport { Parser, parse } from \"./parser/index.cjs\";\nexport type {\n ASTNode,\n Redirect,\n CommandNode,\n PipelineNode,\n AndNode,\n OrNode,\n SequenceNode,\n LiteralNode,\n VariableNode,\n SubstitutionNode,\n GlobNode,\n ConcatNode,\n IfNode,\n ForNode,\n WhileNode,\n UntilNode,\n CaseNode,\n CaseClause,\n ArithmeticNode,\n} from \"./parser/index.cjs\";\nexport {\n isCommandNode,\n isPipelineNode,\n isAndNode,\n isOrNode,\n isSequenceNode,\n isLiteralNode,\n isVariableNode,\n isSubstitutionNode,\n isGlobNode,\n isConcatNode,\n isIfNode,\n isForNode,\n isWhileNode,\n isUntilNode,\n isCaseNode,\n isArithmeticNode,\n} from \"./parser/index.cjs\";\n\n// Interpreter\nexport { Interpreter, type InterpreterOptions, BreakException, ContinueException } from \"./interpreter/index.cjs\";\n\n// Filesystem\nexport { createVirtualFS } from \"./fs/index.cjs\";\nexport {\n FileSystem,\n ReadOnlyFileSystem,\n WebFileSystem,\n createWebUnderlyingFS,\n type PathOps,\n type Permission,\n type PermissionRules,\n type UnderlyingFS,\n} from \"./fs/index.cjs\";\n\n// I/O\nexport { createStdin, StdinImpl } from \"./io/index.cjs\";\nexport { createStdout, createStderr, createPipe, OutputCollectorImpl, PipeBuffer } from \"./io/index.cjs\";\n\n// Utilities\nexport { escape, escapeForInterpolation, globVirtualFS } from \"./utils/index.cjs\";\nexport type { GlobVirtualFS, GlobOptions } from \"./utils/index.cjs\";\n\n// Version Control\nexport { VersionControlSystem } from \"./vcs/index.cjs\";\nexport type {\n VCSConfig,\n VCSAttributeRule,\n VCSResolvedAttributes,\n VCSDiffMode,\n VCSPatchSuppressionReason,\n Revision,\n DiffEntry,\n TreeManifest,\n TreeEntry,\n FileEntry,\n DirectoryEntry,\n VCSIndexEntry,\n VCSIndexFile,\n CommitOptions,\n CheckoutOptions,\n LogOptions,\n LogEntry,\n BranchInfo,\n} from \"./vcs/index.cjs\";\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACuD,IAAvD;AACuD,IAAvD;
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACuD,IAAvD;AACuD,IAAvD;AAiB2B,IAA3B;AAGiD,IAAjD;AAG0C,IAA1C;AAI8B,IAA9B;AAuCO,IAjBP;AAoBwF,IAAxF;AAGgC,IAAhC;AAUO,IATP;AAYuC,IAAvC;AACwF,IAAxF;AAG8D,IAA9D;AAIqC,IAArC;",
|
|
8
8
|
"debugId": "27F0973A44539CA064756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/types.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"// Virtual Filesystem Interface\nexport interface VirtualFS {\n readFile(path: string): Promise<Buffer>;\n readFile(path: string, encoding: BufferEncoding): Promise<string>;\n readdir(path: string): Promise<string[]>;\n stat(path: string): Promise<FileStat>;\n exists(path: string): Promise<boolean>;\n\n writeFile(path: string, data: Buffer | string): Promise<void>;\n appendFile(path: string, data: Buffer | string): Promise<void>;\n mkdir(path: string, opts?: { recursive?: boolean }): Promise<void>;\n\n rm(path: string, opts?: { recursive?: boolean; force?: boolean }): Promise<void>;\n\n resolve(...paths: string[]): string;\n dirname(path: string): string;\n basename(path: string): string;\n glob(pattern: string, opts?: { cwd?: string }): Promise<string[]>;\n}\n\nexport interface FileStat {\n isFile(): boolean;\n isDirectory(): boolean;\n size: number;\n mtime: Date;\n}\n\n// Command Interfaces\nexport type Command = (ctx: CommandContext) => Promise<number>;\n\nexport interface CommandContext {\n args: string[];\n stdin: Stdin;\n stdout: Stdout;\n stderr: Stderr;\n fs: VirtualFS;\n cwd: string;\n env: Record<string, string>;\n setCwd: (path: string) => void;\n exec?: (name: string, args: string[]) => Promise<ExecResult>;\n}\n\nexport interface Stdin {\n stream(): AsyncIterable<Uint8Array>;\n buffer(): Promise<Buffer>;\n text(): Promise<string>;\n lines(): AsyncIterable<string>;\n}\n\nexport interface Stdout {\n write(chunk: Uint8Array): Promise<void>;\n writeText(str: string): Promise<void>;\n isTTY: boolean;\n}\n\nexport interface Stderr {\n write(chunk: Uint8Array): Promise<void>;\n writeText(str: string): Promise<void>;\n isTTY: boolean;\n}\n\nexport interface OutputCollector extends Stdout {\n close(): void;\n collect(): Promise<Buffer>;\n getReadableStream(): AsyncIterable<Uint8Array>;\n}\n\n// Execution Result\nexport interface ExecResult {\n stdout: Buffer;\n stderr: Buffer;\n exitCode: number;\n}\n\n// Shell Configuration\nexport interface ShellConfig {\n fs: VirtualFS;\n cwd: string;\n env: Record<string, string>;\n commands: Record<string, Command>;\n isTTY?: boolean;\n}\n\n// Raw escape hatch type\nexport interface RawValue {\n raw: string;\n}\n\nexport function isRawValue(value: unknown): value is RawValue {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"raw\" in value &&\n typeof (value as RawValue).raw === \"string\"\n );\n}\n\n// JS Object Redirection types\nexport type RedirectObject = Buffer | Blob | Response | string;\n\nexport interface RedirectObjectMap {\n [marker: string]: RedirectObject;\n}\n\nexport function isRedirectObject(value: unknown): value is RedirectObject {\n return (\n Buffer.isBuffer(value) ||\n value instanceof Blob ||\n value instanceof Response ||\n typeof value === \"string\"\n );\n}\n"
|
|
5
|
+
"// Virtual Filesystem Interface\nexport interface VirtualFSWritable {\n write(chunk: Uint8Array): Promise<void>;\n close(): Promise<void>;\n abort?(reason?: unknown): Promise<void>;\n}\n\nexport interface VirtualFS {\n readFile(path: string): Promise<Buffer>;\n readFile(path: string, encoding: BufferEncoding): Promise<string>;\n readStream(path: string): AsyncIterable<Uint8Array>;\n readdir(path: string): Promise<string[]>;\n stat(path: string): Promise<FileStat>;\n exists(path: string): Promise<boolean>;\n\n writeFile(path: string, data: Buffer | string): Promise<void>;\n appendFile(path: string, data: Buffer | string): Promise<void>;\n writeStream(path: string, opts?: { append?: boolean }): Promise<VirtualFSWritable>;\n mkdir(path: string, opts?: { recursive?: boolean }): Promise<void>;\n\n rm(path: string, opts?: { recursive?: boolean; force?: boolean }): Promise<void>;\n\n resolve(...paths: string[]): string;\n dirname(path: string): string;\n basename(path: string): string;\n glob(pattern: string, opts?: { cwd?: string }): Promise<string[]>;\n}\n\nexport interface FileStat {\n isFile(): boolean;\n isDirectory(): boolean;\n size: number;\n mtime: Date;\n mtimeMs: number;\n}\n\n// Command Interfaces\nexport type Command = (ctx: CommandContext) => Promise<number>;\n\nexport interface CommandContext {\n args: string[];\n stdin: Stdin;\n stdout: Stdout;\n stderr: Stderr;\n fs: VirtualFS;\n cwd: string;\n env: Record<string, string>;\n setCwd: (path: string) => void;\n exec?: (name: string, args: string[]) => Promise<ExecResult>;\n}\n\nexport interface Stdin {\n stream(): AsyncIterable<Uint8Array>;\n buffer(): Promise<Buffer>;\n text(): Promise<string>;\n lines(): AsyncIterable<string>;\n}\n\nexport interface Stdout {\n write(chunk: Uint8Array): Promise<void>;\n writeText(str: string): Promise<void>;\n isTTY: boolean;\n}\n\nexport interface Stderr {\n write(chunk: Uint8Array): Promise<void>;\n writeText(str: string): Promise<void>;\n isTTY: boolean;\n}\n\nexport interface OutputCollector extends Stdout {\n close(): void;\n collect(): Promise<Buffer>;\n getReadableStream(): AsyncIterable<Uint8Array>;\n}\n\n// Execution Result\nexport interface ExecResult {\n stdout: Buffer;\n stderr: Buffer;\n exitCode: number;\n}\n\n// Shell Configuration\nexport interface ShellConfig {\n fs: VirtualFS;\n cwd: string;\n env: Record<string, string>;\n commands: Record<string, Command>;\n isTTY?: boolean;\n}\n\n// Raw escape hatch type\nexport interface RawValue {\n raw: string;\n}\n\nexport function isRawValue(value: unknown): value is RawValue {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"raw\" in value &&\n typeof (value as RawValue).raw === \"string\"\n );\n}\n\n// JS Object Redirection types\nexport type RedirectObject = Buffer | Blob | Response | string;\n\nexport interface RedirectObjectMap {\n [marker: string]: RedirectObject;\n}\n\nexport function isRedirectObject(value: unknown): value is RedirectObject {\n return (\n Buffer.isBuffer(value) ||\n value instanceof Blob ||\n value instanceof Response ||\n typeof value === \"string\"\n );\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiGO,SAAS,UAAU,CAAC,OAAmC;AAAA,EAC5D,OACE,OAAO,UAAU,YACjB,UAAU,QACV,SAAS,SACT,OAAQ,MAAmB,QAAQ;AAAA;AAWhC,SAAS,gBAAgB,CAAC,OAAyC;AAAA,EACxE,OACE,OAAO,SAAS,KAAK,KACrB,iBAAiB,QACjB,iBAAiB,YACjB,OAAO,UAAU;AAAA;",
|
|
8
8
|
"debugId": "324A9AF65A2908F664756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
function __accessProp(key) {
|
|
6
|
+
return this[key];
|
|
7
|
+
}
|
|
8
|
+
var __toCommonJS = (from) => {
|
|
9
|
+
var entry = (__moduleCache ??= new WeakMap).get(from), desc;
|
|
10
|
+
if (entry)
|
|
11
|
+
return entry;
|
|
12
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (var key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(entry, key))
|
|
16
|
+
__defProp(entry, key, {
|
|
17
|
+
get: __accessProp.bind(from, key),
|
|
18
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
__moduleCache.set(from, entry);
|
|
22
|
+
return entry;
|
|
23
|
+
};
|
|
24
|
+
var __moduleCache;
|
|
25
|
+
var __returnValue = (v) => v;
|
|
26
|
+
function __exportSetter(name, newValue) {
|
|
27
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
28
|
+
}
|
|
29
|
+
var __export = (target, all) => {
|
|
30
|
+
for (var name in all)
|
|
31
|
+
__defProp(target, name, {
|
|
32
|
+
get: all[name],
|
|
33
|
+
enumerable: true,
|
|
34
|
+
configurable: true,
|
|
35
|
+
set: __exportSetter.bind(all, name)
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// src/vcs/content.ts
|
|
40
|
+
var exports_content = {};
|
|
41
|
+
__export(exports_content, {
|
|
42
|
+
readStreamSample: () => readStreamSample,
|
|
43
|
+
hashSample: () => hashSample,
|
|
44
|
+
detectBinaryFromSample: () => detectBinaryFromSample,
|
|
45
|
+
appendSample: () => appendSample,
|
|
46
|
+
MAX_PATCH_BYTES: () => MAX_PATCH_BYTES,
|
|
47
|
+
BINARY_SAMPLE_BYTES: () => BINARY_SAMPLE_BYTES
|
|
48
|
+
});
|
|
49
|
+
module.exports = __toCommonJS(exports_content);
|
|
50
|
+
var import_sha2 = require("@noble/hashes/sha2.js");
|
|
51
|
+
var BINARY_SAMPLE_BYTES = 64 * 1024;
|
|
52
|
+
var MAX_PATCH_BYTES = 1024 * 1024;
|
|
53
|
+
var textDecoder = new TextDecoder("utf-8", { fatal: true });
|
|
54
|
+
var ALLOWED_CONTROL_BYTES = new Set([8, 9, 10, 12, 13]);
|
|
55
|
+
function detectBinaryFromSample(sample) {
|
|
56
|
+
if (sample.length === 0) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
let controlBytes = 0;
|
|
60
|
+
for (const byte of sample) {
|
|
61
|
+
if (byte === 0) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
if (byte < 32 && !ALLOWED_CONTROL_BYTES.has(byte)) {
|
|
65
|
+
controlBytes++;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
textDecoder.decode(sample);
|
|
70
|
+
} catch {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
return controlBytes / sample.length > 0.2;
|
|
74
|
+
}
|
|
75
|
+
function appendSample(sample, chunk, limit = BINARY_SAMPLE_BYTES) {
|
|
76
|
+
if (sample.length >= limit || chunk.length === 0) {
|
|
77
|
+
return sample;
|
|
78
|
+
}
|
|
79
|
+
const nextLength = Math.min(limit, sample.length + chunk.length);
|
|
80
|
+
const next = new Uint8Array(nextLength);
|
|
81
|
+
next.set(sample, 0);
|
|
82
|
+
next.set(chunk.subarray(0, nextLength - sample.length), sample.length);
|
|
83
|
+
return next;
|
|
84
|
+
}
|
|
85
|
+
async function readStreamSample(source, limit = BINARY_SAMPLE_BYTES) {
|
|
86
|
+
let sample = new Uint8Array;
|
|
87
|
+
for await (const chunk of source) {
|
|
88
|
+
sample = appendSample(sample, chunk, limit);
|
|
89
|
+
if (sample.length >= limit) {
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return sample;
|
|
94
|
+
}
|
|
95
|
+
function hashSample(sample) {
|
|
96
|
+
return toHex(import_sha2.sha256(sample));
|
|
97
|
+
}
|
|
98
|
+
function toHex(bytes) {
|
|
99
|
+
let out = "";
|
|
100
|
+
for (const byte of bytes) {
|
|
101
|
+
out += byte.toString(16).padStart(2, "0");
|
|
102
|
+
}
|
|
103
|
+
return out;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
//# debugId=F85446D2DF34909764756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/vcs/content.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { sha256 } from \"@noble/hashes/sha2.js\";\n\nexport const BINARY_SAMPLE_BYTES = 64 * 1024;\nexport const MAX_PATCH_BYTES = 1024 * 1024;\n\nconst textDecoder = new TextDecoder(\"utf-8\", { fatal: true });\nconst ALLOWED_CONTROL_BYTES = new Set([0x08, 0x09, 0x0a, 0x0c, 0x0d]);\n\nexport function detectBinaryFromSample(sample: Uint8Array<ArrayBufferLike>): boolean {\n if (sample.length === 0) {\n return false;\n }\n\n let controlBytes = 0;\n\n for (const byte of sample) {\n if (byte === 0x00) {\n return true;\n }\n if (byte < 0x20 && !ALLOWED_CONTROL_BYTES.has(byte)) {\n controlBytes++;\n }\n }\n\n try {\n textDecoder.decode(sample);\n } catch {\n return true;\n }\n\n return controlBytes / sample.length > 0.2;\n}\n\nexport function appendSample(\n sample: Uint8Array<ArrayBufferLike>,\n chunk: Uint8Array<ArrayBufferLike>,\n limit: number = BINARY_SAMPLE_BYTES,\n): Uint8Array<ArrayBufferLike> {\n if (sample.length >= limit || chunk.length === 0) {\n return sample;\n }\n\n const nextLength = Math.min(limit, sample.length + chunk.length);\n const next = new Uint8Array(nextLength);\n next.set(sample, 0);\n next.set(chunk.subarray(0, nextLength - sample.length), sample.length);\n return next;\n}\n\nexport async function readStreamSample(\n source: AsyncIterable<Uint8Array>,\n limit: number = BINARY_SAMPLE_BYTES,\n): Promise<Uint8Array<ArrayBufferLike>> {\n let sample: Uint8Array<ArrayBufferLike> = new Uint8Array();\n for await (const chunk of source) {\n sample = appendSample(sample, chunk, limit);\n if (sample.length >= limit) {\n break;\n }\n }\n return sample;\n}\n\nexport function hashSample(sample: Uint8Array<ArrayBufferLike>): string {\n return toHex(sha256(sample));\n}\n\nfunction toHex(bytes: Uint8Array): string {\n let out = \"\";\n for (const byte of bytes) {\n out += byte.toString(16).padStart(2, \"0\");\n }\n return out;\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAuB,IAAvB;AAEO,IAAM,sBAAsB,KAAK;AACjC,IAAM,kBAAkB,OAAO;AAEtC,IAAM,cAAc,IAAI,YAAY,SAAS,EAAE,OAAO,KAAK,CAAC;AAC5D,IAAM,wBAAwB,IAAI,IAAI,CAAC,GAAM,GAAM,IAAM,IAAM,EAAI,CAAC;AAE7D,SAAS,sBAAsB,CAAC,QAA8C;AAAA,EACnF,IAAI,OAAO,WAAW,GAAG;AAAA,IACvB,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,eAAe;AAAA,EAEnB,WAAW,QAAQ,QAAQ;AAAA,IACzB,IAAI,SAAS,GAAM;AAAA,MACjB,OAAO;AAAA,IACT;AAAA,IACA,IAAI,OAAO,MAAQ,CAAC,sBAAsB,IAAI,IAAI,GAAG;AAAA,MACnD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,IAAI;AAAA,IACF,YAAY,OAAO,MAAM;AAAA,IACzB,MAAM;AAAA,IACN,OAAO;AAAA;AAAA,EAGT,OAAO,eAAe,OAAO,SAAS;AAAA;AAGjC,SAAS,YAAY,CAC1B,QACA,OACA,QAAgB,qBACa;AAAA,EAC7B,IAAI,OAAO,UAAU,SAAS,MAAM,WAAW,GAAG;AAAA,IAChD,OAAO;AAAA,EACT;AAAA,EAEA,MAAM,aAAa,KAAK,IAAI,OAAO,OAAO,SAAS,MAAM,MAAM;AAAA,EAC/D,MAAM,OAAO,IAAI,WAAW,UAAU;AAAA,EACtC,KAAK,IAAI,QAAQ,CAAC;AAAA,EAClB,KAAK,IAAI,MAAM,SAAS,GAAG,aAAa,OAAO,MAAM,GAAG,OAAO,MAAM;AAAA,EACrE,OAAO;AAAA;AAGT,eAAsB,gBAAgB,CACpC,QACA,QAAgB,qBACsB;AAAA,EACtC,IAAI,SAAsC,IAAI;AAAA,EAC9C,iBAAiB,SAAS,QAAQ;AAAA,IAChC,SAAS,aAAa,QAAQ,OAAO,KAAK;AAAA,IAC1C,IAAI,OAAO,UAAU,OAAO;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAAA,EACA,OAAO;AAAA;AAGF,SAAS,UAAU,CAAC,QAA6C;AAAA,EACtE,OAAO,MAAM,mBAAO,MAAM,CAAC;AAAA;AAG7B,SAAS,KAAK,CAAC,OAA2B;AAAA,EACxC,IAAI,MAAM;AAAA,EACV,WAAW,QAAQ,OAAO;AAAA,IACxB,OAAO,KAAK,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAAA,EAC1C;AAAA,EACA,OAAO;AAAA;",
|
|
8
|
+
"debugId": "F85446D2DF34909764756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -39,63 +39,107 @@ var __export = (target, all) => {
|
|
|
39
39
|
// src/vcs/diff.ts
|
|
40
40
|
var exports_diff = {};
|
|
41
41
|
__export(exports_diff, {
|
|
42
|
-
diffWorkingTree: () => diffWorkingTree,
|
|
43
42
|
diffManifests: () => diffManifests
|
|
44
43
|
});
|
|
45
44
|
module.exports = __toCommonJS(exports_diff);
|
|
45
|
+
var import_content = require("./content.cjs");
|
|
46
46
|
var import_rules = require("./rules.cjs");
|
|
47
|
-
var
|
|
48
|
-
function diffManifests(before, after,
|
|
47
|
+
var import_text_diff = require("./text-diff.cjs");
|
|
48
|
+
async function diffManifests(before, after, options) {
|
|
49
49
|
const entries = [];
|
|
50
50
|
const allPaths = new Set([...Object.keys(before), ...Object.keys(after)]);
|
|
51
|
-
for (const path of allPaths) {
|
|
51
|
+
for (const path of [...allPaths].sort((a, b) => a.localeCompare(b))) {
|
|
52
52
|
const prev = before[path];
|
|
53
53
|
const curr = after[path];
|
|
54
54
|
if (!prev && curr) {
|
|
55
|
-
entries.push(createDiffEntry("add", path, curr, undefined,
|
|
55
|
+
entries.push(await createDiffEntry("add", path, curr, undefined, options));
|
|
56
56
|
} else if (prev && !curr) {
|
|
57
|
-
entries.push(createDiffEntry("delete", path, undefined, prev,
|
|
57
|
+
entries.push(await createDiffEntry("delete", path, undefined, prev, options));
|
|
58
58
|
} else if (prev && curr && !entriesEqual(prev, curr)) {
|
|
59
|
-
entries.push(createDiffEntry("modify", path, curr, prev,
|
|
59
|
+
entries.push(await createDiffEntry("modify", path, curr, prev, options));
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
-
return entries
|
|
62
|
+
return entries;
|
|
63
63
|
}
|
|
64
|
-
async function
|
|
65
|
-
const
|
|
66
|
-
rules,
|
|
67
|
-
trackedPaths: Object.keys(manifest)
|
|
68
|
-
});
|
|
69
|
-
return diffManifests(manifest, workingManifest, rules);
|
|
70
|
-
}
|
|
71
|
-
function createDiffEntry(type, path, current, previous, rules) {
|
|
64
|
+
async function createDiffEntry(type, path, current, previous, options) {
|
|
65
|
+
const rules = options.rules ?? new import_rules.VCSRules;
|
|
72
66
|
const attributes = rules.resolveAttributes(path);
|
|
73
67
|
const entryKind = getEntryKind(current ?? previous);
|
|
74
68
|
const previousEntryKind = previous ? getEntryKind(previous) : undefined;
|
|
69
|
+
const currentFile = isFileEntry(current) ? current : undefined;
|
|
70
|
+
const previousFile = isFileEntry(previous) ? previous : undefined;
|
|
71
|
+
const binary = await resolveBinary(path, currentFile, previousFile, attributes, options);
|
|
72
|
+
const diff = resolveDiffMode(attributes, binary);
|
|
75
73
|
const entry = {
|
|
76
74
|
type,
|
|
77
75
|
path,
|
|
78
|
-
binary
|
|
79
|
-
diff
|
|
76
|
+
binary,
|
|
77
|
+
diff,
|
|
80
78
|
entryKind,
|
|
81
|
-
previousEntryKind
|
|
79
|
+
previousEntryKind,
|
|
80
|
+
blobId: currentFile?.blobId,
|
|
81
|
+
previousBlobId: previousFile?.blobId
|
|
82
82
|
};
|
|
83
|
-
if (
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
83
|
+
if (!currentFile && !previousFile) {
|
|
84
|
+
return entry;
|
|
85
|
+
}
|
|
86
|
+
if (diff === "none") {
|
|
87
|
+
entry.patchSuppressedReason = "none";
|
|
88
|
+
return entry;
|
|
90
89
|
}
|
|
90
|
+
if (diff === "binary") {
|
|
91
|
+
entry.patchSuppressedReason = "binary";
|
|
92
|
+
return entry;
|
|
93
|
+
}
|
|
94
|
+
const largestSize = Math.max(currentFile?.size ?? 0, previousFile?.size ?? 0);
|
|
95
|
+
if (largestSize > import_content.MAX_PATCH_BYTES) {
|
|
96
|
+
entry.patchSuppressedReason = "too-large";
|
|
97
|
+
return entry;
|
|
98
|
+
}
|
|
99
|
+
const previousText = previousFile ? await options.objectStore.readBlobText(previousFile.blobId) : "";
|
|
100
|
+
const currentText = currentFile ? await options.objectStore.readBlobText(currentFile.blobId) : "";
|
|
101
|
+
entry.patch = import_text_diff.createUnifiedPatch(path, previousText, currentText);
|
|
91
102
|
return entry;
|
|
92
103
|
}
|
|
104
|
+
async function resolveBinary(path, current, previous, attributes, options) {
|
|
105
|
+
if (attributes.diff === "text") {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
if (attributes.diff === "binary" || attributes.binary === true) {
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
const currentBinary = await resolveEntryBinary(path, current, options.afterIndex, options.objectStore);
|
|
112
|
+
const previousBinary = await resolveEntryBinary(path, previous, options.beforeIndex, options.objectStore);
|
|
113
|
+
return currentBinary || previousBinary;
|
|
114
|
+
}
|
|
115
|
+
async function resolveEntryBinary(path, entry, indexEntries, objectStore) {
|
|
116
|
+
if (!entry) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
const cached = indexEntries?.[path];
|
|
120
|
+
if (cached?.blobId === entry.blobId) {
|
|
121
|
+
return cached.binary;
|
|
122
|
+
}
|
|
123
|
+
return objectStore.isBinaryBlob(entry.blobId);
|
|
124
|
+
}
|
|
125
|
+
function resolveDiffMode(attributes, binary) {
|
|
126
|
+
if (attributes.diff === "none") {
|
|
127
|
+
return "none";
|
|
128
|
+
}
|
|
129
|
+
if (attributes.diff === "text") {
|
|
130
|
+
return "text";
|
|
131
|
+
}
|
|
132
|
+
if (attributes.diff === "binary" || binary) {
|
|
133
|
+
return "binary";
|
|
134
|
+
}
|
|
135
|
+
return "text";
|
|
136
|
+
}
|
|
93
137
|
function entriesEqual(a, b) {
|
|
94
138
|
if (getEntryKind(a) !== getEntryKind(b))
|
|
95
139
|
return false;
|
|
96
140
|
if (!isFileEntry(a) || !isFileEntry(b))
|
|
97
141
|
return true;
|
|
98
|
-
return a.
|
|
142
|
+
return a.blobId === b.blobId && a.size === b.size;
|
|
99
143
|
}
|
|
100
144
|
function getEntryKind(entry) {
|
|
101
145
|
return entry?.kind === "directory" ? "directory" : "file";
|
|
@@ -104,4 +148,4 @@ function isFileEntry(entry) {
|
|
|
104
148
|
return !!entry && entry.kind !== "directory";
|
|
105
149
|
}
|
|
106
150
|
|
|
107
|
-
//# debugId=
|
|
151
|
+
//# debugId=07954E8C085717B664756E2164756E21
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/vcs/diff.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type {
|
|
5
|
+
"import type { TreeManifest, DiffEntry, TreeEntry, VCSIndexEntry } from \"./types.cjs\";\nimport { MAX_PATCH_BYTES } from \"./content.cjs\";\nimport { VCSObjectStore } from \"./objects.cjs\";\nimport { VCSRules } from \"./rules.cjs\";\nimport { createUnifiedPatch } from \"./text-diff.cjs\";\n\ninterface DiffOptions {\n rules?: VCSRules;\n objectStore: VCSObjectStore;\n beforeIndex?: Record<string, VCSIndexEntry>;\n afterIndex?: Record<string, VCSIndexEntry>;\n}\n\n/**\n * Compute diff entries between two tree manifests.\n */\nexport async function diffManifests(\n before: TreeManifest,\n after: TreeManifest,\n options: DiffOptions,\n): Promise<DiffEntry[]> {\n const entries: DiffEntry[] = [];\n const allPaths = new Set([...Object.keys(before), ...Object.keys(after)]);\n\n for (const path of [...allPaths].sort((a, b) => a.localeCompare(b))) {\n const prev = before[path];\n const curr = after[path];\n\n if (!prev && curr) {\n entries.push(await createDiffEntry(\"add\", path, curr, undefined, options));\n } else if (prev && !curr) {\n entries.push(await createDiffEntry(\"delete\", path, undefined, prev, options));\n } else if (prev && curr && !entriesEqual(prev, curr)) {\n entries.push(await createDiffEntry(\"modify\", path, curr, prev, options));\n }\n }\n\n return entries;\n}\n\nasync function createDiffEntry(\n type: DiffEntry[\"type\"],\n path: string,\n current: TreeEntry | undefined,\n previous: TreeEntry | undefined,\n options: DiffOptions,\n): Promise<DiffEntry> {\n const rules = options.rules ?? new VCSRules();\n const attributes = rules.resolveAttributes(path);\n const entryKind = getEntryKind(current ?? previous);\n const previousEntryKind = previous ? getEntryKind(previous) : undefined;\n const currentFile = isFileEntry(current) ? current : undefined;\n const previousFile = isFileEntry(previous) ? previous : undefined;\n const binary = await resolveBinary(path, currentFile, previousFile, attributes, options);\n const diff = resolveDiffMode(attributes, binary);\n const entry: DiffEntry = {\n type,\n path,\n binary,\n diff,\n entryKind,\n previousEntryKind,\n blobId: currentFile?.blobId,\n previousBlobId: previousFile?.blobId,\n };\n\n if (!currentFile && !previousFile) {\n return entry;\n }\n\n if (diff === \"none\") {\n entry.patchSuppressedReason = \"none\";\n return entry;\n }\n\n if (diff === \"binary\") {\n entry.patchSuppressedReason = \"binary\";\n return entry;\n }\n\n const largestSize = Math.max(currentFile?.size ?? 0, previousFile?.size ?? 0);\n if (largestSize > MAX_PATCH_BYTES) {\n entry.patchSuppressedReason = \"too-large\";\n return entry;\n }\n\n const previousText = previousFile\n ? await options.objectStore.readBlobText(previousFile.blobId)\n : \"\";\n const currentText = currentFile\n ? await options.objectStore.readBlobText(currentFile.blobId)\n : \"\";\n entry.patch = createUnifiedPatch(path, previousText, currentText);\n return entry;\n}\n\nasync function resolveBinary(\n path: string,\n current: Extract<TreeEntry, { kind?: \"file\" }> | undefined,\n previous: Extract<TreeEntry, { kind?: \"file\" }> | undefined,\n attributes: ReturnType<VCSRules[\"resolveAttributes\"]>,\n options: DiffOptions,\n): Promise<boolean> {\n if (attributes.diff === \"text\") {\n return false;\n }\n if (attributes.diff === \"binary\" || attributes.binary === true) {\n return true;\n }\n\n const currentBinary = await resolveEntryBinary(\n path,\n current,\n options.afterIndex,\n options.objectStore,\n );\n const previousBinary = await resolveEntryBinary(\n path,\n previous,\n options.beforeIndex,\n options.objectStore,\n );\n\n return currentBinary || previousBinary;\n}\n\nasync function resolveEntryBinary(\n path: string,\n entry: Extract<TreeEntry, { kind?: \"file\" }> | undefined,\n indexEntries: Record<string, VCSIndexEntry> | undefined,\n objectStore: VCSObjectStore,\n): Promise<boolean> {\n if (!entry) {\n return false;\n }\n const cached = indexEntries?.[path];\n if (cached?.blobId === entry.blobId) {\n return cached.binary;\n }\n return objectStore.isBinaryBlob(entry.blobId);\n}\n\nfunction resolveDiffMode(\n attributes: ReturnType<VCSRules[\"resolveAttributes\"]>,\n binary: boolean,\n): DiffEntry[\"diff\"] {\n if (attributes.diff === \"none\") {\n return \"none\";\n }\n if (attributes.diff === \"text\") {\n return \"text\";\n }\n if (attributes.diff === \"binary\" || binary) {\n return \"binary\";\n }\n return \"text\";\n}\n\nfunction entriesEqual(a: TreeEntry, b: TreeEntry): boolean {\n if (getEntryKind(a) !== getEntryKind(b)) return false;\n if (!isFileEntry(a) || !isFileEntry(b)) return true;\n return a.blobId === b.blobId && a.size === b.size;\n}\n\nfunction getEntryKind(entry: TreeEntry | undefined): \"file\" | \"directory\" {\n return entry?.kind === \"directory\" ? \"directory\" : \"file\";\n}\n\nfunction isFileEntry(entry: TreeEntry | undefined): entry is Extract<TreeEntry, { kind?: \"file\" }> {\n return !!entry && entry.kind !== \"directory\";\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "07954E8C085717B664756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/vcs/index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"export { VersionControlSystem } from \"./vcs.cjs\";\nexport type {\n VCSConfig,\n VCSAttributeRule,\n VCSResolvedAttributes,\n VCSDiffMode,\n Revision,\n DiffEntry,\n TreeManifest,\n TreeEntry,\n FileEntry,\n DirectoryEntry,\n CommitOptions,\n CheckoutOptions,\n LogOptions,\n LogEntry,\n BranchInfo,\n} from \"./types.cjs\";\n"
|
|
5
|
+
"export { VersionControlSystem } from \"./vcs.cjs\";\nexport type {\n VCSConfig,\n VCSAttributeRule,\n VCSResolvedAttributes,\n VCSDiffMode,\n VCSPatchSuppressionReason,\n Revision,\n DiffEntry,\n TreeManifest,\n TreeEntry,\n FileEntry,\n DirectoryEntry,\n VCSIndexEntry,\n VCSIndexFile,\n CommitOptions,\n CheckoutOptions,\n LogOptions,\n LogEntry,\n BranchInfo,\n} from \"./types.cjs\";\n"
|
|
6
6
|
],
|
|
7
7
|
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAqC,IAArC;",
|
|
8
8
|
"debugId": "882B2013CEEDB5D864756E2164756E21",
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
function __accessProp(key) {
|
|
6
|
+
return this[key];
|
|
7
|
+
}
|
|
8
|
+
var __toCommonJS = (from) => {
|
|
9
|
+
var entry = (__moduleCache ??= new WeakMap).get(from), desc;
|
|
10
|
+
if (entry)
|
|
11
|
+
return entry;
|
|
12
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (var key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(entry, key))
|
|
16
|
+
__defProp(entry, key, {
|
|
17
|
+
get: __accessProp.bind(from, key),
|
|
18
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
__moduleCache.set(from, entry);
|
|
22
|
+
return entry;
|
|
23
|
+
};
|
|
24
|
+
var __moduleCache;
|
|
25
|
+
var __returnValue = (v) => v;
|
|
26
|
+
function __exportSetter(name, newValue) {
|
|
27
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
28
|
+
}
|
|
29
|
+
var __export = (target, all) => {
|
|
30
|
+
for (var name in all)
|
|
31
|
+
__defProp(target, name, {
|
|
32
|
+
get: all[name],
|
|
33
|
+
enumerable: true,
|
|
34
|
+
configurable: true,
|
|
35
|
+
set: __exportSetter.bind(all, name)
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// src/vcs/objects.ts
|
|
40
|
+
var exports_objects = {};
|
|
41
|
+
__export(exports_objects, {
|
|
42
|
+
VCSObjectStore: () => VCSObjectStore
|
|
43
|
+
});
|
|
44
|
+
module.exports = __toCommonJS(exports_objects);
|
|
45
|
+
var import_sha2 = require("@noble/hashes/sha2.js");
|
|
46
|
+
var import_content = require("./content.cjs");
|
|
47
|
+
|
|
48
|
+
class VCSObjectStore {
|
|
49
|
+
fs;
|
|
50
|
+
basePath;
|
|
51
|
+
constructor(fs, basePath) {
|
|
52
|
+
this.fs = fs;
|
|
53
|
+
this.basePath = basePath;
|
|
54
|
+
}
|
|
55
|
+
async initialize() {
|
|
56
|
+
await this.fs.mkdir(this.path("objects", "blobs"), { recursive: true });
|
|
57
|
+
await this.fs.mkdir(this.path("tmp"), { recursive: true });
|
|
58
|
+
}
|
|
59
|
+
async hasBlob(blobId) {
|
|
60
|
+
return this.fs.exists(this.blobPath(blobId));
|
|
61
|
+
}
|
|
62
|
+
async store(source) {
|
|
63
|
+
const tempPath = this.path("tmp", `${Date.now()}-${Math.random().toString(36).slice(2)}.blob`);
|
|
64
|
+
const writer = await this.fs.writeStream(tempPath);
|
|
65
|
+
const hash = import_sha2.sha256.create();
|
|
66
|
+
let size = 0;
|
|
67
|
+
let sample = new Uint8Array;
|
|
68
|
+
try {
|
|
69
|
+
for await (const chunk of source) {
|
|
70
|
+
const bytes = chunk instanceof Uint8Array ? chunk : new Uint8Array(chunk);
|
|
71
|
+
hash.update(bytes);
|
|
72
|
+
size += bytes.byteLength;
|
|
73
|
+
sample = import_content.appendSample(sample, bytes);
|
|
74
|
+
await writer.write(bytes);
|
|
75
|
+
}
|
|
76
|
+
await writer.close();
|
|
77
|
+
const blobId = toHex(hash.digest());
|
|
78
|
+
const finalPath = this.blobPath(blobId);
|
|
79
|
+
await this.fs.mkdir(this.fs.dirname(finalPath), { recursive: true });
|
|
80
|
+
if (!await this.fs.exists(finalPath)) {
|
|
81
|
+
await copyStream(this.fs, tempPath, finalPath);
|
|
82
|
+
}
|
|
83
|
+
await this.fs.rm(tempPath, { force: true });
|
|
84
|
+
return {
|
|
85
|
+
blobId,
|
|
86
|
+
size,
|
|
87
|
+
binary: import_content.detectBinaryFromSample(sample),
|
|
88
|
+
sampleHash: import_content.hashSample(sample)
|
|
89
|
+
};
|
|
90
|
+
} catch (error) {
|
|
91
|
+
await writer.abort?.(error);
|
|
92
|
+
await this.fs.rm(tempPath, { force: true });
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async readBlob(blobId) {
|
|
97
|
+
return this.fs.readFile(this.blobPath(blobId));
|
|
98
|
+
}
|
|
99
|
+
async readBlobText(blobId) {
|
|
100
|
+
return this.fs.readFile(this.blobPath(blobId), "utf8");
|
|
101
|
+
}
|
|
102
|
+
readBlobStream(blobId) {
|
|
103
|
+
return this.fs.readStream(this.blobPath(blobId));
|
|
104
|
+
}
|
|
105
|
+
async isBinaryBlob(blobId) {
|
|
106
|
+
const sample = await import_content.readStreamSample(this.readBlobStream(blobId));
|
|
107
|
+
return import_content.detectBinaryFromSample(sample);
|
|
108
|
+
}
|
|
109
|
+
async deleteTempFiles() {
|
|
110
|
+
await this.fs.rm(this.path("tmp"), { recursive: true, force: true });
|
|
111
|
+
await this.fs.mkdir(this.path("tmp"), { recursive: true });
|
|
112
|
+
}
|
|
113
|
+
blobPath(blobId) {
|
|
114
|
+
return this.path("objects", "blobs", blobId.slice(0, 2), blobId.slice(2));
|
|
115
|
+
}
|
|
116
|
+
path(...segments) {
|
|
117
|
+
return this.fs.resolve(this.basePath, ...segments);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async function copyStream(fs, fromPath, toPath) {
|
|
121
|
+
const writer = await fs.writeStream(toPath);
|
|
122
|
+
try {
|
|
123
|
+
for await (const chunk of fs.readStream(fromPath)) {
|
|
124
|
+
await writer.write(chunk);
|
|
125
|
+
}
|
|
126
|
+
await writer.close();
|
|
127
|
+
} catch (error) {
|
|
128
|
+
await writer.abort?.(error);
|
|
129
|
+
await fs.rm(toPath, { force: true });
|
|
130
|
+
throw error;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function toHex(bytes) {
|
|
134
|
+
let out = "";
|
|
135
|
+
for (const byte of bytes) {
|
|
136
|
+
out += byte.toString(16).padStart(2, "0");
|
|
137
|
+
}
|
|
138
|
+
return out;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
//# debugId=46E2107E1DA7789564756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/vcs/objects.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { sha256 } from \"@noble/hashes/sha2.js\";\nimport type { VirtualFS } from \"../types.cjs\";\nimport {\n appendSample,\n detectBinaryFromSample,\n hashSample,\n readStreamSample,\n} from \"./content.cjs\";\n\nexport interface StoredBlob {\n blobId: string;\n size: number;\n binary: boolean;\n sampleHash: string;\n}\n\nexport class VCSObjectStore {\n constructor(\n private readonly fs: VirtualFS,\n private readonly basePath: string,\n ) {}\n\n async initialize(): Promise<void> {\n await this.fs.mkdir(this.path(\"objects\", \"blobs\"), { recursive: true });\n await this.fs.mkdir(this.path(\"tmp\"), { recursive: true });\n }\n\n async hasBlob(blobId: string): Promise<boolean> {\n return this.fs.exists(this.blobPath(blobId));\n }\n\n async store(source: AsyncIterable<Uint8Array>): Promise<StoredBlob> {\n const tempPath = this.path(\"tmp\", `${Date.now()}-${Math.random().toString(36).slice(2)}.blob`);\n const writer = await this.fs.writeStream(tempPath);\n const hash = sha256.create();\n let size = 0;\n let sample: Uint8Array<ArrayBufferLike> = new Uint8Array();\n\n try {\n for await (const chunk of source) {\n const bytes = chunk instanceof Uint8Array ? chunk : new Uint8Array(chunk);\n hash.update(bytes);\n size += bytes.byteLength;\n sample = appendSample(sample, bytes);\n await writer.write(bytes);\n }\n await writer.close();\n\n const blobId = toHex(hash.digest());\n const finalPath = this.blobPath(blobId);\n await this.fs.mkdir(this.fs.dirname(finalPath), { recursive: true });\n\n if (!(await this.fs.exists(finalPath))) {\n await copyStream(this.fs, tempPath, finalPath);\n }\n\n await this.fs.rm(tempPath, { force: true });\n return {\n blobId,\n size,\n binary: detectBinaryFromSample(sample),\n sampleHash: hashSample(sample),\n };\n } catch (error) {\n await writer.abort?.(error);\n await this.fs.rm(tempPath, { force: true });\n throw error;\n }\n }\n\n async readBlob(blobId: string): Promise<Buffer> {\n return this.fs.readFile(this.blobPath(blobId));\n }\n\n async readBlobText(blobId: string): Promise<string> {\n return this.fs.readFile(this.blobPath(blobId), \"utf8\");\n }\n\n readBlobStream(blobId: string): AsyncIterable<Uint8Array> {\n return this.fs.readStream(this.blobPath(blobId));\n }\n\n async isBinaryBlob(blobId: string): Promise<boolean> {\n const sample = await readStreamSample(this.readBlobStream(blobId));\n return detectBinaryFromSample(sample);\n }\n\n async deleteTempFiles(): Promise<void> {\n await this.fs.rm(this.path(\"tmp\"), { recursive: true, force: true });\n await this.fs.mkdir(this.path(\"tmp\"), { recursive: true });\n }\n\n private blobPath(blobId: string): string {\n return this.path(\"objects\", \"blobs\", blobId.slice(0, 2), blobId.slice(2));\n }\n\n private path(...segments: string[]): string {\n return this.fs.resolve(this.basePath, ...segments);\n }\n}\n\nasync function copyStream(fs: VirtualFS, fromPath: string, toPath: string): Promise<void> {\n const writer = await fs.writeStream(toPath);\n try {\n for await (const chunk of fs.readStream(fromPath)) {\n await writer.write(chunk);\n }\n await writer.close();\n } catch (error) {\n await writer.abort?.(error);\n await fs.rm(toPath, { force: true });\n throw error;\n }\n}\n\nfunction toHex(bytes: Uint8Array): string {\n let out = \"\";\n for (const byte of bytes) {\n out += byte.toString(16).padStart(2, \"0\");\n }\n return out;\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "46E2107E1DA7789564756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|