@morlay/session-rdb 0.0.20 → 0.0.21-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +59 -31
  2. package/dist/artifact.d.mts +25 -65
  3. package/dist/artifact.mjs +2 -2
  4. package/dist/{schema-BkQN5GyT.d.mts → backend-DpdtxYpz.d.mts} +346 -93
  5. package/dist/{branch-Co6xlbi0.mjs → branch-5JzX9rUq.mjs} +163 -52
  6. package/dist/deletion.d.mts +7 -0
  7. package/dist/deletion.mjs +2 -0
  8. package/dist/dist-vIVO6bA-.mjs +1524 -0
  9. package/dist/import.d.mts +4 -4
  10. package/dist/import.mjs +28 -11
  11. package/dist/index.d.mts +2 -3
  12. package/dist/index.mjs +4 -1631
  13. package/dist/{log-DO69NQnn.mjs → log-CnYct2Dv.mjs} +37 -82
  14. package/dist/{sqlite-DYExtbLo.mjs → sqlite-fpvm5Dzs.mjs} +205 -75
  15. package/dist/src-CWTWV7vx.mjs +1904 -0
  16. package/dist/storage.d.mts +14 -5
  17. package/dist/storage.mjs +2 -2
  18. package/dist/testing.d.mts +1 -26
  19. package/dist/testing.mjs +10503 -9614
  20. package/drizzle/postgres/20260918120000_v3_event_usage/migration.sql +14 -0
  21. package/drizzle/postgres/20260918120000_v3_event_usage/snapshot.json +1309 -0
  22. package/drizzle/sqlite/20260918120000_v3_event_usage/migration.sql +14 -0
  23. package/drizzle/sqlite/20260918120000_v3_event_usage/snapshot.json +1031 -0
  24. package/package.json +28 -29
  25. package/src/adapters/to-postgres.ts +1 -3
  26. package/src/adapters/to-sqlite.ts +0 -2
  27. package/src/adapters/types.ts +0 -3
  28. package/src/artifact.ts +0 -2
  29. package/src/backend.ts +31 -2
  30. package/src/branch.ts +223 -135
  31. package/src/deletion.ts +87 -0
  32. package/src/drizzle/postgres-v2.ts +0 -1
  33. package/src/drizzle/postgres-v3.ts +0 -1
  34. package/src/drizzle/sqlite-v2.ts +0 -1
  35. package/src/drizzle/sqlite-v3.ts +0 -1
  36. package/src/entities/v2/session-events.ts +0 -1
  37. package/src/entities/v3/event-usage.ts +25 -0
  38. package/src/entities/v3/events.ts +1 -3
  39. package/src/entities/v3/index.ts +4 -0
  40. package/src/entities/v3/session-events.ts +1 -2
  41. package/src/entities/v3/session-projcache-rows.ts +0 -8
  42. package/src/entities/v3/sessions.ts +3 -3
  43. package/src/entities/v3/storage-units.ts +0 -1
  44. package/src/entities/v3/workspace-sessions.ts +0 -5
  45. package/src/entities/v3/workspace-state.ts +0 -6
  46. package/src/entities/v3/workspaces.ts +0 -5
  47. package/src/export.ts +103 -0
  48. package/src/gc.ts +76 -0
  49. package/src/import-storages.ts +4 -37
  50. package/src/import.ts +54 -31
  51. package/src/index.ts +150 -114
  52. package/src/legacy.ts +4 -42
  53. package/src/log.ts +63 -106
  54. package/src/postgres.ts +249 -22
  55. package/src/schema.ts +6 -6
  56. package/src/session-query.ts +0 -4
  57. package/src/sqlite.ts +231 -55
  58. package/src/storage-takeover/index.ts +2 -28
  59. package/src/storage-takeover/projection-cache.ts +30 -134
  60. package/src/storage-takeover/repository.ts +20 -59
  61. package/src/storage-takeover/storage-backend.ts +3 -33
  62. package/src/storage-takeover/types.ts +14 -56
  63. package/src/storage.ts +0 -2
  64. package/src/testing/contract.ts +19 -50
  65. package/src/testing/coordinator-contract.ts +10 -25
  66. package/src/testing.ts +1 -4
  67. package/src/usage.ts +191 -0
  68. package/dist/index-D55G9n4k.d.mts +0 -271
  69. package/dist/magic-string.es-BgJoa-3K.mjs +0 -1017
