@orkestrel/workspace 0.0.6 → 0.0.8

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.
@@ -3,9 +3,9 @@ import { createDatabase, createMemoryDriver } from "@orkestrel/database";
3
3
  import { Emitter } from "@orkestrel/emitter";
4
4
  //#region src/core/constants.ts
5
5
  /**
6
- * File extensions mapped to language tags for text content.
6
+ * Maps file extensions to language tags for text content.
7
7
  *
8
- * Unknown extensions intentionally fall back to `text` in
8
+ * The table is frozen, and an extension it does not list falls back to `text` in
9
9
  * {@link import('./helpers.js').inferLanguage}.
10
10
  */
11
11
  var EXTENSION_LANGUAGES = Object.freeze({
@@ -52,12 +52,15 @@ var EXTENSION_LANGUAGES = Object.freeze({
52
52
  });
53
53
  //#endregion
54
54
  //#region src/core/errors.ts
55
- /** An invalid workspace edit or search operation. */
55
+ /**
56
+ * Reports an invalid workspace edit or search operation, carrying a {@link WorkspaceErrorCode}
57
+ * and, when the operation had one, the context it ran under.
58
+ */
56
59
  var WorkspaceError = class extends Error {
57
60
  code;
58
61
  context;
59
62
  /**
60
- * Create a workspace error.
63
+ * Creates a workspace error.
61
64
  *
62
65
  * @param code - The machine-readable failure code
63
66
  * @param message - The human-readable failure message
@@ -71,10 +74,14 @@ var WorkspaceError = class extends Error {
71
74
  }
72
75
  };
73
76
  /**
74
- * Narrow a caught value to a {@link WorkspaceError}.
77
+ * Narrows a caught value to a {@link WorkspaceError}.
78
+ *
79
+ * @remarks
80
+ * The check is one `instanceof` test, so it stays total: every input answers `true` or `false`
81
+ * and none throws.
75
82
  *
76
83
  * @param value - The caught value
77
- * @returns Whether the value is a workspace error
84
+ * @returns True if the value is a workspace error; false otherwise
78
85
  *
79
86
  * @example
80
87
  * ```ts
@@ -87,7 +94,7 @@ function isWorkspaceError(value) {
87
94
  //#endregion
88
95
  //#region src/core/helpers.ts
89
96
  /**
90
- * Infer a language tag from the final file extension.
97
+ * Infers a language tag from the final file extension.
91
98
  *
92
99
  * @param path - The file path
93
100
  * @returns The mapped language, or `text` when the extension is absent or unknown
@@ -103,10 +110,10 @@ function inferLanguage(path) {
103
110
  return EXTENSION_LANGUAGES[path.slice(dot + 1).toLowerCase()] ?? "text";
104
111
  }
105
112
  /**
106
- * Determine whether content is the text arm.
113
+ * Determines whether content is the text arm.
107
114
  *
108
115
  * @param content - The file content
109
- * @returns Whether the content carries text and a language
116
+ * @returns True if the content carries text and a language; false otherwise
110
117
  *
111
118
  * @example
112
119
  * ```ts
@@ -117,57 +124,21 @@ function isText(content) {
117
124
  return "text" in content;
118
125
  }
119
126
  /**
120
- * Determine whether content is the binary arm.
127
+ * Determines whether content is the binary arm.
121
128
  *
122
129
  * @param content - The file content
123
- * @returns Whether the content carries base64 data and a MIME
130
+ * @returns True if the content carries a base64 string and a MIME; false otherwise
124
131
  *
125
132
  * @example
126
133
  * ```ts
127
- * isBinary({ data: 'AAAA', mime: 'image/png' }) // true
134
+ * isBinary({ base64: 'AAAA', mime: 'image/png' }) // true
128
135
  * ```
129
136
  */
130
137
  function isBinary(content) {
131
- return "data" in content;
132
- }
133
- /**
134
- * Narrow an unknown value to an immutable file record.
135
- *
136
- * @param value - The value to inspect
137
- * @returns Whether the value has the file shape
138
- *
139
- * @example
140
- * ```ts
141
- * isFile({ path: 'a.txt', content: { text: 'a', language: 'text' }, state: 'created', size: 1, lines: 1 })
142
- * ```
143
- */
144
- function isFile(value) {
145
- return holds(() => {
146
- if (!isRecord(value)) return false;
147
- if (!isString(value.path) || !literalOf("created", "modified")(value.state)) return false;
148
- if (!isNumber(value.size) || !isNumber(value.lines)) return false;
149
- if (!isRecord(value.content)) return false;
150
- const text = isString(value.content.text) && isString(value.content.language);
151
- const binary = isString(value.content.data) && literalOf("image/png", "image/jpeg", "image/gif", "image/webp")(value.content.mime);
152
- return text || binary;
153
- });
154
- }
155
- /**
156
- * Narrow an unknown value to a workspace snapshot.
157
- *
158
- * @param value - The value read from a persistence boundary
159
- * @returns Whether the value has the workspace snapshot shape
160
- *
161
- * @example
162
- * ```ts
163
- * isWorkspaceSnapshot({ id: 'work', files: [] }) // true
164
- * ```
165
- */
166
- function isWorkspaceSnapshot(value) {
167
- return holds(() => isRecord(value) && isString(value.id) && arrayOf(isFile)(value.files));
138
+ return "base64" in content;
168
139
  }
169
140
  /**
170
- * Compute the byte size of file content.
141
+ * Computes the byte size of file content.
171
142
  *
172
143
  * @param content - The content to measure
173
144
  * @returns UTF-8 bytes for text or decoded bytes for binary content
@@ -179,10 +150,10 @@ function isWorkspaceSnapshot(value) {
179
150
  */
180
151
  function computeSize(content) {
181
152
  if (isText(content)) return new TextEncoder().encode(content.text).length;
182
- return decodedSize(content.data);
153
+ return computeDecodedSize(content.base64);
183
154
  }
184
155
  /**
185
- * Count the lines in file content.
156
+ * Counts the lines in file content.
186
157
  *
187
158
  * @param content - The content to inspect
188
159
  * @returns The text line count, or zero for empty text and binary content
@@ -200,27 +171,27 @@ function countLines(content) {
200
171
  return count;
201
172
  }
202
173
  /**
203
- * Compute the decoded byte length of a base64 string.
174
+ * Computes the decoded byte length of a base64 string, arithmetically rather than by decoding it.
204
175
  *
205
- * @param base64 - The base64 data
176
+ * @param base64 - The base64 string
206
177
  * @returns The decoded byte count
207
178
  *
208
179
  * @example
209
180
  * ```ts
210
- * decodedSize('AAAA') // 3
181
+ * computeDecodedSize('AAAA') // 3
211
182
  * ```
212
183
  */
213
- function decodedSize(base64) {
184
+ function computeDecodedSize(base64) {
214
185
  let padding = 0;
215
186
  if (base64.endsWith("==")) padding = 2;
216
187
  else if (base64.endsWith("=")) padding = 1;
217
188
  return Math.floor(base64.length * 3 / 4) - padding;
218
189
  }
219
190
  /**
220
- * Determine whether a 1-based range is structurally valid.
191
+ * Determines whether a 1-based range is structurally valid.
221
192
  *
222
193
  * @param range - The range to inspect
223
- * @returns Whether both positions are positive and ordered
194
+ * @returns True if both positions are positive and ordered; false otherwise
224
195
  *
225
196
  * @example
226
197
  * ```ts
@@ -234,7 +205,7 @@ function isValidRange(range) {
234
205
  return !(range.start.line === range.end.line && range.start.column > range.end.column);
235
206
  }
236
207
  /**
237
- * Clamp a position to text bounds.
208
+ * Clamps a position to text bounds.
238
209
  *
239
210
  * @param text - The addressed text
240
211
  * @param position - The requested position
@@ -255,7 +226,7 @@ function clampPosition(text, position) {
255
226
  };
256
227
  }
257
228
  /**
258
- * Clamp both positions in a range to text bounds.
229
+ * Clamps both positions in a range to text bounds.
259
230
  *
260
231
  * @param text - The addressed text
261
232
  * @param range - The requested range
@@ -273,7 +244,7 @@ function clampRange(text, range) {
273
244
  };
274
245
  }
275
246
  /**
276
- * Convert a 1-based position to a zero-based string offset.
247
+ * Converts a 1-based position to a zero-based string offset.
277
248
  *
278
249
  * @param text - The addressed text
279
250
  * @param position - The requested position
@@ -292,7 +263,7 @@ function offsetAt(text, position) {
292
263
  return Math.min(offset, text.length);
293
264
  }
294
265
  /**
295
- * Slice a clamped half-open text range.
266
+ * Slices a clamped half-open text range.
296
267
  *
297
268
  * @param text - The source text
298
269
  * @param range - The requested range
@@ -308,7 +279,7 @@ function sliceRange(text, range) {
308
279
  return text.slice(offsetAt(text, clamped.start), offsetAt(text, clamped.end));
309
280
  }
310
281
  /**
311
- * Replace a clamped half-open text range.
282
+ * Replaces a clamped half-open text range.
312
283
  *
313
284
  * @param text - The source text
314
285
  * @param range - The requested range
@@ -327,7 +298,7 @@ function spliceRange(text, range, replacement) {
327
298
  return text.slice(0, start) + replacement + text.slice(end);
328
299
  }
329
300
  /**
330
- * Assemble a nested range from four 1-based coordinates.
301
+ * Assembles a nested range from four 1-based coordinates.
331
302
  *
332
303
  * @param fromLine - The start line
333
304
  * @param fromColumn - The start column
@@ -353,7 +324,7 @@ function rangeOf(fromLine, fromColumn, toLine, toColumn) {
353
324
  };
354
325
  }
355
326
  /**
356
- * Escape regular-expression metacharacters for literal matching.
327
+ * Escapes regular-expression metacharacters for literal matching.
357
328
  *
358
329
  * @param value - The literal text
359
330
  * @returns The escaped regular-expression source
@@ -367,13 +338,52 @@ function escapeRegExp(value) {
367
338
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
368
339
  }
369
340
  //#endregion
341
+ //#region src/core/validators.ts
342
+ /**
343
+ * Narrows an unknown value to an immutable file record.
344
+ *
345
+ * @param value - The value to inspect
346
+ * @returns True if the value has the file shape; false otherwise
347
+ *
348
+ * @example
349
+ * ```ts
350
+ * isFile({ path: 'a.txt', content: { text: 'a', language: 'text' }, state: 'created', size: 1, lines: 1 })
351
+ * ```
352
+ */
353
+ function isFile(value) {
354
+ return holds(() => {
355
+ if (!isRecord(value)) return false;
356
+ if (!isString(value.path) || !literalOf("created", "modified")(value.state)) return false;
357
+ if (!isNumber(value.size) || !isNumber(value.lines)) return false;
358
+ if (!isRecord(value.content)) return false;
359
+ const text = isString(value.content.text) && isString(value.content.language);
360
+ const binary = isString(value.content.base64) && literalOf("image/png", "image/jpeg", "image/gif", "image/webp")(value.content.mime);
361
+ return text || binary;
362
+ });
363
+ }
364
+ /**
365
+ * Narrows an unknown value to a workspace snapshot.
366
+ *
367
+ * @param value - The value read from a persistence boundary
368
+ * @returns True if the value has the workspace snapshot shape; false otherwise
369
+ *
370
+ * @example
371
+ * ```ts
372
+ * isWorkspaceSnapshot({ id: 'work', files: [] }) // true
373
+ * ```
374
+ */
375
+ function isWorkspaceSnapshot(value) {
376
+ return holds(() => isRecord(value) && isString(value.id) && arrayOf(isFile)(value.files));
377
+ }
378
+ //#endregion
370
379
  //#region src/core/workspaces/Workspace.ts
371
380
  /**
372
- * A mutable path-keyed editing surface over immutable files.
381
+ * Implements `WorkspaceInterface` over one insertion-ordered path map the instance owns,
382
+ * projecting fresh arrays on every read.
373
383
  *
374
384
  * Whole-file edits create text files, ranged edits operate only on existing text files, and
375
385
  * binary files remain available through construction-time hydration. Mutations emit after the
376
- * registry has changed.
386
+ * file map has changed.
377
387
  *
378
388
  * @example
379
389
  * ```ts
@@ -390,7 +400,7 @@ var Workspace = class {
390
400
  #files = /* @__PURE__ */ new Map();
391
401
  #emitter;
392
402
  /**
393
- * Create a workspace.
403
+ * Creates a workspace.
394
404
  *
395
405
  * @param options - Optional identity, emitter configuration, and initial files
396
406
  */
@@ -436,7 +446,7 @@ var Workspace = class {
436
446
  };
437
447
  }
438
448
  has(path) {
439
- if (isArray(path)) return path.some((one) => this.#files.has(one));
449
+ if (isArray(path)) return path.every((one) => this.#files.has(one));
440
450
  return this.#files.has(path);
441
451
  }
442
452
  search(query, options) {
@@ -446,7 +456,7 @@ var Workspace = class {
446
456
  for (const file of this.#files.values()) {
447
457
  if (limit !== void 0 && matches.length >= limit) break;
448
458
  if (!isText(file.content)) continue;
449
- const lines = file.content.text.split("\n");
459
+ const lines = file.content.text.split(/\r\n|\n/);
450
460
  for (let index = 0; index < lines.length; index += 1) {
451
461
  if (limit !== void 0 && matches.length >= limit) break;
452
462
  const lineText = lines[index] ?? "";
@@ -500,39 +510,42 @@ var Workspace = class {
500
510
  for (const [one, text] of Object.entries(path)) this.#write(one, text);
501
511
  return;
502
512
  }
503
- const text = content ?? "";
513
+ if (content === void 0) return;
504
514
  if (!range) {
505
- this.#write(path, text);
515
+ this.#write(path, content);
506
516
  return;
507
517
  }
508
- this.#splice(path, text, range);
518
+ this.#splice(path, content, range);
509
519
  }
510
520
  prepend(path, content) {
511
521
  if (isRecord(path)) {
512
522
  for (const [one, text] of Object.entries(path)) this.#prepend(one, text);
513
523
  return;
514
524
  }
515
- this.#prepend(path, content ?? "");
525
+ if (content === void 0) return;
526
+ this.#prepend(path, content);
516
527
  }
517
528
  append(path, content) {
518
529
  if (isRecord(path)) {
519
530
  for (const [one, text] of Object.entries(path)) this.#append(one, text);
520
531
  return;
521
532
  }
522
- this.#append(path, content ?? "");
533
+ if (content === void 0) return;
534
+ this.#append(path, content);
523
535
  }
524
536
  move(from, to) {
525
537
  if (isRecord(from)) {
526
- let moved = false;
527
- for (const [one, target] of Object.entries(from)) if (this.#move(one, target)) moved = true;
538
+ let moved = true;
539
+ for (const [one, target] of Object.entries(from)) if (!this.#move(one, target)) moved = false;
528
540
  return moved;
529
541
  }
530
- return this.#move(from, to ?? "");
542
+ if (to === void 0) return false;
543
+ return this.#move(from, to);
531
544
  }
532
545
  remove(path) {
533
546
  if (isArray(path)) {
534
- let removed = false;
535
- for (const one of path) if (this.#remove(one)) removed = true;
547
+ let removed = true;
548
+ for (const one of path) if (!this.#remove(one)) removed = false;
536
549
  return removed;
537
550
  }
538
551
  return this.#remove(path);
@@ -565,7 +578,7 @@ var Workspace = class {
565
578
  }
566
579
  #splice(path, content, range) {
567
580
  const existing = this.#files.get(path);
568
- if (!existing) throw new WorkspaceError("MODALITY", `Cannot splice a range of a missing file: ${path}`, { path });
581
+ if (!existing) throw new WorkspaceError("MISSING", `Cannot splice a range of a missing file: ${path}`, { path });
569
582
  if (!isText(existing.content)) throw new WorkspaceError("MODALITY", `Cannot splice a range of a binary file: ${path}`, { path });
570
583
  if (!isValidRange(range)) throw new WorkspaceError("RANGE", `Invalid range for file: ${path}`, {
571
584
  path,
@@ -634,7 +647,8 @@ var Workspace = class {
634
647
  //#endregion
635
648
  //#region src/core/workspaces/WorkspaceManager.ts
636
649
  /**
637
- * An insertion-ordered workspace registry with an active selection.
650
+ * Implements `WorkspaceManagerInterface` over an insertion-ordered id map and one active id
651
+ * the instance owns, resolving `active` through that map on every read and holding no emitter.
638
652
  *
639
653
  * A supplied store adds lenient snapshot `open` and `save` operations. Event defaults flow into
640
654
  * workspaces created through the registry, while observability remains owned by each workspace.
@@ -655,7 +669,7 @@ var WorkspaceManager = class {
655
669
  #error;
656
670
  #store;
657
671
  /**
658
- * Create a registry.
672
+ * Creates a registry.
659
673
  *
660
674
  * @param options - Default event hooks and optional snapshot store
661
675
  */
@@ -719,8 +733,8 @@ var WorkspaceManager = class {
719
733
  }
720
734
  remove(ids) {
721
735
  if (isArray(ids)) {
722
- let removed = false;
723
- for (const id of ids) if (this.#drop(id)) removed = true;
736
+ let removed = true;
737
+ for (const id of ids) if (!this.#drop(id)) removed = false;
724
738
  return removed;
725
739
  }
726
740
  return this.#drop(ids);
@@ -742,21 +756,27 @@ var WorkspaceManager = class {
742
756
  //#endregion
743
757
  //#region src/core/workspaces/stores/DatabaseWorkspaceStore.ts
744
758
  /**
745
- * A workspace snapshot store over a database table.
759
+ * Persists workspace snapshots in a database table.
746
760
  *
747
761
  * Snapshots occupy one opaque column and are narrowed when read back from the storage boundary.
748
762
  *
749
763
  * @example
750
764
  * ```ts
751
- * import { createDatabaseWorkspaceStore } from '@orkestrel/workspace'
752
- *
753
- * const store = createDatabaseWorkspaceStore()
765
+ * import { rawShape, stringShape } from '@orkestrel/contract'
766
+ * import { createDatabase, createMemoryDriver } from '@orkestrel/database'
767
+ * import { DatabaseWorkspaceStore } from '@orkestrel/workspace'
768
+ *
769
+ * const database = createDatabase({
770
+ * driver: createMemoryDriver(),
771
+ * tables: { workspaces: { id: stringShape(), snapshot: rawShape({}) } },
772
+ * })
773
+ * const store = new DatabaseWorkspaceStore(database.table('workspaces'))
754
774
  * ```
755
775
  */
756
776
  var DatabaseWorkspaceStore = class {
757
777
  #table;
758
778
  /**
759
- * Wrap a workspace snapshot table.
779
+ * Wraps a workspace snapshot table.
760
780
  *
761
781
  * @param table - The table keyed by workspace identifier
762
782
  */
@@ -781,7 +801,7 @@ var DatabaseWorkspaceStore = class {
781
801
  //#endregion
782
802
  //#region src/core/workspaces/stores/MemoryWorkspaceStore.ts
783
803
  /**
784
- * A process-local workspace snapshot store.
804
+ * Holds workspace snapshots in the current process.
785
805
  *
786
806
  * @example
787
807
  * ```ts
@@ -807,16 +827,37 @@ var MemoryWorkspaceStore = class {
807
827
  //#endregion
808
828
  //#region src/core/factories.ts
809
829
  /**
810
- * Create an immutable file with derived size and line counts.
830
+ * Creates an immutable file with derived size and line counts.
811
831
  *
812
832
  * @param input - The file path, content, and optional state
813
833
  * @returns A frozen file record
814
834
  *
815
- * @example
835
+ * @example Files and content
816
836
  * ```ts
817
- * import { createFile, createTextContent } from '@orkestrel/workspace'
818
- *
819
- * createFile({ path: 'a.txt', content: createTextContent('hello', 'text') })
837
+ * import {
838
+ * computeSize,
839
+ * countLines,
840
+ * createBinaryContent,
841
+ * createFile,
842
+ * createTextContent,
843
+ * inferLanguage,
844
+ * isBinary,
845
+ * isText,
846
+ * } from '@orkestrel/workspace'
847
+ *
848
+ * const note = createFile({
849
+ * path: 'notes.md',
850
+ * content: createTextContent('# Title\nBody', inferLanguage('notes.md')), // 'markdown'
851
+ * })
852
+ *
853
+ * note.size // 12 — UTF-8 bytes, through computeSize
854
+ * note.lines // 2 — through countLines
855
+ * note.state // 'created'
856
+ * isText(note.content) // true
857
+ *
858
+ * const icon = createFile({ path: 'icon.png', content: createBinaryContent('AAAA', 'image/png') })
859
+ * isBinary(icon.content) // true
860
+ * icon.size // 3 — decoded base64 bytes, through computeDecodedSize
820
861
  * ```
821
862
  */
822
863
  function createFile(input) {
@@ -829,7 +870,8 @@ function createFile(input) {
829
870
  });
830
871
  }
831
872
  /**
832
- * Create the text arm of {@link FileContent}.
873
+ * Creates the text arm of {@link FileContent}, returned as {@link TextContent} rather than as
874
+ * the whole union.
833
875
  *
834
876
  * @param text - The text body
835
877
  * @param language - The language tag
@@ -849,9 +891,10 @@ function createTextContent(text, language) {
849
891
  };
850
892
  }
851
893
  /**
852
- * Create the binary arm of {@link FileContent}.
894
+ * Creates the binary arm of {@link FileContent}, returned as {@link BinaryContent} rather than
895
+ * as the whole union.
853
896
  *
854
- * @param data - The base64 payload
897
+ * @param base64 - The base64 payload
855
898
  * @param mime - The binary MIME
856
899
  * @returns Binary file content
857
900
  *
@@ -862,14 +905,14 @@ function createTextContent(text, language) {
862
905
  * createBinaryContent('AAAA', 'image/png')
863
906
  * ```
864
907
  */
865
- function createBinaryContent(data, mime) {
908
+ function createBinaryContent(base64, mime) {
866
909
  return {
867
- data,
910
+ base64,
868
911
  mime
869
912
  };
870
913
  }
871
914
  /**
872
- * Create a workspace.
915
+ * Creates a workspace with the same identity, emitter, and seed options the constructor takes.
873
916
  *
874
917
  * @param options - Optional identity, emitter configuration, and initial files
875
918
  * @returns A working workspace
@@ -886,7 +929,7 @@ function createWorkspace(options) {
886
929
  return new Workspace(options);
887
930
  }
888
931
  /**
889
- * Create an in-memory workspace snapshot store.
932
+ * Creates an in-memory workspace snapshot store.
890
933
  *
891
934
  * @returns A process-local workspace store
892
935
  *
@@ -901,9 +944,10 @@ function createMemoryWorkspaceStore() {
901
944
  return new MemoryWorkspaceStore();
902
945
  }
903
946
  /**
904
- * Create a database-backed workspace snapshot store.
947
+ * Creates a database-backed workspace snapshot store, over an in-memory driver when the caller
948
+ * supplies none.
905
949
  *
906
- * @param driver - The database driver; defaults to an in-memory driver
950
+ * @param driver - The database driver. Default: an in-memory driver.
907
951
  * @returns A workspace store backed by the supplied driver
908
952
  *
909
953
  * @example
@@ -924,7 +968,7 @@ function createDatabaseWorkspaceStore(driver = createMemoryDriver()) {
924
968
  }).table("workspaces"));
925
969
  }
926
970
  /**
927
- * Create an empty workspace registry.
971
+ * Creates an empty workspace registry.
928
972
  *
929
973
  * @param options - Default event hooks and optional durability
930
974
  * @returns A workspace manager
@@ -941,6 +985,6 @@ function createWorkspaceManager(options) {
941
985
  return new WorkspaceManager(options);
942
986
  }
943
987
  //#endregion
944
- export { DatabaseWorkspaceStore, EXTENSION_LANGUAGES, MemoryWorkspaceStore, Workspace, WorkspaceError, WorkspaceManager, clampPosition, clampRange, computeSize, countLines, createBinaryContent, createDatabaseWorkspaceStore, createFile, createMemoryWorkspaceStore, createTextContent, createWorkspace, createWorkspaceManager, decodedSize, escapeRegExp, inferLanguage, isBinary, isFile, isText, isValidRange, isWorkspaceError, isWorkspaceSnapshot, offsetAt, rangeOf, sliceRange, spliceRange };
988
+ export { DatabaseWorkspaceStore, EXTENSION_LANGUAGES, MemoryWorkspaceStore, Workspace, WorkspaceError, WorkspaceManager, clampPosition, clampRange, computeDecodedSize, computeSize, countLines, createBinaryContent, createDatabaseWorkspaceStore, createFile, createMemoryWorkspaceStore, createTextContent, createWorkspace, createWorkspaceManager, escapeRegExp, inferLanguage, isBinary, isFile, isText, isValidRange, isWorkspaceError, isWorkspaceSnapshot, offsetAt, rangeOf, sliceRange, spliceRange };
945
989
 
946
990
  //# sourceMappingURL=index.js.map