@orkestrel/workspace 0.0.7 → 0.0.9
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 +7 -7
- package/dist/src/core/index.cjs +48 -15
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +63 -24
- package/dist/src/core/index.d.ts +63 -24
- package/dist/src/core/index.js +49 -16
- package/dist/src/core/index.js.map +1 -1
- package/package.json +15 -16
package/README.md
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
# @orkestrel/workspace
|
|
2
2
|
|
|
3
|
-
The virtual file workspace for the `@orkestrel` line
|
|
3
|
+
> The virtual file workspace for the `@orkestrel` line: a path-keyed map of immutable files with
|
|
4
|
+
> an editing surface over it, a registry that holds those maps by id under one active selection,
|
|
5
|
+
> and a snapshot store seam that persists them.
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
Around that map sit a registry of named workspaces with one active selection, and pluggable stores
|
|
9
|
-
that persist plain snapshots.
|
|
7
|
+
Reach a file by its path — `write`, `read`, `search`, `replace`, `move`, `remove` — and every edit
|
|
8
|
+
mints a new file value and puts it back, so a file is a value you can hold and compare rather than
|
|
9
|
+
a handle that changes underneath you.
|
|
10
10
|
|
|
11
11
|
It is not a filesystem. There is no disk, no `node:fs`, no watcher, no synchronization lifecycle,
|
|
12
12
|
and no dirty-state tracking — a path is a key, not a location. Durability is a separate seam: a
|
|
13
13
|
snapshot is a plain serializable value, and a store is the thing that keeps one.
|
|
14
14
|
|
|
15
15
|
Nothing here is model-specific. An agent loop, a tool handler, and plain application code are all
|
|
16
|
-
|
|
16
|
+
callers.
|
|
17
17
|
|
|
18
18
|
## Install
|
|
19
19
|
|
package/dist/src/core/index.cjs
CHANGED
|
@@ -6,7 +6,7 @@ let _orkestrel_emitter = require("@orkestrel/emitter");
|
|
|
6
6
|
/**
|
|
7
7
|
* Maps file extensions to language tags for text content.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* The table is frozen, and an extension it does not list falls back to `text` in
|
|
10
10
|
* {@link import('./helpers.js').inferLanguage}.
|
|
11
11
|
*/
|
|
12
12
|
var EXTENSION_LANGUAGES = Object.freeze({
|
|
@@ -53,7 +53,10 @@ var EXTENSION_LANGUAGES = Object.freeze({
|
|
|
53
53
|
});
|
|
54
54
|
//#endregion
|
|
55
55
|
//#region src/core/errors.ts
|
|
56
|
-
/**
|
|
56
|
+
/**
|
|
57
|
+
* Reports an invalid workspace edit or search operation, carrying a {@link WorkspaceErrorCode}
|
|
58
|
+
* and, when the operation had one, the context it ran under.
|
|
59
|
+
*/
|
|
57
60
|
var WorkspaceError = class extends Error {
|
|
58
61
|
code;
|
|
59
62
|
context;
|
|
@@ -74,6 +77,10 @@ var WorkspaceError = class extends Error {
|
|
|
74
77
|
/**
|
|
75
78
|
* Narrows a caught value to a {@link WorkspaceError}.
|
|
76
79
|
*
|
|
80
|
+
* @remarks
|
|
81
|
+
* The check is one `instanceof` test, so it stays total: every input answers `true` or `false`
|
|
82
|
+
* and none throws.
|
|
83
|
+
*
|
|
77
84
|
* @param value - The caught value
|
|
78
85
|
* @returns True if the value is a workspace error; false otherwise
|
|
79
86
|
*
|
|
@@ -83,7 +90,7 @@ var WorkspaceError = class extends Error {
|
|
|
83
90
|
* ```
|
|
84
91
|
*/
|
|
85
92
|
function isWorkspaceError(value) {
|
|
86
|
-
return value
|
|
93
|
+
return (0, _orkestrel_contract.isInstance)(value, WorkspaceError);
|
|
87
94
|
}
|
|
88
95
|
//#endregion
|
|
89
96
|
//#region src/core/helpers.ts
|
|
@@ -118,7 +125,7 @@ function isText(content) {
|
|
|
118
125
|
return "text" in content;
|
|
119
126
|
}
|
|
120
127
|
/**
|
|
121
|
-
*
|
|
128
|
+
* Determines whether content is the binary arm.
|
|
122
129
|
*
|
|
123
130
|
* @param content - The file content
|
|
124
131
|
* @returns True if the content carries a base64 string and a MIME; false otherwise
|
|
@@ -165,7 +172,7 @@ function countLines(content) {
|
|
|
165
172
|
return count;
|
|
166
173
|
}
|
|
167
174
|
/**
|
|
168
|
-
* Computes the decoded byte length of a base64 string.
|
|
175
|
+
* Computes the decoded byte length of a base64 string, arithmetically rather than by decoding it.
|
|
169
176
|
*
|
|
170
177
|
* @param base64 - The base64 string
|
|
171
178
|
* @returns The decoded byte count
|
|
@@ -372,11 +379,12 @@ function isWorkspaceSnapshot(value) {
|
|
|
372
379
|
//#endregion
|
|
373
380
|
//#region src/core/workspaces/Workspace.ts
|
|
374
381
|
/**
|
|
375
|
-
*
|
|
382
|
+
* Implements `WorkspaceInterface` over one insertion-ordered path map the instance owns,
|
|
383
|
+
* projecting fresh arrays on every read.
|
|
376
384
|
*
|
|
377
385
|
* Whole-file edits create text files, ranged edits operate only on existing text files, and
|
|
378
386
|
* binary files remain available through construction-time hydration. Mutations emit after the
|
|
379
|
-
*
|
|
387
|
+
* file map has changed.
|
|
380
388
|
*
|
|
381
389
|
* @example
|
|
382
390
|
* ```ts
|
|
@@ -640,7 +648,8 @@ var Workspace = class {
|
|
|
640
648
|
//#endregion
|
|
641
649
|
//#region src/core/workspaces/WorkspaceManager.ts
|
|
642
650
|
/**
|
|
643
|
-
*
|
|
651
|
+
* Implements `WorkspaceManagerInterface` over an insertion-ordered id map and one active id
|
|
652
|
+
* the instance owns, resolving `active` through that map on every read and holding no emitter.
|
|
644
653
|
*
|
|
645
654
|
* A supplied store adds lenient snapshot `open` and `save` operations. Event defaults flow into
|
|
646
655
|
* workspaces created through the registry, while observability remains owned by each workspace.
|
|
@@ -824,11 +833,32 @@ var MemoryWorkspaceStore = class {
|
|
|
824
833
|
* @param input - The file path, content, and optional state
|
|
825
834
|
* @returns A frozen file record
|
|
826
835
|
*
|
|
827
|
-
* @example
|
|
836
|
+
* @example Files and content
|
|
828
837
|
* ```ts
|
|
829
|
-
* import {
|
|
838
|
+
* import {
|
|
839
|
+
* computeSize,
|
|
840
|
+
* countLines,
|
|
841
|
+
* createBinaryContent,
|
|
842
|
+
* createFile,
|
|
843
|
+
* createTextContent,
|
|
844
|
+
* inferLanguage,
|
|
845
|
+
* isBinary,
|
|
846
|
+
* isText,
|
|
847
|
+
* } from '@orkestrel/workspace'
|
|
848
|
+
*
|
|
849
|
+
* const note = createFile({
|
|
850
|
+
* path: 'notes.md',
|
|
851
|
+
* content: createTextContent('# Title\nBody', inferLanguage('notes.md')), // 'markdown'
|
|
852
|
+
* })
|
|
853
|
+
*
|
|
854
|
+
* note.size // 12 — UTF-8 bytes, through computeSize
|
|
855
|
+
* note.lines // 2 — through countLines
|
|
856
|
+
* note.state // 'created'
|
|
857
|
+
* isText(note.content) // true
|
|
830
858
|
*
|
|
831
|
-
* createFile({ path: '
|
|
859
|
+
* const icon = createFile({ path: 'icon.png', content: createBinaryContent('AAAA', 'image/png') })
|
|
860
|
+
* isBinary(icon.content) // true
|
|
861
|
+
* icon.size // 3 — decoded base64 bytes, through computeDecodedSize
|
|
832
862
|
* ```
|
|
833
863
|
*/
|
|
834
864
|
function createFile(input) {
|
|
@@ -841,7 +871,8 @@ function createFile(input) {
|
|
|
841
871
|
});
|
|
842
872
|
}
|
|
843
873
|
/**
|
|
844
|
-
* Creates the text arm of {@link FileContent}
|
|
874
|
+
* Creates the text arm of {@link FileContent}, returned as {@link TextContent} rather than as
|
|
875
|
+
* the whole union.
|
|
845
876
|
*
|
|
846
877
|
* @param text - The text body
|
|
847
878
|
* @param language - The language tag
|
|
@@ -861,7 +892,8 @@ function createTextContent(text, language) {
|
|
|
861
892
|
};
|
|
862
893
|
}
|
|
863
894
|
/**
|
|
864
|
-
* Creates the binary arm of {@link FileContent}
|
|
895
|
+
* Creates the binary arm of {@link FileContent}, returned as {@link BinaryContent} rather than
|
|
896
|
+
* as the whole union.
|
|
865
897
|
*
|
|
866
898
|
* @param base64 - The base64 payload
|
|
867
899
|
* @param mime - The binary MIME
|
|
@@ -881,7 +913,7 @@ function createBinaryContent(base64, mime) {
|
|
|
881
913
|
};
|
|
882
914
|
}
|
|
883
915
|
/**
|
|
884
|
-
* Creates a workspace.
|
|
916
|
+
* Creates a workspace with the same identity, emitter, and seed options the constructor takes.
|
|
885
917
|
*
|
|
886
918
|
* @param options - Optional identity, emitter configuration, and initial files
|
|
887
919
|
* @returns A working workspace
|
|
@@ -913,7 +945,8 @@ function createMemoryWorkspaceStore() {
|
|
|
913
945
|
return new MemoryWorkspaceStore();
|
|
914
946
|
}
|
|
915
947
|
/**
|
|
916
|
-
* Creates a database-backed workspace snapshot store
|
|
948
|
+
* Creates a database-backed workspace snapshot store, over an in-memory driver when the caller
|
|
949
|
+
* supplies none.
|
|
917
950
|
*
|
|
918
951
|
* @param driver - The database driver. Default: an in-memory driver.
|
|
919
952
|
* @returns A workspace store backed by the supplied driver
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["#id","#files","#emitter","#pattern","#write","#splice","#prepend","#append","#move","#remove","#workspaces","#on","#error","#store","#active","#drop","#table","#snapshots"],"sources":["../../../src/core/constants.ts","../../../src/core/errors.ts","../../../src/core/helpers.ts","../../../src/core/validators.ts","../../../src/core/workspaces/Workspace.ts","../../../src/core/workspaces/WorkspaceManager.ts","../../../src/core/workspaces/stores/DatabaseWorkspaceStore.ts","../../../src/core/workspaces/stores/MemoryWorkspaceStore.ts","../../../src/core/factories.ts"],"sourcesContent":["/**\n * Maps file extensions to language tags for text content.\n *\n * Unknown extensions intentionally fall back to `text` in\n * {@link import('./helpers.js').inferLanguage}.\n */\nexport const EXTENSION_LANGUAGES: Readonly<Record<string, string>> = Object.freeze({\n\tts: 'typescript',\n\ttsx: 'typescript',\n\tjs: 'javascript',\n\tjsx: 'javascript',\n\tmjs: 'javascript',\n\tcjs: 'javascript',\n\tjson: 'json',\n\tmd: 'markdown',\n\thtml: 'html',\n\thtm: 'html',\n\tcss: 'css',\n\tscss: 'scss',\n\tsass: 'sass',\n\tless: 'less',\n\tvue: 'vue',\n\tsvelte: 'svelte',\n\tpy: 'python',\n\trb: 'ruby',\n\trs: 'rust',\n\tgo: 'go',\n\tjava: 'java',\n\tkt: 'kotlin',\n\tswift: 'swift',\n\tc: 'c',\n\tcpp: 'cpp',\n\th: 'c',\n\thpp: 'cpp',\n\tcs: 'csharp',\n\tphp: 'php',\n\tsql: 'sql',\n\tsh: 'bash',\n\tbash: 'bash',\n\tzsh: 'bash',\n\tps1: 'powershell',\n\tyaml: 'yaml',\n\tyml: 'yaml',\n\ttoml: 'toml',\n\txml: 'xml',\n\tsvg: 'xml',\n\ttxt: 'text',\n})\n","import type { WorkspaceErrorCode } from './types.js'\n\n/** Reports an invalid workspace edit or search operation. */\nexport class WorkspaceError extends Error {\n\treadonly code: WorkspaceErrorCode\n\treadonly context?: Readonly<Record<string, unknown>>\n\n\t/**\n\t * Creates a workspace error.\n\t *\n\t * @param code - The machine-readable failure code\n\t * @param message - The human-readable failure message\n\t * @param context - Optional values associated with the failed operation\n\t */\n\tconstructor(\n\t\tcode: WorkspaceErrorCode,\n\t\tmessage: string,\n\t\tcontext?: Readonly<Record<string, unknown>>,\n\t) {\n\t\tsuper(message)\n\t\tthis.name = 'WorkspaceError'\n\t\tthis.code = code\n\t\tif (context !== undefined) this.context = context\n\t}\n}\n\n/**\n * Narrows a caught value to a {@link WorkspaceError}.\n *\n * @param value - The caught value\n * @returns True if the value is a workspace error; false otherwise\n *\n * @example\n * ```ts\n * if (isWorkspaceError(error)) error.code\n * ```\n */\nexport function isWorkspaceError(value: unknown): value is WorkspaceError {\n\treturn value instanceof WorkspaceError\n}\n","import type { BinaryContent, FileContent, Position, Range, TextContent } from './types.js'\nimport { EXTENSION_LANGUAGES } from './constants.js'\n\n/**\n * Infers a language tag from the final file extension.\n *\n * @param path - The file path\n * @returns The mapped language, or `text` when the extension is absent or unknown\n *\n * @example\n * ```ts\n * inferLanguage('src/main.ts') // 'typescript'\n * ```\n */\nexport function inferLanguage(path: string): string {\n\tconst dot = path.lastIndexOf('.')\n\tif (dot === -1) return 'text'\n\tconst extension = path.slice(dot + 1).toLowerCase()\n\treturn EXTENSION_LANGUAGES[extension] ?? 'text'\n}\n\n/**\n * Determines whether content is the text arm.\n *\n * @param content - The file content\n * @returns True if the content carries text and a language; false otherwise\n *\n * @example\n * ```ts\n * isText({ text: 'hello', language: 'text' }) // true\n * ```\n */\nexport function isText(content: FileContent): content is TextContent {\n\treturn 'text' in content\n}\n\n/**\n * Checks whether content is the binary arm.\n *\n * @param content - The file content\n * @returns True if the content carries a base64 string and a MIME; false otherwise\n *\n * @example\n * ```ts\n * isBinary({ base64: 'AAAA', mime: 'image/png' }) // true\n * ```\n */\nexport function isBinary(content: FileContent): content is BinaryContent {\n\treturn 'base64' in content\n}\n\n/**\n * Computes the byte size of file content.\n *\n * @param content - The content to measure\n * @returns UTF-8 bytes for text or decoded bytes for binary content\n *\n * @example\n * ```ts\n * computeSize({ text: 'café', language: 'text' }) // 5\n * ```\n */\nexport function computeSize(content: FileContent): number {\n\tif (isText(content)) return new TextEncoder().encode(content.text).length\n\treturn computeDecodedSize(content.base64)\n}\n\n/**\n * Counts the lines in file content.\n *\n * @param content - The content to inspect\n * @returns The text line count, or zero for empty text and binary content\n *\n * @example\n * ```ts\n * countLines({ text: 'a\\nb', language: 'text' }) // 2\n * ```\n */\nexport function countLines(content: FileContent): number {\n\tif (!isText(content)) return 0\n\tif (content.text.length === 0) return 0\n\tlet count = 1\n\tfor (const character of content.text) if (character === '\\n') count += 1\n\treturn count\n}\n\n/**\n * Computes the decoded byte length of a base64 string.\n *\n * @param base64 - The base64 string\n * @returns The decoded byte count\n *\n * @example\n * ```ts\n * computeDecodedSize('AAAA') // 3\n * ```\n */\nexport function computeDecodedSize(base64: string): number {\n\tlet padding = 0\n\tif (base64.endsWith('==')) padding = 2\n\telse if (base64.endsWith('=')) padding = 1\n\treturn Math.floor((base64.length * 3) / 4) - padding\n}\n\n/**\n * Determines whether a 1-based range is structurally valid.\n *\n * @param range - The range to inspect\n * @returns True if both positions are positive and ordered; false otherwise\n *\n * @example\n * ```ts\n * isValidRange({ start: { line: 1, column: 1 }, end: { line: 1, column: 2 } }) // true\n * ```\n */\nexport function isValidRange(range: Range): boolean {\n\tif (range.start.line < 1 || range.start.column < 1) return false\n\tif (range.end.line < 1 || range.end.column < 1) return false\n\tif (range.start.line > range.end.line) return false\n\treturn !(range.start.line === range.end.line && range.start.column > range.end.column)\n}\n\n/**\n * Clamps a position to text bounds.\n *\n * @param text - The addressed text\n * @param position - The requested position\n * @returns The clamped position\n *\n * @example\n * ```ts\n * clampPosition('ab', { line: 9, column: 9 }) // { line: 1, column: 3 }\n * ```\n */\nexport function clampPosition(text: string, position: Position): Position {\n\tconst lines = text.split('\\n')\n\tconst line = Math.max(1, Math.min(position.line, lines.length))\n\tconst lineText = lines[line - 1] ?? ''\n\tconst column = Math.max(1, Math.min(position.column, lineText.length + 1))\n\treturn { line, column }\n}\n\n/**\n * Clamps both positions in a range to text bounds.\n *\n * @param text - The addressed text\n * @param range - The requested range\n * @returns The clamped range\n *\n * @example\n * ```ts\n * clampRange('ab', { start: { line: 1, column: 1 }, end: { line: 9, column: 9 } })\n * ```\n */\nexport function clampRange(text: string, range: Range): Range {\n\treturn { start: clampPosition(text, range.start), end: clampPosition(text, range.end) }\n}\n\n/**\n * Converts a 1-based position to a zero-based string offset.\n *\n * @param text - The addressed text\n * @param position - The requested position\n * @returns The bounded string offset\n *\n * @example\n * ```ts\n * offsetAt('ab\\ncd', { line: 2, column: 1 }) // 3\n * ```\n */\nexport function offsetAt(text: string, position: Position): number {\n\tconst lines = text.split('\\n')\n\tlet offset = 0\n\tfor (let index = 0; index < position.line - 1 && index < lines.length; index += 1) {\n\t\toffset += (lines[index]?.length ?? 0) + 1\n\t}\n\toffset += position.column - 1\n\treturn Math.min(offset, text.length)\n}\n\n/**\n * Slices a clamped half-open text range.\n *\n * @param text - The source text\n * @param range - The requested range\n * @returns The ranged substring\n *\n * @example\n * ```ts\n * sliceRange('hello', { start: { line: 1, column: 1 }, end: { line: 1, column: 6 } }) // 'hello'\n * ```\n */\nexport function sliceRange(text: string, range: Range): string {\n\tconst clamped = clampRange(text, range)\n\treturn text.slice(offsetAt(text, clamped.start), offsetAt(text, clamped.end))\n}\n\n/**\n * Replaces a clamped half-open text range.\n *\n * @param text - The source text\n * @param range - The requested range\n * @param replacement - The replacement text\n * @returns The spliced text\n *\n * @example\n * ```ts\n * spliceRange('hello', { start: { line: 1, column: 1 }, end: { line: 1, column: 6 } }, 'bye')\n * ```\n */\nexport function spliceRange(text: string, range: Range, replacement: string): string {\n\tconst clamped = clampRange(text, range)\n\tconst start = offsetAt(text, clamped.start)\n\tconst end = offsetAt(text, clamped.end)\n\treturn text.slice(0, start) + replacement + text.slice(end)\n}\n\n/**\n * Assembles a nested range from four 1-based coordinates.\n *\n * @param fromLine - The start line\n * @param fromColumn - The start column\n * @param toLine - The end line\n * @param toColumn - The end column\n * @returns The assembled range without validation\n *\n * @example\n * ```ts\n * rangeOf(1, 1, 1, 2)\n * ```\n */\nexport function rangeOf(\n\tfromLine: number,\n\tfromColumn: number,\n\ttoLine: number,\n\ttoColumn: number,\n): Range {\n\treturn { start: { line: fromLine, column: fromColumn }, end: { line: toLine, column: toColumn } }\n}\n\n/**\n * Escapes regular-expression metacharacters for literal matching.\n *\n * @param value - The literal text\n * @returns The escaped regular-expression source\n *\n * @example\n * ```ts\n * escapeRegExp('a.b') // 'a\\\\.b'\n * ```\n */\nexport function escapeRegExp(value: string): string {\n\treturn value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n","import type { FileInterface, WorkspaceSnapshot } from './types.js'\nimport { arrayOf, holds, isNumber, isRecord, isString, literalOf } from '@orkestrel/contract'\n\n/**\n * Narrows an unknown value to an immutable file record.\n *\n * @param value - The value to inspect\n * @returns True if the value has the file shape; false otherwise\n *\n * @example\n * ```ts\n * isFile({ path: 'a.txt', content: { text: 'a', language: 'text' }, state: 'created', size: 1, lines: 1 })\n * ```\n */\nexport function isFile(value: unknown): value is FileInterface {\n\treturn holds(() => {\n\t\tif (!isRecord(value)) return false\n\t\tif (!isString(value.path) || !literalOf('created', 'modified')(value.state)) return false\n\t\tif (!isNumber(value.size) || !isNumber(value.lines)) return false\n\t\tif (!isRecord(value.content)) return false\n\t\tconst text = isString(value.content.text) && isString(value.content.language)\n\t\tconst binary =\n\t\t\tisString(value.content.base64) &&\n\t\t\tliteralOf('image/png', 'image/jpeg', 'image/gif', 'image/webp')(value.content.mime)\n\t\treturn text || binary\n\t})\n}\n\n/**\n * Narrows an unknown value to a workspace snapshot.\n *\n * @param value - The value read from a persistence boundary\n * @returns True if the value has the workspace snapshot shape; false otherwise\n *\n * @example\n * ```ts\n * isWorkspaceSnapshot({ id: 'work', files: [] }) // true\n * ```\n */\nexport function isWorkspaceSnapshot(value: unknown): value is WorkspaceSnapshot {\n\treturn holds(() => isRecord(value) && isString(value.id) && arrayOf(isFile)(value.files))\n}\n","import type { EmitterInterface } from '@orkestrel/emitter'\nimport type {\n\tFileInterface,\n\tRange,\n\tReadResult,\n\tReplaceResult,\n\tSearchMatch,\n\tSearchOptions,\n\tWorkspaceEventMap,\n\tWorkspaceInterface,\n\tWorkspaceOptions,\n\tWorkspaceSnapshot,\n} from '../types.js'\nimport { isArray, isRecord } from '@orkestrel/contract'\nimport { Emitter } from '@orkestrel/emitter'\nimport { WorkspaceError } from '../errors.js'\nimport { createFile } from '../factories.js'\nimport {\n\tclampRange,\n\tescapeRegExp,\n\tinferLanguage,\n\tisText,\n\tisValidRange,\n\tsliceRange,\n\tspliceRange,\n} from '../helpers.js'\n\n/**\n * Provides a mutable path-keyed editing surface over immutable files.\n *\n * Whole-file edits create text files, ranged edits operate only on existing text files, and\n * binary files remain available through construction-time hydration. Mutations emit after the\n * registry has changed.\n *\n * @example\n * ```ts\n * import { Workspace } from '@orkestrel/workspace'\n *\n * const workspace = new Workspace()\n * workspace.write('notes.txt', 'hello')\n * workspace.append('notes.txt', ' world')\n * workspace.read('notes.txt') // 'hello world'\n * ```\n */\nexport class Workspace implements WorkspaceInterface {\n\treadonly #id: string\n\treadonly #files = new Map<string, FileInterface>()\n\treadonly #emitter: Emitter<WorkspaceEventMap>\n\n\t/**\n\t * Creates a workspace.\n\t *\n\t * @param options - Optional identity, emitter configuration, and initial files\n\t */\n\tconstructor(options?: WorkspaceOptions) {\n\t\tthis.#id = options?.id ?? crypto.randomUUID()\n\t\tthis.#emitter = new Emitter<WorkspaceEventMap>({\n\t\t\t...(options?.on === undefined ? {} : { on: options.on }),\n\t\t\t...(options?.error === undefined ? {} : { error: options.error }),\n\t\t})\n\t\tif (options?.seed) for (const file of options.seed) this.#files.set(file.path, file)\n\t}\n\n\tget id(): string {\n\t\treturn this.#id\n\t}\n\n\tget emitter(): EmitterInterface<WorkspaceEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tget count(): number {\n\t\treturn this.#files.size\n\t}\n\n\tfile(path: string): FileInterface | undefined {\n\t\treturn this.#files.get(path)\n\t}\n\n\tfiles(): readonly FileInterface[] {\n\t\treturn [...this.#files.values()]\n\t}\n\n\tread(path: string): string | undefined\n\tread(path: string, range: Range): ReadResult | undefined\n\tread(paths: readonly string[]): Readonly<Record<string, string>>\n\tread(\n\t\tpath: string | readonly string[],\n\t\trange?: Range,\n\t): string | ReadResult | undefined | Readonly<Record<string, string>> {\n\t\tif (isArray(path)) {\n\t\t\tconst result: Record<string, string> = {}\n\t\t\tfor (const one of path) {\n\t\t\t\tconst file = this.#files.get(one)\n\t\t\t\tif (file && isText(file.content)) result[one] = file.content.text\n\t\t\t}\n\t\t\treturn result\n\t\t}\n\t\tconst file = this.#files.get(path)\n\t\tif (!file) return undefined\n\t\tif (!range) return isText(file.content) ? file.content.text : undefined\n\t\tif (!isText(file.content)) {\n\t\t\tthrow new WorkspaceError('MODALITY', `Cannot read a range of a binary file: ${path}`, {\n\t\t\t\tpath,\n\t\t\t})\n\t\t}\n\t\treturn {\n\t\t\tcontent: sliceRange(file.content.text, range),\n\t\t\trange: clampRange(file.content.text, range),\n\t\t}\n\t}\n\n\thas(path: string): boolean\n\thas(paths: readonly string[]): boolean\n\thas(path: string | readonly string[]): boolean {\n\t\tif (isArray(path)) return path.every((one) => this.#files.has(one))\n\t\treturn this.#files.has(path)\n\t}\n\n\tsearch(query: string, options?: SearchOptions): readonly SearchMatch[] {\n\t\tconst pattern = this.#pattern(query, options)\n\t\tconst limit = options?.limit\n\t\tconst matches: SearchMatch[] = []\n\t\tfor (const file of this.#files.values()) {\n\t\t\tif (limit !== undefined && matches.length >= limit) break\n\t\t\tif (!isText(file.content)) continue\n\t\t\tconst lines = file.content.text.split(/\\r\\n|\\n/)\n\t\t\tfor (let index = 0; index < lines.length; index += 1) {\n\t\t\t\tif (limit !== undefined && matches.length >= limit) break\n\t\t\t\tconst lineText = lines[index] ?? ''\n\t\t\t\tpattern.lastIndex = 0\n\t\t\t\tlet hit = pattern.exec(lineText)\n\t\t\t\twhile (hit !== null) {\n\t\t\t\t\tif (limit !== undefined && matches.length >= limit) break\n\t\t\t\t\tmatches.push({\n\t\t\t\t\t\tpath: file.path,\n\t\t\t\t\t\tline: index + 1,\n\t\t\t\t\t\tcolumn: hit.index + 1,\n\t\t\t\t\t\tlength: hit[0].length,\n\t\t\t\t\t\tcontent: lineText,\n\t\t\t\t\t})\n\t\t\t\t\tif (hit[0].length === 0) pattern.lastIndex += 1\n\t\t\t\t\thit = pattern.exec(lineText)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn matches\n\t}\n\n\treplace(query: string, replacement: string, options?: SearchOptions): ReplaceResult {\n\t\tconst pattern = this.#pattern(query, options)\n\t\tconst limit = options?.limit\n\t\tlet occurrences = 0\n\t\tlet files = 0\n\t\tfor (const [path, file] of this.#files) {\n\t\t\tif (limit !== undefined && occurrences >= limit) break\n\t\t\tif (!isText(file.content)) continue\n\t\t\tconst remaining = limit === undefined ? undefined : limit - occurrences\n\t\t\tlet count = 0\n\t\t\tpattern.lastIndex = 0\n\t\t\tconst next = file.content.text.replace(pattern, (match) => {\n\t\t\t\tif (remaining !== undefined && count >= remaining) return match\n\t\t\t\tcount += 1\n\t\t\t\treturn replacement\n\t\t\t})\n\t\t\tif (count > 0) {\n\t\t\t\toccurrences += count\n\t\t\t\tfiles += 1\n\t\t\t\tthis.write(path, next)\n\t\t\t}\n\t\t}\n\t\treturn { occurrences, files }\n\t}\n\n\twrite(path: string, content: string): void\n\twrite(path: string, content: string, range: Range): void\n\twrite(files: Readonly<Record<string, string>>): void\n\twrite(path: string | Readonly<Record<string, string>>, content?: string, range?: Range): void {\n\t\tif (isRecord(path)) {\n\t\t\tfor (const [one, text] of Object.entries(path)) this.#write(one, text)\n\t\t\treturn\n\t\t}\n\t\tif (content === undefined) return\n\t\tif (!range) {\n\t\t\tthis.#write(path, content)\n\t\t\treturn\n\t\t}\n\t\tthis.#splice(path, content, range)\n\t}\n\n\tprepend(path: string, content: string): void\n\tprepend(files: Readonly<Record<string, string>>): void\n\tprepend(path: string | Readonly<Record<string, string>>, content?: string): void {\n\t\tif (isRecord(path)) {\n\t\t\tfor (const [one, text] of Object.entries(path)) this.#prepend(one, text)\n\t\t\treturn\n\t\t}\n\t\tif (content === undefined) return\n\t\tthis.#prepend(path, content)\n\t}\n\n\tappend(path: string, content: string): void\n\tappend(files: Readonly<Record<string, string>>): void\n\tappend(path: string | Readonly<Record<string, string>>, content?: string): void {\n\t\tif (isRecord(path)) {\n\t\t\tfor (const [one, text] of Object.entries(path)) this.#append(one, text)\n\t\t\treturn\n\t\t}\n\t\tif (content === undefined) return\n\t\tthis.#append(path, content)\n\t}\n\n\tmove(from: string, to: string): boolean\n\tmove(mapping: Readonly<Record<string, string>>): boolean\n\tmove(from: string | Readonly<Record<string, string>>, to?: string): boolean {\n\t\tif (isRecord(from)) {\n\t\t\tlet moved = true\n\t\t\tfor (const [one, target] of Object.entries(from)) {\n\t\t\t\tif (!this.#move(one, target)) moved = false\n\t\t\t}\n\t\t\treturn moved\n\t\t}\n\t\tif (to === undefined) return false\n\t\treturn this.#move(from, to)\n\t}\n\n\tremove(path: string): boolean\n\tremove(paths: readonly string[]): boolean\n\tremove(path: string | readonly string[]): boolean {\n\t\tif (isArray(path)) {\n\t\t\tlet removed = true\n\t\t\tfor (const one of path) {\n\t\t\t\tif (!this.#remove(one)) removed = false\n\t\t\t}\n\t\t\treturn removed\n\t\t}\n\t\treturn this.#remove(path)\n\t}\n\n\tclear(): void {\n\t\tthis.#files.clear()\n\t\tthis.#emitter.emit('clear')\n\t}\n\n\tsnapshot(): WorkspaceSnapshot {\n\t\treturn { id: this.#id, files: this.files() }\n\t}\n\n\tdestroy(): void {\n\t\tthis.#emitter.destroy()\n\t}\n\n\t#write(path: string, content: string): void {\n\t\tconst existing = this.#files.get(path)\n\t\tconst language =\n\t\t\texisting && isText(existing.content) ? existing.content.language : inferLanguage(path)\n\t\tconst file = createFile({\n\t\t\tpath,\n\t\t\tcontent: { text: content, language },\n\t\t\tstate: existing ? 'modified' : 'created',\n\t\t})\n\t\tthis.#files.set(path, file)\n\t\tthis.#emitter.emit('write', file)\n\t}\n\n\t#splice(path: string, content: string, range: Range): void {\n\t\tconst existing = this.#files.get(path)\n\t\tif (!existing) {\n\t\t\tthrow new WorkspaceError('MISSING', `Cannot splice a range of a missing file: ${path}`, {\n\t\t\t\tpath,\n\t\t\t})\n\t\t}\n\t\tif (!isText(existing.content)) {\n\t\t\tthrow new WorkspaceError('MODALITY', `Cannot splice a range of a binary file: ${path}`, {\n\t\t\t\tpath,\n\t\t\t})\n\t\t}\n\t\tif (!isValidRange(range)) {\n\t\t\tthrow new WorkspaceError('RANGE', `Invalid range for file: ${path}`, { path, range })\n\t\t}\n\t\tconst file = createFile({\n\t\t\tpath,\n\t\t\tcontent: {\n\t\t\t\ttext: spliceRange(existing.content.text, range, content),\n\t\t\t\tlanguage: existing.content.language,\n\t\t\t},\n\t\t\tstate: 'modified',\n\t\t})\n\t\tthis.#files.set(path, file)\n\t\tthis.#emitter.emit('write', file)\n\t}\n\n\t#prepend(path: string, content: string): void {\n\t\tconst existing = this.#files.get(path)\n\t\tlet text = ''\n\t\tif (existing) {\n\t\t\tif (!isText(existing.content)) {\n\t\t\t\tthrow new WorkspaceError('MODALITY', `Cannot prepend text to a binary file: ${path}`, {\n\t\t\t\t\tpath,\n\t\t\t\t})\n\t\t\t}\n\t\t\ttext = existing.content.text\n\t\t}\n\t\tthis.#write(path, content + text)\n\t}\n\n\t#append(path: string, content: string): void {\n\t\tconst existing = this.#files.get(path)\n\t\tlet text = ''\n\t\tif (existing) {\n\t\t\tif (!isText(existing.content)) {\n\t\t\t\tthrow new WorkspaceError('MODALITY', `Cannot append text to a binary file: ${path}`, {\n\t\t\t\t\tpath,\n\t\t\t\t})\n\t\t\t}\n\t\t\ttext = existing.content.text\n\t\t}\n\t\tthis.#write(path, text + content)\n\t}\n\n\t#move(from: string, to: string): boolean {\n\t\tif (from === to) return false\n\t\tconst file = this.#files.get(from)\n\t\tif (!file) return false\n\t\tconst moved = createFile({ path: to, content: file.content, state: 'modified' })\n\t\tconst entries = [...this.#files]\n\t\tthis.#files.clear()\n\t\tfor (const [path, current] of entries) {\n\t\t\tif (path === from) this.#files.set(to, moved)\n\t\t\telse if (path !== to) this.#files.set(path, current)\n\t\t}\n\t\tthis.#emitter.emit('move', from, to)\n\t\treturn true\n\t}\n\n\t#remove(path: string): boolean {\n\t\tconst removed = this.#files.delete(path)\n\t\tif (removed) this.#emitter.emit('remove', path)\n\t\treturn removed\n\t}\n\n\t#pattern(query: string, options?: SearchOptions): RegExp {\n\t\tconst source = options?.regex === true ? query : escapeRegExp(query)\n\t\tconst flags = options?.sensitive === false ? 'gi' : 'g'\n\t\ttry {\n\t\t\treturn new RegExp(source, flags)\n\t\t} catch {\n\t\t\tthrow new WorkspaceError('PATTERN', `Invalid search pattern: ${query}`, { query })\n\t\t}\n\t}\n}\n","import type { EmitterErrorHandler, EmitterHooks } from '@orkestrel/emitter'\nimport type {\n\tWorkspaceEventMap,\n\tWorkspaceInterface,\n\tWorkspaceManagerInterface,\n\tWorkspaceManagerOptions,\n\tWorkspaceOptions,\n\tWorkspaceStoreInterface,\n} from '../types.js'\nimport { isArray } from '@orkestrel/contract'\nimport { Workspace } from './Workspace.js'\n\n/**\n * Provides an insertion-ordered workspace registry with an active selection.\n *\n * A supplied store adds lenient snapshot `open` and `save` operations. Event defaults flow into\n * workspaces created through the registry, while observability remains owned by each workspace.\n *\n * @example\n * ```ts\n * import { WorkspaceManager } from '@orkestrel/workspace'\n *\n * const manager = new WorkspaceManager()\n * const workspace = manager.add({ id: 'scratch' })\n * manager.active === workspace\n * ```\n */\nexport class WorkspaceManager implements WorkspaceManagerInterface {\n\treadonly #workspaces = new Map<string, WorkspaceInterface>()\n\t#active: string | undefined\n\treadonly #on: EmitterHooks<WorkspaceEventMap> | undefined\n\treadonly #error: EmitterErrorHandler | undefined\n\treadonly #store: WorkspaceStoreInterface | undefined\n\n\t/**\n\t * Creates a registry.\n\t *\n\t * @param options - Default event hooks and optional snapshot store\n\t */\n\tconstructor(options?: WorkspaceManagerOptions) {\n\t\tthis.#on = options?.on\n\t\tthis.#error = options?.error\n\t\tthis.#store = options?.store\n\t}\n\n\tget count(): number {\n\t\treturn this.#workspaces.size\n\t}\n\n\tget active(): WorkspaceInterface | undefined {\n\t\treturn this.#active === undefined ? undefined : this.#workspaces.get(this.#active)\n\t}\n\n\tworkspace(id: string): WorkspaceInterface | undefined {\n\t\treturn this.#workspaces.get(id)\n\t}\n\n\tworkspaces(): readonly WorkspaceInterface[] {\n\t\treturn [...this.#workspaces.values()]\n\t}\n\n\tadd(options?: WorkspaceOptions): WorkspaceInterface {\n\t\tconst on = options?.on ?? this.#on\n\t\tconst error = options?.error ?? this.#error\n\t\tconst workspace = new Workspace({\n\t\t\t...(options?.id === undefined ? {} : { id: options.id }),\n\t\t\t...(on === undefined ? {} : { on }),\n\t\t\t...(error === undefined ? {} : { error }),\n\t\t\t...(options?.seed === undefined ? {} : { seed: options.seed }),\n\t\t})\n\t\tthis.#workspaces.set(workspace.id, workspace)\n\t\tif (this.#active === undefined) this.#active = workspace.id\n\t\treturn workspace\n\t}\n\n\tswitch(id: string): WorkspaceInterface | undefined {\n\t\tconst workspace = this.#workspaces.get(id)\n\t\tif (workspace === undefined) return undefined\n\t\tthis.#active = id\n\t\treturn workspace\n\t}\n\n\tasync open(id: string): Promise<WorkspaceInterface | undefined> {\n\t\tconst existing = this.#workspaces.get(id)\n\t\tif (existing !== undefined) {\n\t\t\tthis.#active = id\n\t\t\treturn existing\n\t\t}\n\t\tif (this.#store === undefined) return undefined\n\t\tconst snapshot = await this.#store.get(id)\n\t\tif (snapshot === undefined) return undefined\n\t\tconst workspace = this.add({ id, seed: snapshot.files })\n\t\tthis.#active = workspace.id\n\t\treturn workspace\n\t}\n\n\tasync save(id: string): Promise<boolean> {\n\t\tconst workspace = this.#workspaces.get(id)\n\t\tif (this.#store === undefined || workspace === undefined) return false\n\t\tawait this.#store.set(workspace.snapshot())\n\t\treturn true\n\t}\n\n\tremove(id: string): boolean\n\tremove(ids: readonly string[]): boolean\n\tremove(ids: string | readonly string[]): boolean {\n\t\tif (isArray(ids)) {\n\t\t\tlet removed = true\n\t\t\tfor (const id of ids) {\n\t\t\t\tif (!this.#drop(id)) removed = false\n\t\t\t}\n\t\t\treturn removed\n\t\t}\n\t\treturn this.#drop(ids)\n\t}\n\n\tclear(): void {\n\t\tfor (const workspace of this.#workspaces.values()) workspace.destroy()\n\t\tthis.#workspaces.clear()\n\t\tthis.#active = undefined\n\t}\n\n\t#drop(id: string): boolean {\n\t\tconst workspace = this.#workspaces.get(id)\n\t\tif (workspace === undefined) return false\n\t\tthis.#workspaces.delete(id)\n\t\tworkspace.destroy()\n\t\tif (this.#active === id) this.#active = undefined\n\t\treturn true\n\t}\n}\n","import type {\n\tWorkspaceSnapshot,\n\tWorkspaceSnapshotRow,\n\tWorkspaceStoreInterface,\n} from '../../types.js'\nimport type { TableInterface } from '@orkestrel/database'\nimport { isWorkspaceSnapshot } from '../../validators.js'\n\n/**\n * Persists workspace snapshots in a database table.\n *\n * Snapshots occupy one opaque column and are narrowed when read back from the storage boundary.\n *\n * @example\n * ```ts\n * import { rawShape, stringShape } from '@orkestrel/contract'\n * import { createDatabase, createMemoryDriver } from '@orkestrel/database'\n * import { DatabaseWorkspaceStore } from '@orkestrel/workspace'\n *\n * const database = createDatabase({\n * \tdriver: createMemoryDriver(),\n * \ttables: { workspaces: { id: stringShape(), snapshot: rawShape({}) } },\n * })\n * const store = new DatabaseWorkspaceStore(database.table('workspaces'))\n * ```\n */\nexport class DatabaseWorkspaceStore implements WorkspaceStoreInterface {\n\treadonly #table: TableInterface<WorkspaceSnapshotRow>\n\n\t/**\n\t * Wraps a workspace snapshot table.\n\t *\n\t * @param table - The table keyed by workspace identifier\n\t */\n\tconstructor(table: TableInterface<WorkspaceSnapshotRow>) {\n\t\tthis.#table = table\n\t}\n\n\tasync get(id: string): Promise<WorkspaceSnapshot | undefined> {\n\t\tconst row = await this.#table.get(id)\n\t\tif (row === undefined) return undefined\n\t\treturn isWorkspaceSnapshot(row.snapshot) ? row.snapshot : undefined\n\t}\n\n\tasync set(snapshot: WorkspaceSnapshot): Promise<void> {\n\t\tawait this.#table.set({ id: snapshot.id, snapshot })\n\t}\n\n\tasync delete(id: string): Promise<void> {\n\t\tawait this.#table.remove(id)\n\t}\n}\n","import type { WorkspaceSnapshot, WorkspaceStoreInterface } from '../../types.js'\n\n/**\n * Holds workspace snapshots in the current process.\n *\n * @example\n * ```ts\n * import { MemoryWorkspaceStore } from '@orkestrel/workspace'\n *\n * const store = new MemoryWorkspaceStore()\n * ```\n */\nexport class MemoryWorkspaceStore implements WorkspaceStoreInterface {\n\treadonly #snapshots = new Map<string, WorkspaceSnapshot>()\n\n\tget(id: string): Promise<WorkspaceSnapshot | undefined> {\n\t\treturn Promise.resolve(this.#snapshots.get(id))\n\t}\n\n\tset(snapshot: WorkspaceSnapshot): Promise<void> {\n\t\tthis.#snapshots.set(snapshot.id, snapshot)\n\t\treturn Promise.resolve()\n\t}\n\n\tdelete(id: string): Promise<void> {\n\t\tthis.#snapshots.delete(id)\n\t\treturn Promise.resolve()\n\t}\n}\n","import type {\n\tBinaryContent,\n\tBinaryMIME,\n\tFileInput,\n\tFileInterface,\n\tTextContent,\n\tWorkspaceInterface,\n\tWorkspaceManagerInterface,\n\tWorkspaceManagerOptions,\n\tWorkspaceOptions,\n\tWorkspaceSnapshotRow,\n\tWorkspaceStoreInterface,\n} from './types.js'\nimport type { DriverInterface, TableInterface } from '@orkestrel/database'\nimport { rawShape, stringShape } from '@orkestrel/contract'\nimport { createDatabase, createMemoryDriver } from '@orkestrel/database'\nimport { computeSize, countLines } from './helpers.js'\nimport { Workspace } from './workspaces/Workspace.js'\nimport { WorkspaceManager } from './workspaces/WorkspaceManager.js'\nimport { DatabaseWorkspaceStore } from './workspaces/stores/DatabaseWorkspaceStore.js'\nimport { MemoryWorkspaceStore } from './workspaces/stores/MemoryWorkspaceStore.js'\n\n/**\n * Creates an immutable file with derived size and line counts.\n *\n * @param input - The file path, content, and optional state\n * @returns A frozen file record\n *\n * @example\n * ```ts\n * import { createFile, createTextContent } from '@orkestrel/workspace'\n *\n * createFile({ path: 'a.txt', content: createTextContent('hello', 'text') })\n * ```\n */\nexport function createFile(input: FileInput): FileInterface {\n\treturn Object.freeze({\n\t\tpath: input.path,\n\t\tcontent: input.content,\n\t\tstate: input.state ?? 'created',\n\t\tsize: computeSize(input.content),\n\t\tlines: countLines(input.content),\n\t})\n}\n\n/**\n * Creates the text arm of {@link FileContent}.\n *\n * @param text - The text body\n * @param language - The language tag\n * @returns Text file content\n *\n * @example\n * ```ts\n * import { createTextContent } from '@orkestrel/workspace'\n *\n * createTextContent('hello', 'text')\n * ```\n */\nexport function createTextContent(text: string, language: string): TextContent {\n\treturn { text, language }\n}\n\n/**\n * Creates the binary arm of {@link FileContent}.\n *\n * @param base64 - The base64 payload\n * @param mime - The binary MIME\n * @returns Binary file content\n *\n * @example\n * ```ts\n * import { createBinaryContent } from '@orkestrel/workspace'\n *\n * createBinaryContent('AAAA', 'image/png')\n * ```\n */\nexport function createBinaryContent(base64: string, mime: BinaryMIME): BinaryContent {\n\treturn { base64, mime }\n}\n\n/**\n * Creates a workspace.\n *\n * @param options - Optional identity, emitter configuration, and initial files\n * @returns A working workspace\n *\n * @example\n * ```ts\n * import { createWorkspace } from '@orkestrel/workspace'\n *\n * const workspace = createWorkspace()\n * workspace.write('a.txt', 'hello')\n * ```\n */\nexport function createWorkspace(options?: WorkspaceOptions): WorkspaceInterface {\n\treturn new Workspace(options)\n}\n\n/**\n * Creates an in-memory workspace snapshot store.\n *\n * @returns A process-local workspace store\n *\n * @example\n * ```ts\n * import { createMemoryWorkspaceStore } from '@orkestrel/workspace'\n *\n * const store = createMemoryWorkspaceStore()\n * ```\n */\nexport function createMemoryWorkspaceStore(): WorkspaceStoreInterface {\n\treturn new MemoryWorkspaceStore()\n}\n\n/**\n * Creates a database-backed workspace snapshot store.\n *\n * @param driver - The database driver. Default: an in-memory driver.\n * @returns A workspace store backed by the supplied driver\n *\n * @example\n * ```ts\n * import { createDatabaseWorkspaceStore } from '@orkestrel/workspace'\n *\n * const store = createDatabaseWorkspaceStore()\n * ```\n */\nexport function createDatabaseWorkspaceStore(\n\tdriver: DriverInterface = createMemoryDriver(),\n): WorkspaceStoreInterface {\n\tconst columns = { id: stringShape(), snapshot: rawShape({}) }\n\tconst database = createDatabase({ driver, tables: { workspaces: columns } })\n\tconst table: TableInterface<WorkspaceSnapshotRow> = database.table('workspaces')\n\treturn new DatabaseWorkspaceStore(table)\n}\n\n/**\n * Creates an empty workspace registry.\n *\n * @param options - Default event hooks and optional durability\n * @returns A workspace manager\n *\n * @example\n * ```ts\n * import { createWorkspaceManager } from '@orkestrel/workspace'\n *\n * const manager = createWorkspaceManager()\n * manager.add()\n * ```\n */\nexport function createWorkspaceManager(\n\toptions?: WorkspaceManagerOptions,\n): WorkspaceManagerInterface {\n\treturn new WorkspaceManager(options)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../../../src/core/constants.ts","../../../src/core/errors.ts","../../../src/core/helpers.ts","../../../src/core/validators.ts","../../../src/core/workspaces/Workspace.ts","../../../src/core/workspaces/WorkspaceManager.ts","../../../src/core/workspaces/stores/DatabaseWorkspaceStore.ts","../../../src/core/workspaces/stores/MemoryWorkspaceStore.ts","../../../src/core/factories.ts"],"sourcesContent":["/**\n * Maps file extensions to language tags for text content.\n *\n * The table is frozen, and an extension it does not list falls back to `text` in\n * {@link import('./helpers.js').inferLanguage}.\n */\nexport const EXTENSION_LANGUAGES: Readonly<Record<string, string>> = Object.freeze({\n\tts: 'typescript',\n\ttsx: 'typescript',\n\tjs: 'javascript',\n\tjsx: 'javascript',\n\tmjs: 'javascript',\n\tcjs: 'javascript',\n\tjson: 'json',\n\tmd: 'markdown',\n\thtml: 'html',\n\thtm: 'html',\n\tcss: 'css',\n\tscss: 'scss',\n\tsass: 'sass',\n\tless: 'less',\n\tvue: 'vue',\n\tsvelte: 'svelte',\n\tpy: 'python',\n\trb: 'ruby',\n\trs: 'rust',\n\tgo: 'go',\n\tjava: 'java',\n\tkt: 'kotlin',\n\tswift: 'swift',\n\tc: 'c',\n\tcpp: 'cpp',\n\th: 'c',\n\thpp: 'cpp',\n\tcs: 'csharp',\n\tphp: 'php',\n\tsql: 'sql',\n\tsh: 'bash',\n\tbash: 'bash',\n\tzsh: 'bash',\n\tps1: 'powershell',\n\tyaml: 'yaml',\n\tyml: 'yaml',\n\ttoml: 'toml',\n\txml: 'xml',\n\tsvg: 'xml',\n\ttxt: 'text',\n})\n","import type { WorkspaceErrorCode } from './types.js'\nimport { isInstance } from '@orkestrel/contract'\n\n/**\n * Reports an invalid workspace edit or search operation, carrying a {@link WorkspaceErrorCode}\n * and, when the operation had one, the context it ran under.\n */\nexport class WorkspaceError extends Error {\n\treadonly code: WorkspaceErrorCode\n\treadonly context?: Readonly<Record<string, unknown>>\n\n\t/**\n\t * Creates a workspace error.\n\t *\n\t * @param code - The machine-readable failure code\n\t * @param message - The human-readable failure message\n\t * @param context - Optional values associated with the failed operation\n\t */\n\tconstructor(\n\t\tcode: WorkspaceErrorCode,\n\t\tmessage: string,\n\t\tcontext?: Readonly<Record<string, unknown>>,\n\t) {\n\t\tsuper(message)\n\t\tthis.name = 'WorkspaceError'\n\t\tthis.code = code\n\t\tif (context !== undefined) this.context = context\n\t}\n}\n\n/**\n * Narrows a caught value to a {@link WorkspaceError}.\n *\n * @remarks\n * The check is one `instanceof` test, so it stays total: every input answers `true` or `false`\n * and none throws.\n *\n * @param value - The caught value\n * @returns True if the value is a workspace error; false otherwise\n *\n * @example\n * ```ts\n * if (isWorkspaceError(error)) error.code\n * ```\n */\nexport function isWorkspaceError(value: unknown): value is WorkspaceError {\n\treturn isInstance(value, WorkspaceError)\n}\n","import type { BinaryContent, FileContent, Position, Range, TextContent } from './types.js'\nimport { EXTENSION_LANGUAGES } from './constants.js'\n\n/**\n * Infers a language tag from the final file extension.\n *\n * @param path - The file path\n * @returns The mapped language, or `text` when the extension is absent or unknown\n *\n * @example\n * ```ts\n * inferLanguage('src/main.ts') // 'typescript'\n * ```\n */\nexport function inferLanguage(path: string): string {\n\tconst dot = path.lastIndexOf('.')\n\tif (dot === -1) return 'text'\n\tconst extension = path.slice(dot + 1).toLowerCase()\n\treturn EXTENSION_LANGUAGES[extension] ?? 'text'\n}\n\n/**\n * Determines whether content is the text arm.\n *\n * @param content - The file content\n * @returns True if the content carries text and a language; false otherwise\n *\n * @example\n * ```ts\n * isText({ text: 'hello', language: 'text' }) // true\n * ```\n */\nexport function isText(content: FileContent): content is TextContent {\n\treturn 'text' in content\n}\n\n/**\n * Determines whether content is the binary arm.\n *\n * @param content - The file content\n * @returns True if the content carries a base64 string and a MIME; false otherwise\n *\n * @example\n * ```ts\n * isBinary({ base64: 'AAAA', mime: 'image/png' }) // true\n * ```\n */\nexport function isBinary(content: FileContent): content is BinaryContent {\n\treturn 'base64' in content\n}\n\n/**\n * Computes the byte size of file content.\n *\n * @param content - The content to measure\n * @returns UTF-8 bytes for text or decoded bytes for binary content\n *\n * @example\n * ```ts\n * computeSize({ text: 'café', language: 'text' }) // 5\n * ```\n */\nexport function computeSize(content: FileContent): number {\n\tif (isText(content)) return new TextEncoder().encode(content.text).length\n\treturn computeDecodedSize(content.base64)\n}\n\n/**\n * Counts the lines in file content.\n *\n * @param content - The content to inspect\n * @returns The text line count, or zero for empty text and binary content\n *\n * @example\n * ```ts\n * countLines({ text: 'a\\nb', language: 'text' }) // 2\n * ```\n */\nexport function countLines(content: FileContent): number {\n\tif (!isText(content)) return 0\n\tif (content.text.length === 0) return 0\n\tlet count = 1\n\tfor (const character of content.text) if (character === '\\n') count += 1\n\treturn count\n}\n\n/**\n * Computes the decoded byte length of a base64 string, arithmetically rather than by decoding it.\n *\n * @param base64 - The base64 string\n * @returns The decoded byte count\n *\n * @example\n * ```ts\n * computeDecodedSize('AAAA') // 3\n * ```\n */\nexport function computeDecodedSize(base64: string): number {\n\tlet padding = 0\n\tif (base64.endsWith('==')) padding = 2\n\telse if (base64.endsWith('=')) padding = 1\n\treturn Math.floor((base64.length * 3) / 4) - padding\n}\n\n/**\n * Determines whether a 1-based range is structurally valid.\n *\n * @param range - The range to inspect\n * @returns True if both positions are positive and ordered; false otherwise\n *\n * @example\n * ```ts\n * isValidRange({ start: { line: 1, column: 1 }, end: { line: 1, column: 2 } }) // true\n * ```\n */\nexport function isValidRange(range: Range): boolean {\n\tif (range.start.line < 1 || range.start.column < 1) return false\n\tif (range.end.line < 1 || range.end.column < 1) return false\n\tif (range.start.line > range.end.line) return false\n\treturn !(range.start.line === range.end.line && range.start.column > range.end.column)\n}\n\n/**\n * Clamps a position to text bounds.\n *\n * @param text - The addressed text\n * @param position - The requested position\n * @returns The clamped position\n *\n * @example\n * ```ts\n * clampPosition('ab', { line: 9, column: 9 }) // { line: 1, column: 3 }\n * ```\n */\nexport function clampPosition(text: string, position: Position): Position {\n\tconst lines = text.split('\\n')\n\tconst line = Math.max(1, Math.min(position.line, lines.length))\n\tconst lineText = lines[line - 1] ?? ''\n\tconst column = Math.max(1, Math.min(position.column, lineText.length + 1))\n\treturn { line, column }\n}\n\n/**\n * Clamps both positions in a range to text bounds.\n *\n * @param text - The addressed text\n * @param range - The requested range\n * @returns The clamped range\n *\n * @example\n * ```ts\n * clampRange('ab', { start: { line: 1, column: 1 }, end: { line: 9, column: 9 } })\n * ```\n */\nexport function clampRange(text: string, range: Range): Range {\n\treturn { start: clampPosition(text, range.start), end: clampPosition(text, range.end) }\n}\n\n/**\n * Converts a 1-based position to a zero-based string offset.\n *\n * @param text - The addressed text\n * @param position - The requested position\n * @returns The bounded string offset\n *\n * @example\n * ```ts\n * offsetAt('ab\\ncd', { line: 2, column: 1 }) // 3\n * ```\n */\nexport function offsetAt(text: string, position: Position): number {\n\tconst lines = text.split('\\n')\n\tlet offset = 0\n\tfor (let index = 0; index < position.line - 1 && index < lines.length; index += 1) {\n\t\toffset += (lines[index]?.length ?? 0) + 1\n\t}\n\toffset += position.column - 1\n\treturn Math.min(offset, text.length)\n}\n\n/**\n * Slices a clamped half-open text range.\n *\n * @param text - The source text\n * @param range - The requested range\n * @returns The ranged substring\n *\n * @example\n * ```ts\n * sliceRange('hello', { start: { line: 1, column: 1 }, end: { line: 1, column: 6 } }) // 'hello'\n * ```\n */\nexport function sliceRange(text: string, range: Range): string {\n\tconst clamped = clampRange(text, range)\n\treturn text.slice(offsetAt(text, clamped.start), offsetAt(text, clamped.end))\n}\n\n/**\n * Replaces a clamped half-open text range.\n *\n * @param text - The source text\n * @param range - The requested range\n * @param replacement - The replacement text\n * @returns The spliced text\n *\n * @example\n * ```ts\n * spliceRange('hello', { start: { line: 1, column: 1 }, end: { line: 1, column: 6 } }, 'bye')\n * ```\n */\nexport function spliceRange(text: string, range: Range, replacement: string): string {\n\tconst clamped = clampRange(text, range)\n\tconst start = offsetAt(text, clamped.start)\n\tconst end = offsetAt(text, clamped.end)\n\treturn text.slice(0, start) + replacement + text.slice(end)\n}\n\n/**\n * Assembles a nested range from four 1-based coordinates.\n *\n * @param fromLine - The start line\n * @param fromColumn - The start column\n * @param toLine - The end line\n * @param toColumn - The end column\n * @returns The assembled range without validation\n *\n * @example\n * ```ts\n * rangeOf(1, 1, 1, 2)\n * ```\n */\nexport function rangeOf(\n\tfromLine: number,\n\tfromColumn: number,\n\ttoLine: number,\n\ttoColumn: number,\n): Range {\n\treturn { start: { line: fromLine, column: fromColumn }, end: { line: toLine, column: toColumn } }\n}\n\n/**\n * Escapes regular-expression metacharacters for literal matching.\n *\n * @param value - The literal text\n * @returns The escaped regular-expression source\n *\n * @example\n * ```ts\n * escapeRegExp('a.b') // 'a\\\\.b'\n * ```\n */\nexport function escapeRegExp(value: string): string {\n\treturn value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n","import type { FileInterface, WorkspaceSnapshot } from './types.js'\nimport { arrayOf, holds, isNumber, isRecord, isString, literalOf } from '@orkestrel/contract'\n\n/**\n * Narrows an unknown value to an immutable file record.\n *\n * @param value - The value to inspect\n * @returns True if the value has the file shape; false otherwise\n *\n * @example\n * ```ts\n * isFile({ path: 'a.txt', content: { text: 'a', language: 'text' }, state: 'created', size: 1, lines: 1 })\n * ```\n */\nexport function isFile(value: unknown): value is FileInterface {\n\treturn holds(() => {\n\t\tif (!isRecord(value)) return false\n\t\tif (!isString(value.path) || !literalOf('created', 'modified')(value.state)) return false\n\t\tif (!isNumber(value.size) || !isNumber(value.lines)) return false\n\t\tif (!isRecord(value.content)) return false\n\t\tconst text = isString(value.content.text) && isString(value.content.language)\n\t\tconst binary =\n\t\t\tisString(value.content.base64) &&\n\t\t\tliteralOf('image/png', 'image/jpeg', 'image/gif', 'image/webp')(value.content.mime)\n\t\treturn text || binary\n\t})\n}\n\n/**\n * Narrows an unknown value to a workspace snapshot.\n *\n * @param value - The value read from a persistence boundary\n * @returns True if the value has the workspace snapshot shape; false otherwise\n *\n * @example\n * ```ts\n * isWorkspaceSnapshot({ id: 'work', files: [] }) // true\n * ```\n */\nexport function isWorkspaceSnapshot(value: unknown): value is WorkspaceSnapshot {\n\treturn holds(() => isRecord(value) && isString(value.id) && arrayOf(isFile)(value.files))\n}\n","import type { EmitterInterface } from '@orkestrel/emitter'\nimport type {\n\tFileInterface,\n\tRange,\n\tReadResult,\n\tReplaceResult,\n\tSearchMatch,\n\tSearchOptions,\n\tWorkspaceEventMap,\n\tWorkspaceInterface,\n\tWorkspaceOptions,\n\tWorkspaceSnapshot,\n} from '../types.js'\nimport { isArray, isRecord } from '@orkestrel/contract'\nimport { Emitter } from '@orkestrel/emitter'\nimport { WorkspaceError } from '../errors.js'\nimport { createFile } from '../factories.js'\nimport {\n\tclampRange,\n\tescapeRegExp,\n\tinferLanguage,\n\tisText,\n\tisValidRange,\n\tsliceRange,\n\tspliceRange,\n} from '../helpers.js'\n\n/**\n * Implements `WorkspaceInterface` over one insertion-ordered path map the instance owns,\n * projecting fresh arrays on every read.\n *\n * Whole-file edits create text files, ranged edits operate only on existing text files, and\n * binary files remain available through construction-time hydration. Mutations emit after the\n * file map has changed.\n *\n * @example\n * ```ts\n * import { Workspace } from '@orkestrel/workspace'\n *\n * const workspace = new Workspace()\n * workspace.write('notes.txt', 'hello')\n * workspace.append('notes.txt', ' world')\n * workspace.read('notes.txt') // 'hello world'\n * ```\n */\nexport class Workspace implements WorkspaceInterface {\n\treadonly #id: string\n\treadonly #files = new Map<string, FileInterface>()\n\treadonly #emitter: Emitter<WorkspaceEventMap>\n\n\t/**\n\t * Creates a workspace.\n\t *\n\t * @param options - Optional identity, emitter configuration, and initial files\n\t */\n\tconstructor(options?: WorkspaceOptions) {\n\t\tthis.#id = options?.id ?? crypto.randomUUID()\n\t\tthis.#emitter = new Emitter<WorkspaceEventMap>({\n\t\t\t...(options?.on === undefined ? {} : { on: options.on }),\n\t\t\t...(options?.error === undefined ? {} : { error: options.error }),\n\t\t})\n\t\tif (options?.seed) for (const file of options.seed) this.#files.set(file.path, file)\n\t}\n\n\tget id(): string {\n\t\treturn this.#id\n\t}\n\n\tget emitter(): EmitterInterface<WorkspaceEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tget count(): number {\n\t\treturn this.#files.size\n\t}\n\n\tfile(path: string): FileInterface | undefined {\n\t\treturn this.#files.get(path)\n\t}\n\n\tfiles(): readonly FileInterface[] {\n\t\treturn [...this.#files.values()]\n\t}\n\n\tread(path: string): string | undefined\n\tread(path: string, range: Range): ReadResult | undefined\n\tread(paths: readonly string[]): Readonly<Record<string, string>>\n\tread(\n\t\tpath: string | readonly string[],\n\t\trange?: Range,\n\t): string | ReadResult | undefined | Readonly<Record<string, string>> {\n\t\tif (isArray(path)) {\n\t\t\tconst result: Record<string, string> = {}\n\t\t\tfor (const one of path) {\n\t\t\t\tconst file = this.#files.get(one)\n\t\t\t\tif (file && isText(file.content)) result[one] = file.content.text\n\t\t\t}\n\t\t\treturn result\n\t\t}\n\t\tconst file = this.#files.get(path)\n\t\tif (!file) return undefined\n\t\tif (!range) return isText(file.content) ? file.content.text : undefined\n\t\tif (!isText(file.content)) {\n\t\t\tthrow new WorkspaceError('MODALITY', `Cannot read a range of a binary file: ${path}`, {\n\t\t\t\tpath,\n\t\t\t})\n\t\t}\n\t\treturn {\n\t\t\tcontent: sliceRange(file.content.text, range),\n\t\t\trange: clampRange(file.content.text, range),\n\t\t}\n\t}\n\n\thas(path: string): boolean\n\thas(paths: readonly string[]): boolean\n\thas(path: string | readonly string[]): boolean {\n\t\tif (isArray(path)) return path.every((one) => this.#files.has(one))\n\t\treturn this.#files.has(path)\n\t}\n\n\tsearch(query: string, options?: SearchOptions): readonly SearchMatch[] {\n\t\tconst pattern = this.#pattern(query, options)\n\t\tconst limit = options?.limit\n\t\tconst matches: SearchMatch[] = []\n\t\tfor (const file of this.#files.values()) {\n\t\t\tif (limit !== undefined && matches.length >= limit) break\n\t\t\tif (!isText(file.content)) continue\n\t\t\tconst lines = file.content.text.split(/\\r\\n|\\n/)\n\t\t\tfor (let index = 0; index < lines.length; index += 1) {\n\t\t\t\tif (limit !== undefined && matches.length >= limit) break\n\t\t\t\tconst lineText = lines[index] ?? ''\n\t\t\t\tpattern.lastIndex = 0\n\t\t\t\tlet hit = pattern.exec(lineText)\n\t\t\t\twhile (hit !== null) {\n\t\t\t\t\tif (limit !== undefined && matches.length >= limit) break\n\t\t\t\t\tmatches.push({\n\t\t\t\t\t\tpath: file.path,\n\t\t\t\t\t\tline: index + 1,\n\t\t\t\t\t\tcolumn: hit.index + 1,\n\t\t\t\t\t\tlength: hit[0].length,\n\t\t\t\t\t\tcontent: lineText,\n\t\t\t\t\t})\n\t\t\t\t\tif (hit[0].length === 0) pattern.lastIndex += 1\n\t\t\t\t\thit = pattern.exec(lineText)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn matches\n\t}\n\n\treplace(query: string, replacement: string, options?: SearchOptions): ReplaceResult {\n\t\tconst pattern = this.#pattern(query, options)\n\t\tconst limit = options?.limit\n\t\tlet occurrences = 0\n\t\tlet files = 0\n\t\tfor (const [path, file] of this.#files) {\n\t\t\tif (limit !== undefined && occurrences >= limit) break\n\t\t\tif (!isText(file.content)) continue\n\t\t\tconst remaining = limit === undefined ? undefined : limit - occurrences\n\t\t\tlet count = 0\n\t\t\tpattern.lastIndex = 0\n\t\t\tconst next = file.content.text.replace(pattern, (match) => {\n\t\t\t\tif (remaining !== undefined && count >= remaining) return match\n\t\t\t\tcount += 1\n\t\t\t\treturn replacement\n\t\t\t})\n\t\t\tif (count > 0) {\n\t\t\t\toccurrences += count\n\t\t\t\tfiles += 1\n\t\t\t\tthis.write(path, next)\n\t\t\t}\n\t\t}\n\t\treturn { occurrences, files }\n\t}\n\n\twrite(path: string, content: string): void\n\twrite(path: string, content: string, range: Range): void\n\twrite(files: Readonly<Record<string, string>>): void\n\twrite(path: string | Readonly<Record<string, string>>, content?: string, range?: Range): void {\n\t\tif (isRecord(path)) {\n\t\t\tfor (const [one, text] of Object.entries(path)) this.#write(one, text)\n\t\t\treturn\n\t\t}\n\t\tif (content === undefined) return\n\t\tif (!range) {\n\t\t\tthis.#write(path, content)\n\t\t\treturn\n\t\t}\n\t\tthis.#splice(path, content, range)\n\t}\n\n\tprepend(path: string, content: string): void\n\tprepend(files: Readonly<Record<string, string>>): void\n\tprepend(path: string | Readonly<Record<string, string>>, content?: string): void {\n\t\tif (isRecord(path)) {\n\t\t\tfor (const [one, text] of Object.entries(path)) this.#prepend(one, text)\n\t\t\treturn\n\t\t}\n\t\tif (content === undefined) return\n\t\tthis.#prepend(path, content)\n\t}\n\n\tappend(path: string, content: string): void\n\tappend(files: Readonly<Record<string, string>>): void\n\tappend(path: string | Readonly<Record<string, string>>, content?: string): void {\n\t\tif (isRecord(path)) {\n\t\t\tfor (const [one, text] of Object.entries(path)) this.#append(one, text)\n\t\t\treturn\n\t\t}\n\t\tif (content === undefined) return\n\t\tthis.#append(path, content)\n\t}\n\n\tmove(from: string, to: string): boolean\n\tmove(mapping: Readonly<Record<string, string>>): boolean\n\tmove(from: string | Readonly<Record<string, string>>, to?: string): boolean {\n\t\tif (isRecord(from)) {\n\t\t\tlet moved = true\n\t\t\tfor (const [one, target] of Object.entries(from)) {\n\t\t\t\tif (!this.#move(one, target)) moved = false\n\t\t\t}\n\t\t\treturn moved\n\t\t}\n\t\tif (to === undefined) return false\n\t\treturn this.#move(from, to)\n\t}\n\n\tremove(path: string): boolean\n\tremove(paths: readonly string[]): boolean\n\tremove(path: string | readonly string[]): boolean {\n\t\tif (isArray(path)) {\n\t\t\tlet removed = true\n\t\t\tfor (const one of path) {\n\t\t\t\tif (!this.#remove(one)) removed = false\n\t\t\t}\n\t\t\treturn removed\n\t\t}\n\t\treturn this.#remove(path)\n\t}\n\n\tclear(): void {\n\t\tthis.#files.clear()\n\t\tthis.#emitter.emit('clear')\n\t}\n\n\tsnapshot(): WorkspaceSnapshot {\n\t\treturn { id: this.#id, files: this.files() }\n\t}\n\n\tdestroy(): void {\n\t\tthis.#emitter.destroy()\n\t}\n\n\t#write(path: string, content: string): void {\n\t\tconst existing = this.#files.get(path)\n\t\tconst language =\n\t\t\texisting && isText(existing.content) ? existing.content.language : inferLanguage(path)\n\t\tconst file = createFile({\n\t\t\tpath,\n\t\t\tcontent: { text: content, language },\n\t\t\tstate: existing ? 'modified' : 'created',\n\t\t})\n\t\tthis.#files.set(path, file)\n\t\tthis.#emitter.emit('write', file)\n\t}\n\n\t#splice(path: string, content: string, range: Range): void {\n\t\tconst existing = this.#files.get(path)\n\t\tif (!existing) {\n\t\t\tthrow new WorkspaceError('MISSING', `Cannot splice a range of a missing file: ${path}`, {\n\t\t\t\tpath,\n\t\t\t})\n\t\t}\n\t\tif (!isText(existing.content)) {\n\t\t\tthrow new WorkspaceError('MODALITY', `Cannot splice a range of a binary file: ${path}`, {\n\t\t\t\tpath,\n\t\t\t})\n\t\t}\n\t\tif (!isValidRange(range)) {\n\t\t\tthrow new WorkspaceError('RANGE', `Invalid range for file: ${path}`, { path, range })\n\t\t}\n\t\tconst file = createFile({\n\t\t\tpath,\n\t\t\tcontent: {\n\t\t\t\ttext: spliceRange(existing.content.text, range, content),\n\t\t\t\tlanguage: existing.content.language,\n\t\t\t},\n\t\t\tstate: 'modified',\n\t\t})\n\t\tthis.#files.set(path, file)\n\t\tthis.#emitter.emit('write', file)\n\t}\n\n\t#prepend(path: string, content: string): void {\n\t\tconst existing = this.#files.get(path)\n\t\tlet text = ''\n\t\tif (existing) {\n\t\t\tif (!isText(existing.content)) {\n\t\t\t\tthrow new WorkspaceError('MODALITY', `Cannot prepend text to a binary file: ${path}`, {\n\t\t\t\t\tpath,\n\t\t\t\t})\n\t\t\t}\n\t\t\ttext = existing.content.text\n\t\t}\n\t\tthis.#write(path, content + text)\n\t}\n\n\t#append(path: string, content: string): void {\n\t\tconst existing = this.#files.get(path)\n\t\tlet text = ''\n\t\tif (existing) {\n\t\t\tif (!isText(existing.content)) {\n\t\t\t\tthrow new WorkspaceError('MODALITY', `Cannot append text to a binary file: ${path}`, {\n\t\t\t\t\tpath,\n\t\t\t\t})\n\t\t\t}\n\t\t\ttext = existing.content.text\n\t\t}\n\t\tthis.#write(path, text + content)\n\t}\n\n\t#move(from: string, to: string): boolean {\n\t\tif (from === to) return false\n\t\tconst file = this.#files.get(from)\n\t\tif (!file) return false\n\t\tconst moved = createFile({ path: to, content: file.content, state: 'modified' })\n\t\tconst entries = [...this.#files]\n\t\tthis.#files.clear()\n\t\tfor (const [path, current] of entries) {\n\t\t\tif (path === from) this.#files.set(to, moved)\n\t\t\telse if (path !== to) this.#files.set(path, current)\n\t\t}\n\t\tthis.#emitter.emit('move', from, to)\n\t\treturn true\n\t}\n\n\t#remove(path: string): boolean {\n\t\tconst removed = this.#files.delete(path)\n\t\tif (removed) this.#emitter.emit('remove', path)\n\t\treturn removed\n\t}\n\n\t#pattern(query: string, options?: SearchOptions): RegExp {\n\t\tconst source = options?.regex === true ? query : escapeRegExp(query)\n\t\tconst flags = options?.sensitive === false ? 'gi' : 'g'\n\t\ttry {\n\t\t\treturn new RegExp(source, flags)\n\t\t} catch {\n\t\t\tthrow new WorkspaceError('PATTERN', `Invalid search pattern: ${query}`, { query })\n\t\t}\n\t}\n}\n","import type { EmitterErrorHandler, EmitterHooks } from '@orkestrel/emitter'\nimport type {\n\tWorkspaceEventMap,\n\tWorkspaceInterface,\n\tWorkspaceManagerInterface,\n\tWorkspaceManagerOptions,\n\tWorkspaceOptions,\n\tWorkspaceStoreInterface,\n} from '../types.js'\nimport { isArray } from '@orkestrel/contract'\nimport { Workspace } from './Workspace.js'\n\n/**\n * Implements `WorkspaceManagerInterface` over an insertion-ordered id map and one active id\n * the instance owns, resolving `active` through that map on every read and holding no emitter.\n *\n * A supplied store adds lenient snapshot `open` and `save` operations. Event defaults flow into\n * workspaces created through the registry, while observability remains owned by each workspace.\n *\n * @example\n * ```ts\n * import { WorkspaceManager } from '@orkestrel/workspace'\n *\n * const manager = new WorkspaceManager()\n * const workspace = manager.add({ id: 'scratch' })\n * manager.active === workspace\n * ```\n */\nexport class WorkspaceManager implements WorkspaceManagerInterface {\n\treadonly #workspaces = new Map<string, WorkspaceInterface>()\n\t#active: string | undefined\n\treadonly #on: EmitterHooks<WorkspaceEventMap> | undefined\n\treadonly #error: EmitterErrorHandler | undefined\n\treadonly #store: WorkspaceStoreInterface | undefined\n\n\t/**\n\t * Creates a registry.\n\t *\n\t * @param options - Default event hooks and optional snapshot store\n\t */\n\tconstructor(options?: WorkspaceManagerOptions) {\n\t\tthis.#on = options?.on\n\t\tthis.#error = options?.error\n\t\tthis.#store = options?.store\n\t}\n\n\tget count(): number {\n\t\treturn this.#workspaces.size\n\t}\n\n\tget active(): WorkspaceInterface | undefined {\n\t\treturn this.#active === undefined ? undefined : this.#workspaces.get(this.#active)\n\t}\n\n\tworkspace(id: string): WorkspaceInterface | undefined {\n\t\treturn this.#workspaces.get(id)\n\t}\n\n\tworkspaces(): readonly WorkspaceInterface[] {\n\t\treturn [...this.#workspaces.values()]\n\t}\n\n\tadd(options?: WorkspaceOptions): WorkspaceInterface {\n\t\tconst on = options?.on ?? this.#on\n\t\tconst error = options?.error ?? this.#error\n\t\tconst workspace = new Workspace({\n\t\t\t...(options?.id === undefined ? {} : { id: options.id }),\n\t\t\t...(on === undefined ? {} : { on }),\n\t\t\t...(error === undefined ? {} : { error }),\n\t\t\t...(options?.seed === undefined ? {} : { seed: options.seed }),\n\t\t})\n\t\tthis.#workspaces.set(workspace.id, workspace)\n\t\tif (this.#active === undefined) this.#active = workspace.id\n\t\treturn workspace\n\t}\n\n\tswitch(id: string): WorkspaceInterface | undefined {\n\t\tconst workspace = this.#workspaces.get(id)\n\t\tif (workspace === undefined) return undefined\n\t\tthis.#active = id\n\t\treturn workspace\n\t}\n\n\tasync open(id: string): Promise<WorkspaceInterface | undefined> {\n\t\tconst existing = this.#workspaces.get(id)\n\t\tif (existing !== undefined) {\n\t\t\tthis.#active = id\n\t\t\treturn existing\n\t\t}\n\t\tif (this.#store === undefined) return undefined\n\t\tconst snapshot = await this.#store.get(id)\n\t\tif (snapshot === undefined) return undefined\n\t\tconst workspace = this.add({ id, seed: snapshot.files })\n\t\tthis.#active = workspace.id\n\t\treturn workspace\n\t}\n\n\tasync save(id: string): Promise<boolean> {\n\t\tconst workspace = this.#workspaces.get(id)\n\t\tif (this.#store === undefined || workspace === undefined) return false\n\t\tawait this.#store.set(workspace.snapshot())\n\t\treturn true\n\t}\n\n\tremove(id: string): boolean\n\tremove(ids: readonly string[]): boolean\n\tremove(ids: string | readonly string[]): boolean {\n\t\tif (isArray(ids)) {\n\t\t\tlet removed = true\n\t\t\tfor (const id of ids) {\n\t\t\t\tif (!this.#drop(id)) removed = false\n\t\t\t}\n\t\t\treturn removed\n\t\t}\n\t\treturn this.#drop(ids)\n\t}\n\n\tclear(): void {\n\t\tfor (const workspace of this.#workspaces.values()) workspace.destroy()\n\t\tthis.#workspaces.clear()\n\t\tthis.#active = undefined\n\t}\n\n\t#drop(id: string): boolean {\n\t\tconst workspace = this.#workspaces.get(id)\n\t\tif (workspace === undefined) return false\n\t\tthis.#workspaces.delete(id)\n\t\tworkspace.destroy()\n\t\tif (this.#active === id) this.#active = undefined\n\t\treturn true\n\t}\n}\n","import type {\n\tWorkspaceSnapshot,\n\tWorkspaceSnapshotRow,\n\tWorkspaceStoreInterface,\n} from '../../types.js'\nimport type { TableInterface } from '@orkestrel/database'\nimport { isWorkspaceSnapshot } from '../../validators.js'\n\n/**\n * Persists workspace snapshots in a database table.\n *\n * Snapshots occupy one opaque column and are narrowed when read back from the storage boundary.\n *\n * @example\n * ```ts\n * import { rawShape, stringShape } from '@orkestrel/contract'\n * import { createDatabase, createMemoryDriver } from '@orkestrel/database'\n * import { DatabaseWorkspaceStore } from '@orkestrel/workspace'\n *\n * const database = createDatabase({\n * \tdriver: createMemoryDriver(),\n * \ttables: { workspaces: { id: stringShape(), snapshot: rawShape({}) } },\n * })\n * const store = new DatabaseWorkspaceStore(database.table('workspaces'))\n * ```\n */\nexport class DatabaseWorkspaceStore implements WorkspaceStoreInterface {\n\treadonly #table: TableInterface<WorkspaceSnapshotRow>\n\n\t/**\n\t * Wraps a workspace snapshot table.\n\t *\n\t * @param table - The table keyed by workspace identifier\n\t */\n\tconstructor(table: TableInterface<WorkspaceSnapshotRow>) {\n\t\tthis.#table = table\n\t}\n\n\tasync get(id: string): Promise<WorkspaceSnapshot | undefined> {\n\t\tconst row = await this.#table.get(id)\n\t\tif (row === undefined) return undefined\n\t\treturn isWorkspaceSnapshot(row.snapshot) ? row.snapshot : undefined\n\t}\n\n\tasync set(snapshot: WorkspaceSnapshot): Promise<void> {\n\t\tawait this.#table.set({ id: snapshot.id, snapshot })\n\t}\n\n\tasync delete(id: string): Promise<void> {\n\t\tawait this.#table.remove(id)\n\t}\n}\n","import type { WorkspaceSnapshot, WorkspaceStoreInterface } from '../../types.js'\n\n/**\n * Holds workspace snapshots in the current process.\n *\n * @example\n * ```ts\n * import { MemoryWorkspaceStore } from '@orkestrel/workspace'\n *\n * const store = new MemoryWorkspaceStore()\n * ```\n */\nexport class MemoryWorkspaceStore implements WorkspaceStoreInterface {\n\treadonly #snapshots = new Map<string, WorkspaceSnapshot>()\n\n\tget(id: string): Promise<WorkspaceSnapshot | undefined> {\n\t\treturn Promise.resolve(this.#snapshots.get(id))\n\t}\n\n\tset(snapshot: WorkspaceSnapshot): Promise<void> {\n\t\tthis.#snapshots.set(snapshot.id, snapshot)\n\t\treturn Promise.resolve()\n\t}\n\n\tdelete(id: string): Promise<void> {\n\t\tthis.#snapshots.delete(id)\n\t\treturn Promise.resolve()\n\t}\n}\n","import type {\n\tBinaryContent,\n\tBinaryMIME,\n\tFileInput,\n\tFileInterface,\n\tTextContent,\n\tWorkspaceInterface,\n\tWorkspaceManagerInterface,\n\tWorkspaceManagerOptions,\n\tWorkspaceOptions,\n\tWorkspaceSnapshotRow,\n\tWorkspaceStoreInterface,\n} from './types.js'\nimport type { DriverInterface, TableInterface } from '@orkestrel/database'\nimport { rawShape, stringShape } from '@orkestrel/contract'\nimport { createDatabase, createMemoryDriver } from '@orkestrel/database'\nimport { computeSize, countLines } from './helpers.js'\nimport { Workspace } from './workspaces/Workspace.js'\nimport { WorkspaceManager } from './workspaces/WorkspaceManager.js'\nimport { DatabaseWorkspaceStore } from './workspaces/stores/DatabaseWorkspaceStore.js'\nimport { MemoryWorkspaceStore } from './workspaces/stores/MemoryWorkspaceStore.js'\n\n/**\n * Creates an immutable file with derived size and line counts.\n *\n * @param input - The file path, content, and optional state\n * @returns A frozen file record\n *\n * @example Files and content\n * ```ts\n * import {\n * \tcomputeSize,\n * \tcountLines,\n * \tcreateBinaryContent,\n * \tcreateFile,\n * \tcreateTextContent,\n * \tinferLanguage,\n * \tisBinary,\n * \tisText,\n * } from '@orkestrel/workspace'\n *\n * const note = createFile({\n * \tpath: 'notes.md',\n * \tcontent: createTextContent('# Title\\nBody', inferLanguage('notes.md')), // 'markdown'\n * })\n *\n * note.size // 12 — UTF-8 bytes, through computeSize\n * note.lines // 2 — through countLines\n * note.state // 'created'\n * isText(note.content) // true\n *\n * const icon = createFile({ path: 'icon.png', content: createBinaryContent('AAAA', 'image/png') })\n * isBinary(icon.content) // true\n * icon.size // 3 — decoded base64 bytes, through computeDecodedSize\n * ```\n */\nexport function createFile(input: FileInput): FileInterface {\n\treturn Object.freeze({\n\t\tpath: input.path,\n\t\tcontent: input.content,\n\t\tstate: input.state ?? 'created',\n\t\tsize: computeSize(input.content),\n\t\tlines: countLines(input.content),\n\t})\n}\n\n/**\n * Creates the text arm of {@link FileContent}, returned as {@link TextContent} rather than as\n * the whole union.\n *\n * @param text - The text body\n * @param language - The language tag\n * @returns Text file content\n *\n * @example\n * ```ts\n * import { createTextContent } from '@orkestrel/workspace'\n *\n * createTextContent('hello', 'text')\n * ```\n */\nexport function createTextContent(text: string, language: string): TextContent {\n\treturn { text, language }\n}\n\n/**\n * Creates the binary arm of {@link FileContent}, returned as {@link BinaryContent} rather than\n * as the whole union.\n *\n * @param base64 - The base64 payload\n * @param mime - The binary MIME\n * @returns Binary file content\n *\n * @example\n * ```ts\n * import { createBinaryContent } from '@orkestrel/workspace'\n *\n * createBinaryContent('AAAA', 'image/png')\n * ```\n */\nexport function createBinaryContent(base64: string, mime: BinaryMIME): BinaryContent {\n\treturn { base64, mime }\n}\n\n/**\n * Creates a workspace with the same identity, emitter, and seed options the constructor takes.\n *\n * @param options - Optional identity, emitter configuration, and initial files\n * @returns A working workspace\n *\n * @example\n * ```ts\n * import { createWorkspace } from '@orkestrel/workspace'\n *\n * const workspace = createWorkspace()\n * workspace.write('a.txt', 'hello')\n * ```\n */\nexport function createWorkspace(options?: WorkspaceOptions): WorkspaceInterface {\n\treturn new Workspace(options)\n}\n\n/**\n * Creates an in-memory workspace snapshot store.\n *\n * @returns A process-local workspace store\n *\n * @example\n * ```ts\n * import { createMemoryWorkspaceStore } from '@orkestrel/workspace'\n *\n * const store = createMemoryWorkspaceStore()\n * ```\n */\nexport function createMemoryWorkspaceStore(): WorkspaceStoreInterface {\n\treturn new MemoryWorkspaceStore()\n}\n\n/**\n * Creates a database-backed workspace snapshot store, over an in-memory driver when the caller\n * supplies none.\n *\n * @param driver - The database driver. Default: an in-memory driver.\n * @returns A workspace store backed by the supplied driver\n *\n * @example\n * ```ts\n * import { createDatabaseWorkspaceStore } from '@orkestrel/workspace'\n *\n * const store = createDatabaseWorkspaceStore()\n * ```\n */\nexport function createDatabaseWorkspaceStore(\n\tdriver: DriverInterface = createMemoryDriver(),\n): WorkspaceStoreInterface {\n\tconst columns = { id: stringShape(), snapshot: rawShape({}) }\n\tconst database = createDatabase({ driver, tables: { workspaces: columns } })\n\tconst table: TableInterface<WorkspaceSnapshotRow> = database.table('workspaces')\n\treturn new DatabaseWorkspaceStore(table)\n}\n\n/**\n * Creates an empty workspace registry.\n *\n * @param options - Default event hooks and optional durability\n * @returns A workspace manager\n *\n * @example\n * ```ts\n * import { createWorkspaceManager } from '@orkestrel/workspace'\n *\n * const manager = createWorkspaceManager()\n * manager.add()\n * ```\n */\nexport function createWorkspaceManager(\n\toptions?: WorkspaceManagerOptions,\n): WorkspaceManagerInterface {\n\treturn new WorkspaceManager(options)\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { DriverInterface } from '@orkestrel/database';
|
|
2
|
-
import { EmitterErrorHandler } from '@orkestrel/emitter';
|
|
3
|
-
import { EmitterHooks } from '@orkestrel/emitter';
|
|
4
|
-
import { EmitterInterface } from '@orkestrel/emitter';
|
|
5
|
-
import { TableInterface } from '@orkestrel/database';
|
|
1
|
+
import type { DriverInterface } from '@orkestrel/database';
|
|
2
|
+
import type { EmitterErrorHandler } from '@orkestrel/emitter';
|
|
3
|
+
import type { EmitterHooks } from '@orkestrel/emitter';
|
|
4
|
+
import type { EmitterInterface } from '@orkestrel/emitter';
|
|
5
|
+
import type { TableInterface } from '@orkestrel/database';
|
|
6
6
|
|
|
7
7
|
/** Holds the binary arm of a file's immutable content: a base64 payload and its MIME. */
|
|
8
8
|
export declare interface BinaryContent {
|
|
@@ -42,7 +42,7 @@ export declare function clampPosition(text: string, position: Position): Positio
|
|
|
42
42
|
export declare function clampRange(text: string, range: Range): Range;
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
|
-
* Computes the decoded byte length of a base64 string.
|
|
45
|
+
* Computes the decoded byte length of a base64 string, arithmetically rather than by decoding it.
|
|
46
46
|
*
|
|
47
47
|
* @param base64 - The base64 string
|
|
48
48
|
* @returns The decoded byte count
|
|
@@ -81,7 +81,8 @@ export declare function computeSize(content: FileContent): number;
|
|
|
81
81
|
export declare function countLines(content: FileContent): number;
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
|
-
* Creates the binary arm of {@link FileContent}
|
|
84
|
+
* Creates the binary arm of {@link FileContent}, returned as {@link BinaryContent} rather than
|
|
85
|
+
* as the whole union.
|
|
85
86
|
*
|
|
86
87
|
* @param base64 - The base64 payload
|
|
87
88
|
* @param mime - The binary MIME
|
|
@@ -97,7 +98,8 @@ export declare function countLines(content: FileContent): number;
|
|
|
97
98
|
export declare function createBinaryContent(base64: string, mime: BinaryMIME): BinaryContent;
|
|
98
99
|
|
|
99
100
|
/**
|
|
100
|
-
* Creates a database-backed workspace snapshot store
|
|
101
|
+
* Creates a database-backed workspace snapshot store, over an in-memory driver when the caller
|
|
102
|
+
* supplies none.
|
|
101
103
|
*
|
|
102
104
|
* @param driver - The database driver. Default: an in-memory driver.
|
|
103
105
|
* @returns A workspace store backed by the supplied driver
|
|
@@ -117,11 +119,32 @@ export declare function createDatabaseWorkspaceStore(driver?: DriverInterface):
|
|
|
117
119
|
* @param input - The file path, content, and optional state
|
|
118
120
|
* @returns A frozen file record
|
|
119
121
|
*
|
|
120
|
-
* @example
|
|
122
|
+
* @example Files and content
|
|
121
123
|
* ```ts
|
|
122
|
-
* import {
|
|
124
|
+
* import {
|
|
125
|
+
* computeSize,
|
|
126
|
+
* countLines,
|
|
127
|
+
* createBinaryContent,
|
|
128
|
+
* createFile,
|
|
129
|
+
* createTextContent,
|
|
130
|
+
* inferLanguage,
|
|
131
|
+
* isBinary,
|
|
132
|
+
* isText,
|
|
133
|
+
* } from '@orkestrel/workspace'
|
|
134
|
+
*
|
|
135
|
+
* const note = createFile({
|
|
136
|
+
* path: 'notes.md',
|
|
137
|
+
* content: createTextContent('# Title\nBody', inferLanguage('notes.md')), // 'markdown'
|
|
138
|
+
* })
|
|
139
|
+
*
|
|
140
|
+
* note.size // 12 — UTF-8 bytes, through computeSize
|
|
141
|
+
* note.lines // 2 — through countLines
|
|
142
|
+
* note.state // 'created'
|
|
143
|
+
* isText(note.content) // true
|
|
123
144
|
*
|
|
124
|
-
* createFile({ path: '
|
|
145
|
+
* const icon = createFile({ path: 'icon.png', content: createBinaryContent('AAAA', 'image/png') })
|
|
146
|
+
* isBinary(icon.content) // true
|
|
147
|
+
* icon.size // 3 — decoded base64 bytes, through computeDecodedSize
|
|
125
148
|
* ```
|
|
126
149
|
*/
|
|
127
150
|
export declare function createFile(input: FileInput): FileInterface;
|
|
@@ -141,7 +164,8 @@ export declare function createFile(input: FileInput): FileInterface;
|
|
|
141
164
|
export declare function createMemoryWorkspaceStore(): WorkspaceStoreInterface;
|
|
142
165
|
|
|
143
166
|
/**
|
|
144
|
-
* Creates the text arm of {@link FileContent}
|
|
167
|
+
* Creates the text arm of {@link FileContent}, returned as {@link TextContent} rather than as
|
|
168
|
+
* the whole union.
|
|
145
169
|
*
|
|
146
170
|
* @param text - The text body
|
|
147
171
|
* @param language - The language tag
|
|
@@ -157,7 +181,7 @@ export declare function createMemoryWorkspaceStore(): WorkspaceStoreInterface;
|
|
|
157
181
|
export declare function createTextContent(text: string, language: string): TextContent;
|
|
158
182
|
|
|
159
183
|
/**
|
|
160
|
-
* Creates a workspace.
|
|
184
|
+
* Creates a workspace with the same identity, emitter, and seed options the constructor takes.
|
|
161
185
|
*
|
|
162
186
|
* @param options - Optional identity, emitter configuration, and initial files
|
|
163
187
|
* @returns A working workspace
|
|
@@ -235,18 +259,21 @@ export declare function escapeRegExp(value: string): string;
|
|
|
235
259
|
/**
|
|
236
260
|
* Maps file extensions to language tags for text content.
|
|
237
261
|
*
|
|
238
|
-
*
|
|
262
|
+
* The table is frozen, and an extension it does not list falls back to `text` in
|
|
239
263
|
* {@link import('./helpers.js').inferLanguage}.
|
|
240
264
|
*/
|
|
241
265
|
export declare const EXTENSION_LANGUAGES: Readonly<Record<string, string>>;
|
|
242
266
|
|
|
243
267
|
/**
|
|
244
268
|
* Holds a file's immutable content: either text with a language tag or a base64 string with a
|
|
245
|
-
* MIME.
|
|
269
|
+
* MIME. The union carries no discriminant field, so a caller narrows it with a guard.
|
|
246
270
|
*/
|
|
247
271
|
export declare type FileContent = TextContent | BinaryContent;
|
|
248
272
|
|
|
249
|
-
/**
|
|
273
|
+
/**
|
|
274
|
+
* Carries the caller-supplied values used to create an immutable file. The byte size and the line
|
|
275
|
+
* count are derived rather than supplied.
|
|
276
|
+
*/
|
|
250
277
|
export declare interface FileInput {
|
|
251
278
|
readonly path: string;
|
|
252
279
|
readonly content: FileContent;
|
|
@@ -262,7 +289,10 @@ export declare interface FileInterface {
|
|
|
262
289
|
readonly lines: number;
|
|
263
290
|
}
|
|
264
291
|
|
|
265
|
-
/**
|
|
292
|
+
/**
|
|
293
|
+
* Names the edit state of an immutable file value: `created` for the first write to a path and
|
|
294
|
+
* `modified` for every later edit of that path.
|
|
295
|
+
*/
|
|
266
296
|
export declare type FileState = 'created' | 'modified';
|
|
267
297
|
|
|
268
298
|
/**
|
|
@@ -279,7 +309,7 @@ export declare type FileState = 'created' | 'modified';
|
|
|
279
309
|
export declare function inferLanguage(path: string): string;
|
|
280
310
|
|
|
281
311
|
/**
|
|
282
|
-
*
|
|
312
|
+
* Determines whether content is the binary arm.
|
|
283
313
|
*
|
|
284
314
|
* @param content - The file content
|
|
285
315
|
* @returns True if the content carries a base64 string and a MIME; false otherwise
|
|
@@ -333,6 +363,10 @@ export declare function isValidRange(range: Range): boolean;
|
|
|
333
363
|
/**
|
|
334
364
|
* Narrows a caught value to a {@link WorkspaceError}.
|
|
335
365
|
*
|
|
366
|
+
* @remarks
|
|
367
|
+
* The check is one `instanceof` test, so it stays total: every input answers `true` or `false`
|
|
368
|
+
* and none throws.
|
|
369
|
+
*
|
|
336
370
|
* @param value - The caught value
|
|
337
371
|
* @returns True if the value is a workspace error; false otherwise
|
|
338
372
|
*
|
|
@@ -421,7 +455,7 @@ export declare interface ReadResult {
|
|
|
421
455
|
readonly range: Range;
|
|
422
456
|
}
|
|
423
457
|
|
|
424
|
-
/** Carries the tallies produced
|
|
458
|
+
/** Carries the tallies a replacement produced: the occurrences replaced and the files changed. */
|
|
425
459
|
export declare interface ReplaceResult {
|
|
426
460
|
readonly occurrences: number;
|
|
427
461
|
readonly files: number;
|
|
@@ -487,11 +521,12 @@ export declare interface TextContent {
|
|
|
487
521
|
}
|
|
488
522
|
|
|
489
523
|
/**
|
|
490
|
-
*
|
|
524
|
+
* Implements `WorkspaceInterface` over one insertion-ordered path map the instance owns,
|
|
525
|
+
* projecting fresh arrays on every read.
|
|
491
526
|
*
|
|
492
527
|
* Whole-file edits create text files, ranged edits operate only on existing text files, and
|
|
493
528
|
* binary files remain available through construction-time hydration. Mutations emit after the
|
|
494
|
-
*
|
|
529
|
+
* file map has changed.
|
|
495
530
|
*
|
|
496
531
|
* @example
|
|
497
532
|
* ```ts
|
|
@@ -539,7 +574,10 @@ export declare class Workspace implements WorkspaceInterface {
|
|
|
539
574
|
destroy(): void;
|
|
540
575
|
}
|
|
541
576
|
|
|
542
|
-
/**
|
|
577
|
+
/**
|
|
578
|
+
* Reports an invalid workspace edit or search operation, carrying a {@link WorkspaceErrorCode}
|
|
579
|
+
* and, when the operation had one, the context it ran under.
|
|
580
|
+
*/
|
|
543
581
|
export declare class WorkspaceError extends Error {
|
|
544
582
|
readonly code: WorkspaceErrorCode;
|
|
545
583
|
readonly context?: Readonly<Record<string, unknown>>;
|
|
@@ -736,7 +774,8 @@ export declare interface WorkspaceInterface {
|
|
|
736
774
|
}
|
|
737
775
|
|
|
738
776
|
/**
|
|
739
|
-
*
|
|
777
|
+
* Implements `WorkspaceManagerInterface` over an insertion-ordered id map and one active id
|
|
778
|
+
* the instance owns, resolving `active` through that map on every read and holding no emitter.
|
|
740
779
|
*
|
|
741
780
|
* A supplied store adds lenient snapshot `open` and `save` operations. Event defaults flow into
|
|
742
781
|
* workspaces created through the registry, while observability remains owned by each workspace.
|
|
@@ -885,7 +924,7 @@ export declare interface WorkspaceSnapshotRow {
|
|
|
885
924
|
/** Persists workspace snapshots through an asynchronous point-access contract. */
|
|
886
925
|
export declare interface WorkspaceStoreInterface {
|
|
887
926
|
/**
|
|
888
|
-
* Resolves a snapshot.
|
|
927
|
+
* Resolves a snapshot by workspace id.
|
|
889
928
|
*
|
|
890
929
|
* @param id - The workspace identifier
|
|
891
930
|
* @returns The snapshot, or `undefined` when absent
|