@@ -0,0 +1,1524 @@
1
+ //#region ../../../node_modules/.pnpm/@jridgewell+sourcemap-codec@1.6.0/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs
2
+ var comma = ",".charCodeAt(0);
3
+ var semicolon = ";".charCodeAt(0);
4
+ var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
5
+ var intToChar$1 = /* @__PURE__ */ new Uint8Array(64);
6
+ var charToInt = /* @__PURE__ */ new Uint8Array(128);
7
+ for (let i = 0; i < chars.length; i++) {
8
+ const c = chars.charCodeAt(i);
9
+ intToChar$1[i] = c;
10
+ charToInt[c] = i;
11
+ }
12
+ function encodeInteger(builder, num) {
13
+ do {
14
+ let clamped = num & 31;
15
+ num >>>= 5;
16
+ if (num > 0) clamped |= 32;
17
+ builder.write(intToChar$1[clamped]);
18
+ } while (num > 0);
19
+ }
20
+ function encodeSign(num) {
21
+ return num < 0 ? -num << 1 | 1 : num << 1;
22
+ }
23
+ var bufLength = 16384;
24
+ var td = typeof TextDecoder !== "undefined" ? /* @__PURE__ */ new TextDecoder() : typeof Buffer !== "undefined" ? { decode(buf) {
25
+ return Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength).toString();
26
+ } } : { decode(buf) {
27
+ let out = "";
28
+ for (let i = 0; i < buf.length; i++) out += String.fromCharCode(buf[i]);
29
+ return out;
30
+ } };
31
+ var StringWriter = class {
32
+ constructor() {
33
+ this.pos = 0;
34
+ this.out = "";
35
+ this.buffer = new Uint8Array(bufLength);
36
+ }
37
+ write(v) {
38
+ const { buffer } = this;
39
+ buffer[this.pos++] = v;
40
+ if (this.pos === bufLength) {
41
+ this.out += td.decode(buffer);
42
+ this.pos = 0;
43
+ }
44
+ }
45
+ flush() {
46
+ const { buffer, out, pos } = this;
47
+ return pos > 0 ? out + td.decode(buffer.subarray(0, pos)) : out;
48
+ }
49
+ };
50
+ function encodeRangeMappings(decoded) {
51
+ if (decoded.length === 0) return "";
52
+ const writer = new StringWriter();
53
+ for (let i = 0; i < decoded.length; i++) {
54
+ const indices = decoded[i];
55
+ if (i > 0) writer.write(semicolon);
56
+ let index = 0;
57
+ for (let j = 0; j < indices.length; j++) {
58
+ const offset = indices[j];
59
+ encodeInteger(writer, offset - index);
60
+ index = offset;
61
+ }
62
+ }
63
+ return writer.flush();
64
+ }
65
+ function encode(decoded) {
66
+ const writer = new StringWriter();
67
+ let sourcesIndex = 0;
68
+ let sourceLine = 0;
69
+ let sourceColumn = 0;
70
+ let namesIndex = 0;
71
+ for (let i = 0; i < decoded.length; i++) {
72
+ const line = decoded[i];
73
+ if (i > 0) writer.write(semicolon);
74
+ if (line.length === 0) continue;
75
+ let genColumn = 0;
76
+ for (let j = 0; j < line.length; j++) {
77
+ const segment = line[j];
78
+ if (j > 0) writer.write(comma);
79
+ encodeInteger(writer, encodeSign(segment[0] - genColumn));
80
+ genColumn = segment[0];
81
+ if (segment.length === 1) continue;
82
+ encodeInteger(writer, encodeSign(segment[1] - sourcesIndex));
83
+ encodeInteger(writer, encodeSign(segment[2] - sourceLine));
84
+ encodeInteger(writer, encodeSign(segment[3] - sourceColumn));
85
+ sourcesIndex = segment[1];
86
+ sourceLine = segment[2];
87
+ sourceColumn = segment[3];
88
+ if (segment.length === 4) continue;
89
+ encodeInteger(writer, encodeSign(segment[4] - namesIndex));
90
+ namesIndex = segment[4];
91
+ }
92
+ }
93
+ return writer.flush();
94
+ }
95
+ //#endregion
96
+ //#region ../../../node_modules/.pnpm/magic-string@1.4.1/node_modules/magic-string/dist/index.mjs
97
+ var BitSet = class BitSet {
98
+ constructor(arg) {
99
+ this.bits = arg instanceof BitSet ? arg.bits.slice() : [];
100
+ }
101
+ add(n) {
102
+ this.bits[n >> 5] |= 1 << (n & 31);
103
+ }
104
+ has(n) {
105
+ return !!(this.bits[n >> 5] & 1 << (n & 31));
106
+ }
107
+ };
108
+ var Chunk = class Chunk {
109
+ constructor(start, end, content) {
110
+ this.start = start;
111
+ this.end = end;
112
+ this.original = content;
113
+ this.intro = "";
114
+ this.outro = "";
115
+ this.content = content;
116
+ this.storeName = false;
117
+ this.edited = false;
118
+ this.previous = null;
119
+ this.next = null;
120
+ }
121
+ appendLeft(content) {
122
+ this.outro += content;
123
+ }
124
+ appendRight(content) {
125
+ this.intro = this.intro + content;
126
+ }
127
+ clone() {
128
+ const chunk = new Chunk(this.start, this.end, this.original);
129
+ chunk.intro = this.intro;
130
+ chunk.outro = this.outro;
131
+ chunk.content = this.content;
132
+ chunk.storeName = this.storeName;
133
+ chunk.edited = this.edited;
134
+ return chunk;
135
+ }
136
+ contains(index) {
137
+ return this.start < index && index < this.end;
138
+ }
139
+ eachNext(fn) {
140
+ fn(this);
141
+ let chunk = this.next;
142
+ while (chunk) {
143
+ fn(chunk);
144
+ chunk = chunk.next;
145
+ }
146
+ }
147
+ eachPrevious(fn) {
148
+ fn(this);
149
+ let chunk = this.previous;
150
+ while (chunk) {
151
+ fn(chunk);
152
+ chunk = chunk.previous;
153
+ }
154
+ }
155
+ edit(content, storeName, contentOnly) {
156
+ this.content = content;
157
+ if (!contentOnly) {
158
+ this.intro = "";
159
+ this.outro = "";
160
+ }
161
+ this.storeName = storeName;
162
+ this.edited = true;
163
+ return this;
164
+ }
165
+ prependLeft(content) {
166
+ this.outro = content + this.outro;
167
+ }
168
+ prependRight(content) {
169
+ this.intro = content + this.intro;
170
+ }
171
+ reset() {
172
+ this.intro = "";
173
+ this.outro = "";
174
+ if (this.edited) {
175
+ this.content = this.original;
176
+ this.storeName = false;
177
+ this.edited = false;
178
+ }
179
+ }
180
+ split(index) {
181
+ const sliceIndex = index - this.start;
182
+ const originalBefore = this.original.slice(0, sliceIndex);
183
+ const originalAfter = this.original.slice(sliceIndex);
184
+ this.original = originalBefore;
185
+ const newChunk = new Chunk(index, this.end, originalAfter);
186
+ newChunk.outro = this.outro;
187
+ this.outro = "";
188
+ this.end = index;
189
+ if (this.edited) {
190
+ newChunk.edit("", false);
191
+ this.content = "";
192
+ } else this.content = originalBefore;
193
+ newChunk.next = this.next;
194
+ if (newChunk.next) newChunk.next.previous = newChunk;
195
+ newChunk.previous = this;
196
+ this.next = newChunk;
197
+ return newChunk;
198
+ }
199
+ toString() {
200
+ return this.intro + this.content + this.outro;
201
+ }
202
+ trimEnd(rx) {
203
+ this.outro = this.outro.replace(rx, "");
204
+ if (this.outro.length) return true;
205
+ const trimmed = this.content.replace(rx, "");
206
+ if (trimmed.length) {
207
+ if (trimmed !== this.content) {
208
+ if (this.edited) this.edit(trimmed, this.storeName, true);
209
+ else this.split(this.start + trimmed.length).edit("", void 0, true);
210
+ }
211
+ return true;
212
+ } else {
213
+ this.edit("", void 0, true);
214
+ this.intro = this.intro.replace(rx, "");
215
+ if (this.intro.length) return true;
216
+ }
217
+ }
218
+ trimStart(rx) {
219
+ this.intro = this.intro.replace(rx, "");
220
+ if (this.intro.length) return true;
221
+ const trimmed = this.content.replace(rx, "");
222
+ if (trimmed.length) {
223
+ if (trimmed !== this.content) {
224
+ if (this.edited) this.edit(trimmed, this.storeName, true);
225
+ else {
226
+ this.split(this.end - trimmed.length);
227
+ this.edit("", void 0, true);
228
+ }
229
+ }
230
+ return true;
231
+ } else {
232
+ this.edit("", void 0, true);
233
+ this.outro = this.outro.replace(rx, "");
234
+ if (this.outro.length) return true;
235
+ }
236
+ }
237
+ };
238
+ /**
239
+ * The single error type thrown by MagicString.
240
+ *
241
+ * Every message is prefixed with `[MagicString]` so its source is obvious at a
242
+ * glance, and is kept short and consistent in tone.
243
+ */
244
+ var MagicStringError = class extends Error {
245
+ name = "MagicStringError";
246
+ constructor(message, options) {
247
+ super(`[MagicString] ${message}`, options);
248
+ }
249
+ };
250
+ function getBtoa() {
251
+ /* v8 ignore next -- environment fallback, unreachable when `btoa` is present */
252
+ if (typeof globalThis !== "undefined" && typeof globalThis.btoa === "function") return (str) => globalThis.btoa(unescape(encodeURIComponent(str)));
253
+ const buffer = globalThis["Buffer"];
254
+ if (buffer) return (str) => buffer.from(str, "utf-8").toString("base64");
255
+ return () => {
256
+ throw new MagicStringError("unsupported environment: `btoa` or `Buffer` is required");
257
+ };
258
+ /* v8 ignore stop */
259
+ }
260
+ const btoa = /* #__PURE__ */ getBtoa();
261
+ var SourceMap = class {
262
+ constructor(properties) {
263
+ this.version = 3;
264
+ this.file = properties.file;
265
+ this.sources = properties.sources;
266
+ this.sourcesContent = properties.sourcesContent;
267
+ this.names = properties.names;
268
+ this.mappings = typeof properties.mappings === "string" ? properties.mappings : encode(properties.mappings);
269
+ if (typeof properties.x_google_ignoreList !== "undefined") this.x_google_ignoreList = properties.x_google_ignoreList;
270
+ if (typeof properties.debugId !== "undefined") this.debugId = properties.debugId;
271
+ if (typeof properties.rangeMappings !== "undefined") {
272
+ let shouldOutputRangeMapping = false;
273
+ for (const line of properties.rangeMappings) if (line.length !== 0) {
274
+ shouldOutputRangeMapping = true;
275
+ break;
276
+ }
277
+ if (shouldOutputRangeMapping) this.rangeMappings = encodeRangeMappings(properties.rangeMappings);
278
+ }
279
+ }
280
+ /**
281
+ * Returns the equivalent of `JSON.stringify(map)`
282
+ */
283
+ toString() {
284
+ return JSON.stringify(this);
285
+ }
286
+ /**
287
+ * Returns a DataURI containing the sourcemap. Useful for doing this sort of thing:
288
+ * `generateMap(options?: SourceMapOptions): SourceMap;`
289
+ */
290
+ toUrl() {
291
+ return `data:application/json;charset=utf-8;base64,${btoa(this.toString())}`;
292
+ }
293
+ };
294
+ function getLocator(source) {
295
+ const lineOffsets = [0];
296
+ for (let i = source.indexOf("\n"); i !== -1; i = source.indexOf("\n", i + 1)) lineOffsets.push(i + 1);
297
+ return function locate(index) {
298
+ let i = 0;
299
+ let j = lineOffsets.length;
300
+ while (i < j) {
301
+ const m = i + j >> 1;
302
+ if (index < lineOffsets[m]) j = m;
303
+ else i = m + 1;
304
+ }
305
+ const line = i - 1;
306
+ return {
307
+ line,
308
+ column: index - lineOffsets[line]
309
+ };
310
+ };
311
+ }
312
+ function getRelativePath(from, to) {
313
+ const fromParts = from.split(/[/\\]/);
314
+ const toParts = to.split(/[/\\]/);
315
+ fromParts.pop();
316
+ while (fromParts[0] === toParts[0]) {
317
+ fromParts.shift();
318
+ toParts.shift();
319
+ }
320
+ if (fromParts.length) {
321
+ let i = fromParts.length;
322
+ while (i--) fromParts[i] = "..";
323
+ }
324
+ return fromParts.concat(toParts).join("/");
325
+ }
326
+ function guessIndent(code) {
327
+ const lines = code.split("\n");
328
+ const tabbed = lines.filter((line) => /^\t+/.test(line));
329
+ const spaced = lines.filter((line) => /^ {2,}/.test(line));
330
+ if (tabbed.length === 0 && spaced.length === 0) return null;
331
+ if (tabbed.length >= spaced.length) return " ";
332
+ const min = spaced.reduce((previous, current) => {
333
+ const numSpaces = /^ +/.exec(current)[0].length;
334
+ return Math.min(numSpaces, previous);
335
+ }, Infinity);
336
+ return " ".repeat(min);
337
+ }
338
+ const toString = Object.prototype.toString;
339
+ function isObject(thing) {
340
+ return toString.call(thing) === "[object Object]";
341
+ }
342
+ const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
343
+ const intToChar = /* #__PURE__ */ (() => {
344
+ const chars = /* @__PURE__ */ new Uint8Array(64);
345
+ for (let i = 0; i < 64; i++) chars[i] = BASE64_CHARS.charCodeAt(i);
346
+ return chars;
347
+ })();
348
+ const COMMA = 44;
349
+ const SEMICOLON = 59;
350
+ const BUFFER_SIZE = 16384;
351
+ const FLUSH_THRESHOLD = 16348;
352
+ const scratch = /* #__PURE__ */ new Uint8Array(BUFFER_SIZE);
353
+ function writeVlq(pos, num) {
354
+ num = num < 0 ? -num << 1 | 1 : num << 1;
355
+ do {
356
+ let clamped = num & 31;
357
+ num >>>= 5;
358
+ if (num > 0) clamped |= 32;
359
+ scratch[pos++] = intToChar[clamped];
360
+ } while (num > 0);
361
+ return pos;
362
+ }
363
+ const decoder = /* #__PURE__ */ new TextDecoder();
364
+ var MappingsEncoder = class {
365
+ constructor() {
366
+ this.out = "";
367
+ this.pos = 0;
368
+ this.lines = [];
369
+ this.buffered = 0;
370
+ this.needsComma = false;
371
+ this.prevGenColumn = 0;
372
+ this.prevSourceIndex = 0;
373
+ this.prevSourceLine = 0;
374
+ this.prevSourceColumn = 0;
375
+ this.prevNameIndex = 0;
376
+ }
377
+ endLine(segments) {
378
+ this.lines.push(segments);
379
+ this.buffered += segments.length + 1;
380
+ if (this.buffered >= 4096) this.drain(null);
381
+ }
382
+ segments(segments) {
383
+ this.drain(segments);
384
+ }
385
+ finish(segments) {
386
+ this.drain(segments);
387
+ this.flush();
388
+ return this.out;
389
+ }
390
+ drain(trailing) {
391
+ const lines = this.lines;
392
+ const lineCount = lines.length;
393
+ for (let l = 0; l <= lineCount; l++) {
394
+ const line = l < lineCount ? lines[l] : trailing;
395
+ if (line === null) break;
396
+ for (let i = 0; i < line.length; i++) {
397
+ if (this.pos > FLUSH_THRESHOLD) this.flush();
398
+ const segment = line[i];
399
+ if (this.needsComma) scratch[this.pos++] = COMMA;
400
+ this.needsComma = true;
401
+ this.pos = writeVlq(this.pos, segment[0] - this.prevGenColumn);
402
+ this.prevGenColumn = segment[0];
403
+ this.pos = writeVlq(this.pos, segment[1] - this.prevSourceIndex);
404
+ this.prevSourceIndex = segment[1];
405
+ this.pos = writeVlq(this.pos, segment[2] - this.prevSourceLine);
406
+ this.prevSourceLine = segment[2];
407
+ this.pos = writeVlq(this.pos, segment[3] - this.prevSourceColumn);
408
+ this.prevSourceColumn = segment[3];
409
+ if (segment.length === 5) {
410
+ this.pos = writeVlq(this.pos, segment[4] - this.prevNameIndex);
411
+ this.prevNameIndex = segment[4];
412
+ }
413
+ }
414
+ if (l < lineCount) {
415
+ if (this.pos > FLUSH_THRESHOLD) this.flush();
416
+ scratch[this.pos++] = SEMICOLON;
417
+ this.needsComma = false;
418
+ this.prevGenColumn = 0;
419
+ }
420
+ }
421
+ lines.length = 0;
422
+ this.buffered = 0;
423
+ this.flush();
424
+ }
425
+ flush() {
426
+ this.out += decoder.decode(scratch.subarray(0, this.pos));
427
+ this.pos = 0;
428
+ }
429
+ };
430
+ const NEWLINE_CHAR$1 = 10;
431
+ function isWordCode(code) {
432
+ return code >= 97 && code <= 122 || code >= 65 && code <= 90 || code >= 48 && code <= 57 || code === 95;
433
+ }
434
+ var Mappings = class {
435
+ constructor(hires, encoder = null) {
436
+ this.hires = hires;
437
+ this.generatedCodeLine = 0;
438
+ this.generatedCodeColumn = 0;
439
+ this.raw = [];
440
+ this.rawSegments = this.raw[this.generatedCodeLine] = [];
441
+ this.rawRangeMappings = [];
442
+ this.rawRangeMappingsIndices = this.rawRangeMappings[this.generatedCodeLine] = [];
443
+ this.encoder = encoder;
444
+ }
445
+ nextLine() {
446
+ if (this.encoder === null) {
447
+ this.generatedCodeLine += 1;
448
+ this.raw[this.generatedCodeLine] = this.rawSegments = [];
449
+ } else {
450
+ this.encoder.endLine(this.rawSegments);
451
+ this.rawSegments = [];
452
+ this.generatedCodeLine += 1;
453
+ }
454
+ this.generatedCodeColumn = 0;
455
+ this.rawRangeMappings[this.generatedCodeLine] = this.rawRangeMappingsIndices = [];
456
+ }
457
+ addEdit(sourceIndex, content, loc, nameIndex) {
458
+ if (content.length) {
459
+ const contentLengthMinusOne = content.length - 1;
460
+ let contentLineEnd = content.indexOf("\n", 0);
461
+ let previousContentLineEnd = -1;
462
+ while (contentLineEnd >= 0 && contentLengthMinusOne > contentLineEnd) {
463
+ const segment = [
464
+ this.generatedCodeColumn,
465
+ sourceIndex,
466
+ loc.line,
467
+ loc.column
468
+ ];
469
+ if (nameIndex >= 0) segment.push(nameIndex);
470
+ this.rawSegments.push(segment);
471
+ this.nextLine();
472
+ previousContentLineEnd = contentLineEnd;
473
+ contentLineEnd = content.indexOf("\n", contentLineEnd + 1);
474
+ }
475
+ const segment = [
476
+ this.generatedCodeColumn,
477
+ sourceIndex,
478
+ loc.line,
479
+ loc.column
480
+ ];
481
+ if (nameIndex >= 0) segment.push(nameIndex);
482
+ this.rawSegments.push(segment);
483
+ this.advance(content.slice(previousContentLineEnd + 1));
484
+ }
485
+ }
486
+ addUneditedChunk(sourceIndex, chunk, original, loc, sourcemapLocations) {
487
+ const end = chunk.end;
488
+ let i = chunk.start;
489
+ if (this.hires) {
490
+ const boundary = this.hires === "boundary";
491
+ const experimentalRange = this.hires === "experimental-range";
492
+ const encoder = experimentalRange ? null : this.encoder;
493
+ let charInHiresBoundary = false;
494
+ while (i < end) {
495
+ if (encoder !== null && this.rawSegments.length >= 4096) {
496
+ encoder.segments(this.rawSegments);
497
+ this.rawSegments.length = 0;
498
+ }
499
+ if (experimentalRange && i + 1 >= end) this.rawSegments.push([
500
+ this.generatedCodeColumn,
501
+ sourceIndex,
502
+ loc.line,
503
+ loc.column
504
+ ]);
505
+ const code = original.charCodeAt(i);
506
+ if (code === NEWLINE_CHAR$1) {
507
+ loc.line += 1;
508
+ loc.column = 0;
509
+ this.nextLine();
510
+ charInHiresBoundary = false;
511
+ } else {
512
+ if (boundary) {
513
+ if (isWordCode(code)) {
514
+ if (!charInHiresBoundary) {
515
+ this.rawSegments.push([
516
+ this.generatedCodeColumn,
517
+ sourceIndex,
518
+ loc.line,
519
+ loc.column
520
+ ]);
521
+ charInHiresBoundary = true;
522
+ }
523
+ } else {
524
+ this.rawSegments.push([
525
+ this.generatedCodeColumn,
526
+ sourceIndex,
527
+ loc.line,
528
+ loc.column
529
+ ]);
530
+ charInHiresBoundary = false;
531
+ }
532
+ } else if (experimentalRange) {
533
+ if (i === chunk.start) {
534
+ this.rawRangeMappingsIndices.push(this.rawSegments.length);
535
+ this.rawSegments.push([
536
+ this.generatedCodeColumn,
537
+ sourceIndex,
538
+ loc.line,
539
+ loc.column
540
+ ]);
541
+ }
542
+ } else this.rawSegments.push([
543
+ this.generatedCodeColumn,
544
+ sourceIndex,
545
+ loc.line,
546
+ loc.column
547
+ ]);
548
+ loc.column += 1;
549
+ this.generatedCodeColumn += 1;
550
+ }
551
+ i += 1;
552
+ }
553
+ } else {
554
+ const bits = sourcemapLocations.bits;
555
+ while (i < end) {
556
+ let newline = original.indexOf("\n", i);
557
+ if (newline === -1 || newline > end) newline = end;
558
+ if (newline > i) {
559
+ this.rawSegments.push([
560
+ this.generatedCodeColumn,
561
+ sourceIndex,
562
+ loc.line,
563
+ loc.column
564
+ ]);
565
+ for (let w = i + 1 >> 5, last = newline - 1 >> 5; w <= last; w++) {
566
+ let word = bits[w];
567
+ if (!word) continue;
568
+ const base = w << 5;
569
+ while (word) {
570
+ const lowest = word & -word;
571
+ const index = base + 31 - Math.clz32(lowest);
572
+ if (index > i && index < newline) {
573
+ const offset = index - i;
574
+ this.rawSegments.push([
575
+ this.generatedCodeColumn + offset,
576
+ sourceIndex,
577
+ loc.line,
578
+ loc.column + offset
579
+ ]);
580
+ }
581
+ word ^= lowest;
582
+ }
583
+ }
584
+ loc.column += newline - i;
585
+ this.generatedCodeColumn += newline - i;
586
+ }
587
+ if (newline === end) break;
588
+ loc.line += 1;
589
+ loc.column = 0;
590
+ this.nextLine();
591
+ i = newline + 1;
592
+ }
593
+ }
594
+ }
595
+ advance(str) {
596
+ if (!str) return;
597
+ const lastNewline = str.lastIndexOf("\n");
598
+ for (let i = str.indexOf("\n"); i !== -1; i = str.indexOf("\n", i + 1)) this.nextLine();
599
+ this.generatedCodeColumn += str.length - lastNewline - 1;
600
+ }
601
+ };
602
+ const n = "\n";
603
+ const NEWLINE_CHAR = "\n".charCodeAt(0);
604
+ const CR_CHAR = "\r".charCodeAt(0);
605
+ const warned = {
606
+ insertLeft: false,
607
+ insertRight: false,
608
+ storeName: false
609
+ };
610
+ /**
611
+ * Expands the `$` substitution patterns that `String.prototype.replace` accepts
612
+ * in a string replacement.
613
+ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_string_as_a_parameter
614
+ *
615
+ * `captures` holds the capture groups in order, so `captures[0]` is `$1`.
616
+ * `namedCaptures` is `undefined` when the pattern has no named groups, and
617
+ * `$<name>` is then literal text - which is also the case for a string search
618
+ * value, where there are no groups of either kind.
619
+ */
620
+ function expandReplacement(replacement, matched, position, str, captures, namedCaptures) {
621
+ if (!replacement.includes("$")) return replacement;
622
+ let result = "";
623
+ let index = 0;
624
+ while (index < replacement.length) {
625
+ const dollar = replacement.indexOf("$", index);
626
+ if (dollar === -1) {
627
+ result += replacement.slice(index);
628
+ break;
629
+ }
630
+ result += replacement.slice(index, dollar);
631
+ const char = replacement[dollar + 1];
632
+ let expansion = "$";
633
+ let consumed = 1;
634
+ if (char === "$") consumed = 2;
635
+ else if (char === "&") {
636
+ expansion = matched;
637
+ consumed = 2;
638
+ } else if (char === "`") {
639
+ expansion = str.slice(0, position);
640
+ consumed = 2;
641
+ } else if (char === "'") {
642
+ expansion = str.slice(position + matched.length);
643
+ consumed = 2;
644
+ } else if (char === "<" && namedCaptures !== void 0) {
645
+ const close = replacement.indexOf(">", dollar + 2);
646
+ if (close !== -1) {
647
+ expansion = namedCaptures[replacement.slice(dollar + 2, close)] ?? "";
648
+ consumed = close + 1 - dollar;
649
+ }
650
+ } else if (char >= "0" && char <= "9") {
651
+ const second = replacement[dollar + 2];
652
+ const double = second >= "0" && second <= "9" ? Number(char + second) : NaN;
653
+ const single = Number(char);
654
+ if (double >= 1 && double <= captures.length) {
655
+ expansion = captures[double - 1] ?? "";
656
+ consumed = 3;
657
+ } else if (single >= 1 && single <= captures.length) {
658
+ expansion = captures[single - 1] ?? "";
659
+ consumed = 2;
660
+ }
661
+ }
662
+ result += expansion;
663
+ index = dollar + consumed;
664
+ }
665
+ return result;
666
+ }
667
+ var MagicString = class MagicString {
668
+ constructor(string, options = {}) {
669
+ const chunk = new Chunk(0, string.length, string);
670
+ Object.defineProperties(this, {
671
+ original: {
672
+ writable: true,
673
+ value: string
674
+ },
675
+ outro: {
676
+ writable: true,
677
+ value: ""
678
+ },
679
+ intro: {
680
+ writable: true,
681
+ value: ""
682
+ },
683
+ firstChunk: {
684
+ writable: true,
685
+ value: chunk
686
+ },
687
+ lastChunk: {
688
+ writable: true,
689
+ value: chunk
690
+ },
691
+ lastSearchedChunk: {
692
+ writable: true,
693
+ value: chunk
694
+ },
695
+ byStart: {
696
+ writable: true,
697
+ value: /* @__PURE__ */ new Map([[0, chunk]])
698
+ },
699
+ byEnd: {
700
+ writable: true,
701
+ value: /* @__PURE__ */ new Map([[string.length, chunk]])
702
+ },
703
+ filename: {
704
+ writable: true,
705
+ value: options.filename
706
+ },
707
+ indentExclusionRanges: {
708
+ writable: true,
709
+ value: options.indentExclusionRanges
710
+ },
711
+ sourcemapLocations: {
712
+ writable: true,
713
+ value: new BitSet()
714
+ },
715
+ storedNames: {
716
+ writable: true,
717
+ value: {}
718
+ },
719
+ indentStr: {
720
+ writable: true,
721
+ value: void 0
722
+ },
723
+ ignoreList: {
724
+ writable: true,
725
+ value: options.ignoreList
726
+ },
727
+ offset: {
728
+ writable: true,
729
+ value: options.offset || 0
730
+ },
731
+ hasMovedChunks: {
732
+ writable: true,
733
+ value: false
734
+ }
735
+ });
736
+ }
737
+ /**
738
+ * Adds the specified character index (with respect to the original string) to sourcemap mappings, if `hires` is false.
739
+ */
740
+ addSourcemapLocation(char) {
741
+ this.sourcemapLocations.add(char);
742
+ }
743
+ /**
744
+ * Appends the specified content to the end of the string.
745
+ */
746
+ append(content) {
747
+ if (typeof content !== "string") throw new MagicStringError(`content must be a string, got ${typeof content}`);
748
+ this.outro += content;
749
+ return this;
750
+ }
751
+ /**
752
+ * Appends the specified content at the index in the original string.
753
+ * If a range *ending* with index is subsequently moved, the insert will be moved with it.
754
+ * See also `s.prependLeft(...)`.
755
+ */
756
+ appendLeft(index, content) {
757
+ index = index + this.offset;
758
+ if (typeof content !== "string") throw new MagicStringError(`content must be a string, got ${typeof content}`);
759
+ this._split(index);
760
+ const chunk = this.byEnd.get(index);
761
+ if (chunk) chunk.appendLeft(content);
762
+ else this.intro += content;
763
+ return this;
764
+ }
765
+ /**
766
+ * Appends the specified content at the index in the original string.
767
+ * If a range *starting* with index is subsequently moved, the insert will be moved with it.
768
+ * See also `s.prependRight(...)`.
769
+ */
770
+ appendRight(index, content) {
771
+ index = index + this.offset;
772
+ if (typeof content !== "string") throw new MagicStringError(`content must be a string, got ${typeof content}`);
773
+ this._split(index);
774
+ const chunk = this.byStart.get(index);
775
+ if (chunk) chunk.appendRight(content);
776
+ else this.outro += content;
777
+ return this;
778
+ }
779
+ /**
780
+ * Does what you'd expect.
781
+ */
782
+ clone() {
783
+ const cloned = new MagicString(this.original, {
784
+ filename: this.filename,
785
+ ignoreList: this.ignoreList,
786
+ offset: this.offset
787
+ });
788
+ let originalChunk = this.firstChunk;
789
+ let clonedChunk = cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone();
790
+ while (originalChunk) {
791
+ cloned.byStart.set(clonedChunk.start, clonedChunk);
792
+ cloned.byEnd.set(clonedChunk.end, clonedChunk);
793
+ const nextOriginalChunk = originalChunk.next;
794
+ const nextClonedChunk = nextOriginalChunk && nextOriginalChunk.clone();
795
+ if (nextClonedChunk) {
796
+ clonedChunk.next = nextClonedChunk;
797
+ nextClonedChunk.previous = clonedChunk;
798
+ clonedChunk = nextClonedChunk;
799
+ }
800
+ originalChunk = nextOriginalChunk;
801
+ }
802
+ cloned.lastChunk = clonedChunk;
803
+ if (this.indentExclusionRanges) cloned.indentExclusionRanges = this.indentExclusionRanges.slice();
804
+ cloned.sourcemapLocations = new BitSet(this.sourcemapLocations);
805
+ cloned.storedNames = { ...this.storedNames };
806
+ cloned.intro = this.intro;
807
+ cloned.outro = this.outro;
808
+ cloned.hasMovedChunks = this.hasMovedChunks;
809
+ return cloned;
810
+ }
811
+ /**
812
+ * Generates a sourcemap object with raw mappings in array form, rather than encoded as a string.
813
+ * Useful if you need to manipulate the sourcemap further, but most of the time you will use `generateMap` instead.
814
+ */
815
+ generateDecodedMap(options) {
816
+ options = options || {};
817
+ const mappings = new Mappings(options.hires);
818
+ const names = this._generateMappings(mappings);
819
+ return {
820
+ ...this._mapProperties(options, names),
821
+ mappings: mappings.raw,
822
+ rangeMappings: mappings.rawRangeMappings
823
+ };
824
+ }
825
+ /**
826
+ * Generates a version 3 sourcemap.
827
+ */
828
+ generateMap(options) {
829
+ options = options || {};
830
+ const encoder = new MappingsEncoder();
831
+ const mappings = new Mappings(options.hires, encoder);
832
+ const names = this._generateMappings(mappings);
833
+ return new SourceMap({
834
+ ...this._mapProperties(options, names),
835
+ mappings: encoder.finish(mappings.rawSegments),
836
+ rangeMappings: mappings.rawRangeMappings
837
+ });
838
+ }
839
+ /** @internal */
840
+ _generateMappings(mappings) {
841
+ const sourceIndex = 0;
842
+ const names = Object.keys(this.storedNames);
843
+ const locate = getLocator(this.original);
844
+ if (this.intro) mappings.advance(this.intro);
845
+ this.firstChunk.eachNext((chunk) => {
846
+ const loc = locate(chunk.start);
847
+ if (chunk.intro.length) mappings.advance(chunk.intro);
848
+ if (chunk.edited) mappings.addEdit(sourceIndex, chunk.content, loc, chunk.storeName ? names.indexOf(chunk.original) : -1);
849
+ else mappings.addUneditedChunk(sourceIndex, chunk, this.original, loc, this.sourcemapLocations);
850
+ if (chunk.outro.length) mappings.advance(chunk.outro);
851
+ });
852
+ if (this.outro) mappings.advance(this.outro);
853
+ return names;
854
+ }
855
+ /** @internal */
856
+ _mapProperties(options, names) {
857
+ return {
858
+ file: options.file ? options.file.split(/[/\\]/).pop() : void 0,
859
+ sources: [options.source ? getRelativePath(options.file || "", options.source) : options.file || ""],
860
+ sourcesContent: options.includeContent ? [this.original] : void 0,
861
+ names,
862
+ x_google_ignoreList: this.ignoreList ? [0] : void 0
863
+ };
864
+ }
865
+ /** @internal */
866
+ _ensureindentStr() {
867
+ if (this.indentStr === void 0) this.indentStr = guessIndent(this.original);
868
+ }
869
+ /** @internal */
870
+ _getRawIndentString() {
871
+ this._ensureindentStr();
872
+ return this.indentStr;
873
+ }
874
+ getIndentString() {
875
+ this._ensureindentStr();
876
+ return this.indentStr === null ? " " : this.indentStr;
877
+ }
878
+ indent(indentStr, options) {
879
+ const pattern = /^[^\r\n]/gm;
880
+ if (isObject(indentStr)) {
881
+ options = indentStr;
882
+ indentStr = void 0;
883
+ }
884
+ if (indentStr === void 0) {
885
+ this._ensureindentStr();
886
+ indentStr = this.indentStr || " ";
887
+ }
888
+ if (indentStr === "") return this;
889
+ const resolvedIndentStr = indentStr;
890
+ options = options || {};
891
+ const isExcluded = {};
892
+ if (options.exclude) (typeof options.exclude[0] === "number" ? [options.exclude] : options.exclude).forEach((exclusion) => {
893
+ for (let i = exclusion[0]; i < exclusion[1]; i += 1) isExcluded[i] = true;
894
+ });
895
+ let shouldIndentNextCharacter = options.indentStart !== false;
896
+ const indentPiece = (str) => {
897
+ if (str === "") return str;
898
+ const indented = str.replace(pattern, (match, offset) => offset > 0 || shouldIndentNextCharacter ? `${resolvedIndentStr}${match}` : match);
899
+ shouldIndentNextCharacter = str[str.length - 1] === "\n";
900
+ return indented;
901
+ };
902
+ this.intro = indentPiece(this.intro);
903
+ let charIndex = 0;
904
+ let chunk = this.firstChunk;
905
+ const indentAt = (index) => {
906
+ shouldIndentNextCharacter = false;
907
+ if (index === chunk.start) chunk.appendRight(resolvedIndentStr);
908
+ else {
909
+ this._splitChunk(chunk, index);
910
+ chunk = chunk.next;
911
+ chunk.prependRight(resolvedIndentStr);
912
+ }
913
+ };
914
+ while (chunk) {
915
+ const end = chunk.end;
916
+ if (!isExcluded[chunk.start]) chunk.intro = indentPiece(chunk.intro);
917
+ if (chunk.edited) {
918
+ if (!isExcluded[charIndex]) chunk.content = indentPiece(chunk.content);
919
+ } else if (options.exclude) {
920
+ charIndex = chunk.start;
921
+ while (charIndex < end) {
922
+ if (!isExcluded[charIndex]) {
923
+ const char = this.original.charCodeAt(charIndex);
924
+ if (char === NEWLINE_CHAR) shouldIndentNextCharacter = true;
925
+ else if (char !== CR_CHAR && shouldIndentNextCharacter) indentAt(charIndex);
926
+ }
927
+ charIndex += 1;
928
+ }
929
+ } else {
930
+ charIndex = chunk.start;
931
+ while (charIndex < end) {
932
+ if (!shouldIndentNextCharacter) {
933
+ const nextLine = this.original.indexOf(n, charIndex);
934
+ if (nextLine === -1 || nextLine >= end) break;
935
+ shouldIndentNextCharacter = true;
936
+ charIndex = nextLine + 1;
937
+ continue;
938
+ }
939
+ const char = this.original.charCodeAt(charIndex);
940
+ if (char === NEWLINE_CHAR || char === CR_CHAR) {
941
+ charIndex += 1;
942
+ continue;
943
+ }
944
+ indentAt(charIndex);
945
+ charIndex += 1;
946
+ }
947
+ }
948
+ if (!isExcluded[chunk.end - 1]) chunk.outro = indentPiece(chunk.outro);
949
+ charIndex = chunk.end;
950
+ chunk = chunk.next;
951
+ }
952
+ this.outro = indentPiece(this.outro);
953
+ return this;
954
+ }
955
+ /** @internal */
956
+ insert() {
957
+ throw new MagicStringError("insert() is deprecated, use appendLeft() or prependRight()");
958
+ }
959
+ /** @internal */
960
+ insertLeft(index, content) {
961
+ if (!warned.insertLeft) {
962
+ console.warn("magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead");
963
+ warned.insertLeft = true;
964
+ }
965
+ return this.appendLeft(index, content);
966
+ }
967
+ /** @internal */
968
+ insertRight(index, content) {
969
+ if (!warned.insertRight) {
970
+ console.warn("magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead");
971
+ warned.insertRight = true;
972
+ }
973
+ return this.prependRight(index, content);
974
+ }
975
+ /**
976
+ * Moves the characters from `start` and `end` to `index`.
977
+ *
978
+ * `affinity` controls where the range is anchored at `index`. With the
979
+ * default `'right'`, it is inserted before the content that starts at `index`;
980
+ * with `'left'`, it is inserted after the content that ends at `index`. The
981
+ * two differ only when other content has already been moved to that boundary,
982
+ * mirroring the `appendLeft`/`appendRight` distinction.
983
+ */
984
+ move(start, end, index, affinity = "right") {
985
+ start = start + this.offset;
986
+ end = end + this.offset;
987
+ index = index + this.offset;
988
+ if (start === end) return this;
989
+ if (index >= start && index <= end) throw new MagicStringError("cannot move a selection inside itself");
990
+ this._split(start);
991
+ this._split(end);
992
+ this._split(index);
993
+ const first = this.byStart.get(start);
994
+ const last = this.byEnd.get(end);
995
+ if (this.hasMovedChunks) {
996
+ let cursor = first;
997
+ while (cursor !== last) {
998
+ cursor = cursor.next;
999
+ if (!cursor || cursor.start < start || cursor.end > end) throw new MagicStringError(`cannot move ${start} to ${end} because an earlier move split that range`);
1000
+ }
1001
+ }
1002
+ const oldLeft = first.previous;
1003
+ const oldRight = last.next;
1004
+ let newLeft;
1005
+ let newRight;
1006
+ if (affinity === "left") {
1007
+ newLeft = this.byEnd.get(index) ?? null;
1008
+ if (!newLeft) {
1009
+ if (first === this.firstChunk) return this;
1010
+ newRight = this.firstChunk;
1011
+ } else {
1012
+ if (newLeft.next === first) return this;
1013
+ newRight = newLeft.next;
1014
+ }
1015
+ } else {
1016
+ newRight = this.byStart.get(index) ?? null;
1017
+ if (!newRight) {
1018
+ if (last === this.lastChunk) return this;
1019
+ newLeft = this.lastChunk;
1020
+ } else {
1021
+ if (newRight.previous === last) return this;
1022
+ newLeft = newRight.previous;
1023
+ }
1024
+ }
1025
+ if (oldLeft) oldLeft.next = oldRight;
1026
+ if (oldRight) oldRight.previous = oldLeft;
1027
+ if (newLeft) newLeft.next = first;
1028
+ if (newRight) newRight.previous = last;
1029
+ if (!first.previous) this.firstChunk = last.next;
1030
+ if (!last.next) {
1031
+ this.lastChunk = first.previous;
1032
+ this.lastChunk.next = null;
1033
+ }
1034
+ first.previous = newLeft;
1035
+ last.next = newRight || null;
1036
+ if (!newLeft) this.firstChunk = first;
1037
+ if (!newRight) this.lastChunk = last;
1038
+ this.hasMovedChunks = true;
1039
+ return this;
1040
+ }
1041
+ /**
1042
+ * Replaces the characters from `start` to `end` with `content`, along with the appended/prepended content in
1043
+ * that range. The same restrictions as `s.remove()` apply.
1044
+ *
1045
+ * The fourth argument is optional. It can have a storeName property - if true, the original name will be stored
1046
+ * for later inclusion in a sourcemap's names array - and a contentOnly property which determines whether only
1047
+ * the content is overwritten, or anything that was appended/prepended to the range as well.
1048
+ *
1049
+ * It may be preferred to use `s.update(...)` instead if you wish to avoid overwriting the appended/prepended content.
1050
+ */
1051
+ overwrite(start, end, content, options) {
1052
+ const optionObject = typeof options === "object" && options ? options : {};
1053
+ return this.update(start, end, content, {
1054
+ ...optionObject,
1055
+ overwrite: !optionObject.contentOnly
1056
+ });
1057
+ }
1058
+ /**
1059
+ * Replaces the characters from `start` to `end` with `content`. The same restrictions as `s.remove()` apply.
1060
+ *
1061
+ * The fourth argument is optional. It can have a storeName property - if true, the original name will be stored
1062
+ * for later inclusion in a sourcemap's names array - and an overwrite property which determines whether only
1063
+ * the content is overwritten, or anything that was appended/prepended to the range as well.
1064
+ */
1065
+ update(start, end, content, options) {
1066
+ start = start + this.offset;
1067
+ end = end + this.offset;
1068
+ if (typeof content !== "string") throw new MagicStringError(`content must be a string, got ${typeof content}`);
1069
+ if (this.original.length !== 0) {
1070
+ if (start < 0) start = Math.max(0, start + this.original.length);
1071
+ if (end < 0) end = Math.max(0, end + this.original.length);
1072
+ }
1073
+ if (start < 0) throw new MagicStringError(`start ${start} is out of bounds`);
1074
+ if (end > this.original.length) throw new MagicStringError(`end ${end} is out of bounds`);
1075
+ if (start === end) throw new MagicStringError(`cannot overwrite a zero-length range at ${start}, use appendLeft() or prependRight()`);
1076
+ if (start > end) throw new MagicStringError(`end must be greater than start (start: ${start}, end: ${end})`);
1077
+ this._split(start);
1078
+ this._split(end);
1079
+ if (options === true) {
1080
+ if (!warned.storeName) {
1081
+ console.warn("The final argument to magicString.overwrite(...) should be an options object. See https://github.com/rich-harris/magic-string");
1082
+ warned.storeName = true;
1083
+ }
1084
+ options = { storeName: true };
1085
+ }
1086
+ const optionObject = typeof options === "object" && options ? options : {};
1087
+ const storeName = optionObject.storeName || false;
1088
+ const overwrite = optionObject.overwrite || false;
1089
+ if (storeName) {
1090
+ const original = this.original.slice(start, end);
1091
+ Object.defineProperty(this.storedNames, original, {
1092
+ writable: true,
1093
+ value: true,
1094
+ enumerable: true
1095
+ });
1096
+ }
1097
+ const first = this.byStart.get(start);
1098
+ const last = this.byEnd.get(end);
1099
+ /* v8 ignore else -- unreachable: a valid start/end always yields a `first` chunk */
1100
+ if (first) {
1101
+ let chunk = first;
1102
+ while (chunk !== last) {
1103
+ if (chunk.next !== this.byStart.get(chunk.end)) throw new MagicStringError("cannot overwrite across a split point");
1104
+ chunk = chunk.next;
1105
+ chunk.edit("", false);
1106
+ }
1107
+ first.edit(content, storeName, !overwrite);
1108
+ } else {
1109
+ const newChunk = new Chunk(start, end, "").edit(content, storeName);
1110
+ last.next = newChunk;
1111
+ newChunk.previous = last;
1112
+ }
1113
+ return this;
1114
+ }
1115
+ /**
1116
+ * Prepends the string with the specified content.
1117
+ */
1118
+ prepend(content) {
1119
+ if (typeof content !== "string") throw new MagicStringError(`content must be a string, got ${typeof content}`);
1120
+ this.intro = content + this.intro;
1121
+ return this;
1122
+ }
1123
+ /**
1124
+ * Same as `s.appendLeft(...)`, except that the inserted content will go *before* any previous appends or prepends at index
1125
+ */
1126
+ prependLeft(index, content) {
1127
+ index = index + this.offset;
1128
+ if (typeof content !== "string") throw new MagicStringError(`content must be a string, got ${typeof content}`);
1129
+ this._split(index);
1130
+ const chunk = this.byEnd.get(index);
1131
+ if (chunk) chunk.prependLeft(content);
1132
+ else this.intro = content + this.intro;
1133
+ return this;
1134
+ }
1135
+ /**
1136
+ * Same as `s.appendRight(...)`, except that the inserted content will go *before* any previous appends or prepends at `index`
1137
+ */
1138
+ prependRight(index, content) {
1139
+ index = index + this.offset;
1140
+ if (typeof content !== "string") throw new MagicStringError(`content must be a string, got ${typeof content}`);
1141
+ this._split(index);
1142
+ const chunk = this.byStart.get(index);
1143
+ if (chunk) chunk.prependRight(content);
1144
+ else this.outro = content + this.outro;
1145
+ return this;
1146
+ }
1147
+ /**
1148
+ * Removes the characters from `start` to `end` (of the original string, **not** the generated string).
1149
+ * Content appended or prepended at positions strictly inside the range is removed with it, while
1150
+ * content attached at `start` or `end` is preserved — use `s.overwrite(start, end, '')` to remove
1151
+ * the range including its edge inserts.
1152
+ * Removing the same content twice, or making removals that partially overlap, will cause an error.
1153
+ */
1154
+ remove(start, end) {
1155
+ start = start + this.offset;
1156
+ end = end + this.offset;
1157
+ if (this.original.length !== 0) {
1158
+ if (start < 0) start = Math.max(0, start + this.original.length);
1159
+ if (end < 0) end = Math.max(0, end + this.original.length);
1160
+ }
1161
+ if (start === end) return this;
1162
+ if (start < 0 || end > this.original.length) throw new MagicStringError(`range ${start}–${end} is out of bounds`);
1163
+ if (start > end) throw new MagicStringError(`end must be greater than start (start: ${start}, end: ${end})`);
1164
+ this._split(start);
1165
+ this._split(end);
1166
+ let chunk = this.byStart.get(start);
1167
+ while (chunk) {
1168
+ if (chunk.start > start) chunk.intro = "";
1169
+ if (chunk.end < end) chunk.outro = "";
1170
+ chunk.edit("", false, true);
1171
+ chunk = end > chunk.end ? this.byStart.get(chunk.end) : null;
1172
+ }
1173
+ return this;
1174
+ }
1175
+ /**
1176
+ * Reset the modified characters from `start` to `end` (of the original string, **not** the generated string).
1177
+ */
1178
+ reset(start, end) {
1179
+ start = start + this.offset;
1180
+ end = end + this.offset;
1181
+ if (this.original.length !== 0) {
1182
+ if (start < 0) start = Math.max(0, start + this.original.length);
1183
+ if (end < 0) end = Math.max(0, end + this.original.length);
1184
+ }
1185
+ if (start === end) return this;
1186
+ if (start < 0 || end > this.original.length) throw new MagicStringError(`range ${start}–${end} is out of bounds`);
1187
+ if (start > end) throw new MagicStringError(`end must be greater than start (start: ${start}, end: ${end})`);
1188
+ this._split(start);
1189
+ this._split(end);
1190
+ let chunk = this.byStart.get(start);
1191
+ while (chunk) {
1192
+ chunk.reset();
1193
+ chunk = end > chunk.end ? this.byStart.get(chunk.end) : null;
1194
+ }
1195
+ return this;
1196
+ }
1197
+ lastChar() {
1198
+ if (this.outro.length) return this.outro[this.outro.length - 1];
1199
+ let chunk = this.lastChunk;
1200
+ while (chunk) {
1201
+ if (chunk.outro.length) return chunk.outro[chunk.outro.length - 1];
1202
+ if (chunk.content.length) return chunk.content[chunk.content.length - 1];
1203
+ if (chunk.intro.length) return chunk.intro[chunk.intro.length - 1];
1204
+ chunk = chunk.previous;
1205
+ }
1206
+ if (this.intro.length) return this.intro[this.intro.length - 1];
1207
+ return "";
1208
+ }
1209
+ lastLine() {
1210
+ let lineIndex = this.outro.lastIndexOf(n);
1211
+ if (lineIndex !== -1) return this.outro.substr(lineIndex + 1);
1212
+ let lineStr = this.outro;
1213
+ let chunk = this.lastChunk;
1214
+ while (chunk) {
1215
+ if (chunk.outro.length > 0) {
1216
+ lineIndex = chunk.outro.lastIndexOf(n);
1217
+ if (lineIndex !== -1) return chunk.outro.substr(lineIndex + 1) + lineStr;
1218
+ lineStr = chunk.outro + lineStr;
1219
+ }
1220
+ if (chunk.content.length > 0) {
1221
+ lineIndex = chunk.content.lastIndexOf(n);
1222
+ if (lineIndex !== -1) return chunk.content.substr(lineIndex + 1) + lineStr;
1223
+ lineStr = chunk.content + lineStr;
1224
+ }
1225
+ if (chunk.intro.length > 0) {
1226
+ lineIndex = chunk.intro.lastIndexOf(n);
1227
+ if (lineIndex !== -1) return chunk.intro.substr(lineIndex + 1) + lineStr;
1228
+ lineStr = chunk.intro + lineStr;
1229
+ }
1230
+ chunk = chunk.previous;
1231
+ }
1232
+ lineIndex = this.intro.lastIndexOf(n);
1233
+ if (lineIndex !== -1) return this.intro.substr(lineIndex + 1) + lineStr;
1234
+ return this.intro + lineStr;
1235
+ }
1236
+ /**
1237
+ * Returns the content of the generated string that corresponds to the slice between `start` and `end` of the original string.
1238
+ * Throws error if the indices are for characters that were already removed.
1239
+ */
1240
+ slice(start = 0, end = this.original.length - this.offset) {
1241
+ start = start + this.offset;
1242
+ end = end + this.offset;
1243
+ if (this.original.length !== 0) {
1244
+ if (start < 0) start = Math.max(0, start + this.original.length);
1245
+ if (end < 0) end = Math.max(0, end + this.original.length);
1246
+ }
1247
+ let result = "";
1248
+ let chunk = this.firstChunk;
1249
+ while (chunk && (chunk.start > start || chunk.end <= start)) {
1250
+ if (chunk.start < end && chunk.end >= end || end === 0 && chunk.start === 0) return result;
1251
+ chunk = chunk.next;
1252
+ }
1253
+ if (chunk && chunk.edited && chunk.start !== start) throw new MagicStringError(`cannot use edited character ${start} as slice start anchor`);
1254
+ const startChunk = chunk;
1255
+ while (chunk) {
1256
+ if (end === 0 && chunk.start === 0) break;
1257
+ if (chunk.intro && (startChunk !== chunk || chunk.start === start)) result += chunk.intro;
1258
+ const containsEnd = chunk.start < end && chunk.end >= end;
1259
+ if (containsEnd && chunk.edited && chunk.end !== end) throw new MagicStringError(`cannot use edited character ${end} as slice end anchor`);
1260
+ const sliceStart = startChunk === chunk ? start - chunk.start : 0;
1261
+ const sliceEnd = containsEnd ? chunk.content.length + end - chunk.end : chunk.content.length;
1262
+ result += chunk.content.slice(sliceStart, sliceEnd);
1263
+ if (chunk.outro && (!containsEnd || chunk.end === end)) result += chunk.outro;
1264
+ if (containsEnd) break;
1265
+ chunk = chunk.next;
1266
+ }
1267
+ return result;
1268
+ }
1269
+ /**
1270
+ * Returns a clone of `s`, with all content before the `start` and `end` characters of the original string removed.
1271
+ */
1272
+ snip(start, end) {
1273
+ const clone = this.clone();
1274
+ clone.remove(0, start);
1275
+ clone.remove(end, clone.original.length);
1276
+ return clone;
1277
+ }
1278
+ /** @internal */
1279
+ _split(index) {
1280
+ if (this.byStart.get(index) || this.byEnd.get(index)) return;
1281
+ let chunk = this.lastSearchedChunk;
1282
+ let previousChunk = chunk;
1283
+ const searchForward = index > chunk.end;
1284
+ while (chunk) {
1285
+ if (chunk.contains(index)) return this._splitChunk(chunk, index);
1286
+ chunk = searchForward ? this.byStart.get(chunk.end) : this.byEnd.get(chunk.start);
1287
+ if (chunk === previousChunk) return;
1288
+ previousChunk = chunk;
1289
+ }
1290
+ }
1291
+ /** @internal */
1292
+ _splitChunk(chunk, index) {
1293
+ if (chunk.edited && chunk.content.length) {
1294
+ const loc = getLocator(this.original)(index);
1295
+ throw new MagicStringError(`cannot split a chunk that has already been edited (${loc.line}:${loc.column} – "${chunk.original}")`);
1296
+ }
1297
+ const newChunk = chunk.split(index);
1298
+ this.byEnd.set(index, chunk);
1299
+ this.byStart.set(index, newChunk);
1300
+ this.byEnd.set(newChunk.end, newChunk);
1301
+ if (chunk === this.lastChunk) this.lastChunk = newChunk;
1302
+ this.lastSearchedChunk = chunk;
1303
+ return true;
1304
+ }
1305
+ /**
1306
+ * Returns the generated string.
1307
+ */
1308
+ toString() {
1309
+ let str = this.intro;
1310
+ let chunk = this.firstChunk;
1311
+ while (chunk) {
1312
+ str += chunk.toString();
1313
+ chunk = chunk.next;
1314
+ }
1315
+ return str + this.outro;
1316
+ }
1317
+ /**
1318
+ * Returns true if the resulting source is empty (disregarding white space).
1319
+ */
1320
+ isEmpty() {
1321
+ if (this.intro.length && this.intro.trim()) return false;
1322
+ let chunk = this.firstChunk;
1323
+ while (chunk) {
1324
+ if (chunk.intro.length && chunk.intro.trim() || chunk.content.length && chunk.content.trim() || chunk.outro.length && chunk.outro.trim()) return false;
1325
+ chunk = chunk.next;
1326
+ }
1327
+ if (this.outro.length && this.outro.trim()) return false;
1328
+ return true;
1329
+ }
1330
+ length() {
1331
+ let chunk = this.firstChunk;
1332
+ let length = 0;
1333
+ while (chunk) {
1334
+ length += chunk.intro.length + chunk.content.length + chunk.outro.length;
1335
+ chunk = chunk.next;
1336
+ }
1337
+ return length;
1338
+ }
1339
+ /**
1340
+ * Removes empty lines from the start and end.
1341
+ */
1342
+ trimLines() {
1343
+ return this.trim("[\\r\\n]");
1344
+ }
1345
+ /**
1346
+ * Trims content matching `charType` (defaults to `\s`, i.e. whitespace) from the start and end.
1347
+ */
1348
+ trim(charType) {
1349
+ return this.trimStart(charType).trimEnd(charType);
1350
+ }
1351
+ /** @internal */
1352
+ trimEndAborted(charType) {
1353
+ const rx = new RegExp(`${charType || "\\s"}+$`);
1354
+ this.outro = this.outro.replace(rx, "");
1355
+ if (this.outro.length) return true;
1356
+ let chunk = this.lastChunk;
1357
+ do {
1358
+ const end = chunk.end;
1359
+ const aborted = chunk.trimEnd(rx);
1360
+ if (chunk.end !== end) {
1361
+ if (this.lastChunk === chunk) this.lastChunk = chunk.next;
1362
+ this.byEnd.set(chunk.end, chunk);
1363
+ this.byStart.set(chunk.next.start, chunk.next);
1364
+ this.byEnd.set(chunk.next.end, chunk.next);
1365
+ }
1366
+ if (aborted) return true;
1367
+ chunk = chunk.previous;
1368
+ } while (chunk);
1369
+ this.intro = this.intro.replace(rx, "");
1370
+ return this.intro.length > 0;
1371
+ }
1372
+ /**
1373
+ * Trims content matching `charType` (defaults to `\s`, i.e. whitespace) from the end.
1374
+ */
1375
+ trimEnd(charType) {
1376
+ this.trimEndAborted(charType);
1377
+ return this;
1378
+ }
1379
+ /** @internal */
1380
+ trimStartAborted(charType) {
1381
+ const rx = new RegExp(`^${charType || "\\s"}+`);
1382
+ this.intro = this.intro.replace(rx, "");
1383
+ if (this.intro.length) return true;
1384
+ let chunk = this.firstChunk;
1385
+ do {
1386
+ const end = chunk.end;
1387
+ const aborted = chunk.trimStart(rx);
1388
+ if (chunk.end !== end) {
1389
+ if (chunk === this.lastChunk) this.lastChunk = chunk.next;
1390
+ this.byEnd.set(chunk.end, chunk);
1391
+ this.byStart.set(chunk.next.start, chunk.next);
1392
+ this.byEnd.set(chunk.next.end, chunk.next);
1393
+ }
1394
+ if (aborted) return true;
1395
+ chunk = chunk.next;
1396
+ } while (chunk);
1397
+ this.outro = this.outro.replace(rx, "");
1398
+ return this.outro.length > 0;
1399
+ }
1400
+ /**
1401
+ * Trims content matching `charType` (defaults to `\s`, i.e. whitespace) from the start.
1402
+ */
1403
+ trimStart(charType) {
1404
+ this.trimStartAborted(charType);
1405
+ return this;
1406
+ }
1407
+ /**
1408
+ * Indicates if the string has been changed.
1409
+ */
1410
+ hasChanged() {
1411
+ if (this.intro || this.outro) return true;
1412
+ let outputIndex = 0;
1413
+ let chunk = this.firstChunk;
1414
+ while (chunk) {
1415
+ if (chunk.intro || chunk.outro) return true;
1416
+ if (!chunk.edited && chunk.start === outputIndex) outputIndex = chunk.end;
1417
+ else {
1418
+ if (!this.original.startsWith(chunk.content, outputIndex)) return true;
1419
+ outputIndex += chunk.content.length;
1420
+ }
1421
+ chunk = chunk.next;
1422
+ }
1423
+ return outputIndex !== this.original.length;
1424
+ }
1425
+ /**
1426
+ * Whether the original range [start, end) has had any of its characters
1427
+ * removed. `replace`/`replaceAll` search `original`, so a match can land on
1428
+ * text that is no longer in the output - overwriting it would resurrect the
1429
+ * removed characters, so such matches are skipped instead.
1430
+ *
1431
+ * @internal
1432
+ */
1433
+ _hasRemovedContent(start, end) {
1434
+ let chunk = this.firstChunk;
1435
+ while (chunk) {
1436
+ if (chunk.content === "" && chunk.start < end && chunk.end > start) return true;
1437
+ chunk = chunk.next;
1438
+ }
1439
+ return false;
1440
+ }
1441
+ /** @internal */
1442
+ _replaceRegexp(searchValue, replacement) {
1443
+ function getReplacement(match, str) {
1444
+ if (typeof replacement === "string") return expandReplacement(replacement, match[0], match.index, str, match.slice(1), match.groups);
1445
+ else return match.groups === void 0 ? replacement(match[0], ...match.slice(1), match.index, str) : replacement(match[0], ...match.slice(1), match.index, str, match.groups);
1446
+ }
1447
+ const replaceMatch = (match) => {
1448
+ /* v8 ignore next 2 -- `match.index` is always defined for matches from `matchAll` */
1449
+ if (match.index == null) return false;
1450
+ if (this._hasRemovedContent(match.index, match.index + match[0].length)) return false;
1451
+ const replacement = getReplacement(match, this.original);
1452
+ if (replacement === match[0]) return true;
1453
+ if (match[0].length === 0) this.appendRight(match.index, replacement);
1454
+ else this.overwrite(match.index, match.index + match[0].length, replacement);
1455
+ return true;
1456
+ };
1457
+ if (searchValue.global) {
1458
+ searchValue.lastIndex = 0;
1459
+ for (const match of this.original.matchAll(searchValue)) replaceMatch(match);
1460
+ } else {
1461
+ const match = this.original.match(searchValue);
1462
+ if (match && !replaceMatch(match)) {
1463
+ const global = new RegExp(searchValue.source, `${searchValue.flags}g`);
1464
+ for (const next of this.original.matchAll(global)) if (replaceMatch(next)) break;
1465
+ }
1466
+ }
1467
+ return this;
1468
+ }
1469
+ /** @internal */
1470
+ _replaceString(string, replacement) {
1471
+ const { original } = this;
1472
+ let index = original.indexOf(string);
1473
+ while (index !== -1) {
1474
+ if (this._hasRemovedContent(index, index + string.length)) {
1475
+ index = original.indexOf(string, index + string.length);
1476
+ continue;
1477
+ }
1478
+ if (typeof replacement === "function") replacement = replacement(string, index, original);
1479
+ else replacement = expandReplacement(replacement, string, index, original, [], void 0);
1480
+ if (string !== replacement) {
1481
+ if (string.length === 0) this.appendRight(index, replacement);
1482
+ else this.overwrite(index, index + string.length, replacement);
1483
+ }
1484
+ break;
1485
+ }
1486
+ return this;
1487
+ }
1488
+ /**
1489
+ * String replacement with RegExp or string.
1490
+ */
1491
+ replace(searchValue, replacement) {
1492
+ if (typeof searchValue === "string") return this._replaceString(searchValue, replacement);
1493
+ return this._replaceRegexp(searchValue, replacement);
1494
+ }
1495
+ /** @internal */
1496
+ _replaceAllString(string, replacement) {
1497
+ const { original } = this;
1498
+ const stringLength = string.length;
1499
+ if (stringLength === 0) {
1500
+ for (let index = 0; index <= original.length; index += 1) {
1501
+ const _replacement = typeof replacement === "function" ? replacement("", index, original) : expandReplacement(replacement, "", index, original, [], void 0);
1502
+ if (_replacement !== "") this.appendRight(index, _replacement);
1503
+ }
1504
+ return this;
1505
+ }
1506
+ for (let index = original.indexOf(string); index !== -1; index = original.indexOf(string, index + stringLength)) {
1507
+ if (this._hasRemovedContent(index, index + stringLength)) continue;
1508
+ const previous = original.slice(index, index + stringLength);
1509
+ const _replacement = typeof replacement === "function" ? replacement(previous, index, original) : expandReplacement(replacement, previous, index, original, [], void 0);
1510
+ if (previous !== _replacement) this.overwrite(index, index + stringLength, _replacement);
1511
+ }
1512
+ return this;
1513
+ }
1514
+ /**
1515
+ * Same as `s.replace`, but replace all matched strings instead of just one.
1516
+ */
1517
+ replaceAll(searchValue, replacement) {
1518
+ if (typeof searchValue === "string") return this._replaceAllString(searchValue, replacement);
1519
+ if (!searchValue.global) throw new MagicStringError("replaceAll() requires a global RegExp");
1520
+ return this._replaceRegexp(searchValue, replacement);
1521
+ }
1522
+ };
1523
+ //#endregion
1524
+ export { MagicString, MagicString as default };