spliterator 2.2.2 → 3.0.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 (87) hide show
  1. package/LICENSE.md +21 -650
  2. package/README.md +42 -0
  3. package/out/index.d.ts +2 -1
  4. package/out/index.d.ts.map +1 -1
  5. package/out/index.js +2 -1
  6. package/out/index.js.map +1 -1
  7. package/out/lib/AsyncSpliterator.d.ts +33 -28
  8. package/out/lib/AsyncSpliterator.d.ts.map +1 -1
  9. package/out/lib/AsyncSpliterator.js +84 -70
  10. package/out/lib/AsyncSpliterator.js.map +1 -1
  11. package/out/lib/BufferController.d.ts +1 -1
  12. package/out/lib/BufferController.js +1 -1
  13. package/out/lib/CSVSpliterator.d.ts +1 -1
  14. package/out/lib/CSVSpliterator.d.ts.map +1 -1
  15. package/out/lib/CSVSpliterator.js +5 -3
  16. package/out/lib/CSVSpliterator.js.map +1 -1
  17. package/out/lib/CharacterSequence.d.ts +15 -64
  18. package/out/lib/CharacterSequence.d.ts.map +1 -1
  19. package/out/lib/CharacterSequence.js +194 -89
  20. package/out/lib/CharacterSequence.js.map +1 -1
  21. package/out/lib/CompositeDataView.d.ts +1 -1
  22. package/out/lib/CompositeDataView.js +1 -1
  23. package/out/lib/IndexQueue.d.ts +1 -1
  24. package/out/lib/IndexQueue.d.ts.map +1 -1
  25. package/out/lib/IndexQueue.js +40 -11
  26. package/out/lib/IndexQueue.js.map +1 -1
  27. package/out/lib/JSONSpliterator.d.ts +1 -1
  28. package/out/lib/JSONSpliterator.js +1 -1
  29. package/out/lib/PSVSpliterator.d.ts +1 -1
  30. package/out/lib/PSVSpliterator.js +1 -1
  31. package/out/lib/SlidingWindow.d.ts +1 -1
  32. package/out/lib/SlidingWindow.d.ts.map +1 -1
  33. package/out/lib/SlidingWindow.js +11 -10
  34. package/out/lib/SlidingWindow.js.map +1 -1
  35. package/out/lib/Spliterator.d.ts +1 -1
  36. package/out/lib/Spliterator.d.ts.map +1 -1
  37. package/out/lib/Spliterator.js +99 -110
  38. package/out/lib/Spliterator.js.map +1 -1
  39. package/out/lib/TSVSpliterator.d.ts +1 -1
  40. package/out/lib/TSVSpliterator.js +1 -1
  41. package/out/lib/TextSpliterator.d.ts +1 -1
  42. package/out/lib/TextSpliterator.js +1 -1
  43. package/out/lib/casing.d.ts +1 -1
  44. package/out/lib/casing.js +1 -1
  45. package/out/lib/segment-runtime.d.ts +27 -0
  46. package/out/lib/segment-runtime.d.ts.map +1 -0
  47. package/out/lib/segment-runtime.js +38 -0
  48. package/out/lib/segment-runtime.js.map +1 -0
  49. package/out/lib/segment-worker-entry.d.ts +10 -0
  50. package/out/lib/segment-worker-entry.d.ts.map +1 -0
  51. package/out/lib/segment-worker-entry.js +56 -0
  52. package/out/lib/segment-worker-entry.js.map +1 -0
  53. package/out/lib/segment-workers.d.ts +41 -0
  54. package/out/lib/segment-workers.d.ts.map +1 -0
  55. package/out/lib/segment-workers.js +105 -0
  56. package/out/lib/segment-workers.js.map +1 -0
  57. package/out/lib/segments.d.ts +25 -0
  58. package/out/lib/segments.d.ts.map +1 -0
  59. package/out/lib/segments.js +50 -0
  60. package/out/lib/segments.js.map +1 -0
  61. package/out/lib/shared.d.ts +1 -1
  62. package/out/lib/shared.js +1 -1
  63. package/out/lib/take.d.ts +1 -1
  64. package/out/lib/take.js +1 -1
  65. package/out/lib/wasm_base64.d.ts +16 -0
  66. package/out/lib/wasm_base64.d.ts.map +1 -0
  67. package/out/lib/wasm_base64.js +16 -0
  68. package/out/lib/wasm_base64.js.map +1 -0
  69. package/out/lib/wasm_module.d.ts +36 -0
  70. package/out/lib/wasm_module.d.ts.map +1 -0
  71. package/out/lib/wasm_module.js +33 -0
  72. package/out/lib/wasm_module.js.map +1 -0
  73. package/out/lib/writer.d.ts +1 -1
  74. package/out/lib/writer.js +1 -1
  75. package/out/node/cli/commands/csv.d.ts +1 -1
  76. package/out/node/cli/commands/csv.js +1 -1
  77. package/out/node/cli/commands/iterate.d.ts +1 -1
  78. package/out/node/cli/commands/iterate.js +1 -1
  79. package/out/node/cli/index.d.ts +1 -1
  80. package/out/node/cli/index.js +1 -1
  81. package/out/node/cli/utils.d.ts +1 -1
  82. package/out/node/cli/utils.js +1 -1
  83. package/out/node/fs/index.d.ts +14 -2
  84. package/out/node/fs/index.d.ts.map +1 -1
  85. package/out/node/fs/index.js +26 -2
  86. package/out/node/fs/index.js.map +1 -1
  87. package/package.json +5 -3
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license MIT
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * Runs inside a worker thread (spawned by runSegmentWorkers). Reads its segment via its own handle,
7
+ * runs the user handler per record, and posts batched results to the parent with ack backpressure.
8
+ */
9
+ import { parentPort, workerData } from "node:worker_threads";
10
+ import { AsyncSpliterator } from "./AsyncSpliterator.js";
11
+ import { runSegment } from "./segment-runtime.js";
12
+ async function main() {
13
+ const data = workerData;
14
+ const port = parentPort;
15
+ // Ack backpressure: the parent posts `"ack"` per consumed batch; we track outstanding batches.
16
+ let acked = 0;
17
+ let posted = 0;
18
+ let wakeAck;
19
+ port.on("message", (msg) => {
20
+ if (msg === "ack") {
21
+ acked++;
22
+ wakeAck?.();
23
+ wakeAck = undefined;
24
+ }
25
+ });
26
+ const mod = (await import(data.handlerUrl));
27
+ const handleRecord = mod.handleRecord ?? mod.default;
28
+ if (typeof handleRecord !== "function") {
29
+ port.postMessage({ type: "error", message: `Worker module ${data.handlerUrl} has no handleRecord export.` });
30
+ return;
31
+ }
32
+ const { createChunkIterator } = await import("spliterator/node/fs");
33
+ const chunkIterator = await createChunkIterator(data.source, { start: data.start, end: data.end - 1 });
34
+ const records = new AsyncSpliterator(chunkIterator, { delimiter: data.delimiter, autoDispose: true });
35
+ try {
36
+ await runSegment({
37
+ records,
38
+ handleRecord,
39
+ segmentIndex: data.segmentIndex,
40
+ batchSize: data.batchSize,
41
+ maxInFlight: data.maxInFlight,
42
+ post: (batch, transfer) => {
43
+ posted++;
44
+ port.postMessage({ type: "batch", records: batch }, transfer);
45
+ },
46
+ waitForAck: () => new Promise((resolve) => (wakeAck = resolve)),
47
+ inFlight: () => posted - acked,
48
+ });
49
+ port.postMessage({ type: "done" });
50
+ }
51
+ catch (error) {
52
+ port.postMessage({ type: "error", message: error instanceof Error ? error.message : String(error) });
53
+ }
54
+ }
55
+ void main();
56
+ //# sourceMappingURL=segment-worker-entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segment-worker-entry.js","sourceRoot":"","sources":["../../lib/segment-worker-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAE5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,UAAU,EAAuB,MAAM,sBAAsB,CAAA;AActE,KAAK,UAAU,IAAI;IAClB,MAAM,IAAI,GAAG,UAAwB,CAAA;IACrC,MAAM,IAAI,GAAG,UAAW,CAAA;IAExB,+FAA+F;IAC/F,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,IAAI,MAAM,GAAG,CAAC,CAAA;IACd,IAAI,OAAiC,CAAA;IAErC,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAY,EAAE,EAAE;QACnC,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;YACnB,KAAK,EAAE,CAAA;YACP,OAAO,EAAE,EAAE,CAAA;YACX,OAAO,GAAG,SAAS,CAAA;QACpB,CAAC;IACF,CAAC,CAAC,CAAA;IAEF,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAgE,CAAA;IAC1G,MAAM,YAAY,GAAG,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,OAAO,CAAA;IAEpD,IAAI,OAAO,YAAY,KAAK,UAAU,EAAE,CAAC;QACxC,IAAI,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,iBAAiB,IAAI,CAAC,UAAU,8BAA8B,EAAE,CAAC,CAAA;QAE5G,OAAM;IACP,CAAC;IAED,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAA;IACnE,MAAM,aAAa,GAAG,MAAM,mBAAmB,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,CAAA;IACtG,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,SAAkB,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAA;IAE9G,IAAI,CAAC;QACJ,MAAM,UAAU,CAAC;YAChB,OAAO;YACP,YAAY;YACZ,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,IAAI,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;gBACzB,MAAM,EAAE,CAAA;gBACR,IAAI,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,QAAQ,CAAC,CAAA;YAC9D,CAAC;YACD,UAAU,EAAE,GAAG,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,GAAG,OAAO,CAAC,CAAC;YACrE,QAAQ,EAAE,GAAG,EAAE,CAAC,MAAM,GAAG,KAAK;SAC9B,CAAC,CAAA;QAEF,IAAI,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAA;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,IAAI,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;IACrG,CAAC;AACF,CAAC;AAED,KAAK,IAAI,EAAE,CAAA"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license MIT
4
+ * @author Teffen Ellis, et al.
5
+ */
6
+ import type { CharacterSequenceInput } from "./CharacterSequence.js";
7
+ import type { AsyncDataResource } from "./shared.js";
8
+ export interface MinimalWorker {
9
+ on(event: "message", cb: (msg: unknown) => void): void;
10
+ on(event: "error", cb: (err: Error) => void): void;
11
+ }
12
+ /**
13
+ * Drain a worker's batched messages into an async iterator. Listeners attach **eagerly** (messages posted before
14
+ * iteration starts are buffered, not lost) and draining uses a `batches[] + head` pointer (no `Array.shift()`).
15
+ * `onBatchConsumed` fires once per batch after its records are yielded — the ack hook for backpressure. An `error`
16
+ * message or worker `error` rejects the iterator.
17
+ */
18
+ export declare function workerToIterable<R>(worker: MinimalWorker, onBatchConsumed: () => void): AsyncIterableIterator<R>;
19
+ export interface AsManyWorkersOptions {
20
+ /** Module path or URL exporting `handleRecord(bytes, ctx)`. Runs once per worker at import. */
21
+ worker: string | URL;
22
+ /** The record delimiter. @default LineFeed */
23
+ delimiter?: CharacterSequenceInput;
24
+ /** Desired number of segments/workers. Clamped to ≥ 1; fewer may run. */
25
+ concurrency: number;
26
+ /** Bytes read at each ideal boundary to find the next delimiter. @default 65536 */
27
+ probeSize?: number;
28
+ /** Results per message. @default 256 */
29
+ batchSize?: number;
30
+ /** Unacked batches per worker before it pauses. @default 4 */
31
+ maxInFlight?: number;
32
+ /** Forwarded to every worker via `workerData.userData`. */
33
+ workerData?: unknown;
34
+ }
35
+ /**
36
+ * Spawn one worker per delimiter-aligned segment, each running the `worker` handler module over its own handle, and
37
+ * merge their results into a single async iterator. Results interleave across segments. Sends an `ack` per consumed
38
+ * batch (backpressure); terminates all workers on completion, error, or early return.
39
+ */
40
+ export declare function runSegmentWorkers<R>(source: AsyncDataResource, options: AsManyWorkersOptions): AsyncIterableIterator<R>;
41
+ //# sourceMappingURL=segment-workers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segment-workers.d.ts","sourceRoot":"","sources":["../../lib/segment-workers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAA;AAEpE,OAAO,KAAK,EAAE,iBAAiB,EAAa,MAAM,aAAa,CAAA;AAE/D,MAAM,WAAW,aAAa;IAC7B,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAA;IACtD,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAA;CAClD;AAID;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,IAAI,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAmDhH;AAED,MAAM,WAAW,oBAAoB;IACpC,+FAA+F;IAC/F,MAAM,EAAE,MAAM,GAAG,GAAG,CAAA;IACpB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,sBAAsB,CAAA;IAClC,yEAAyE;IACzE,WAAW,EAAE,MAAM,CAAA;IACnB,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,2DAA2D;IAC3D,UAAU,CAAC,EAAE,OAAO,CAAA;CACpB;AAED;;;;GAIG;AACH,wBAAuB,iBAAiB,CAAC,CAAC,EACzC,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,oBAAoB,GAC3B,qBAAqB,CAAC,CAAC,CAAC,CA8C1B"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license MIT
4
+ * @author Teffen Ellis, et al.
5
+ */
6
+ import { Worker } from "node:worker_threads";
7
+ import { computeSegments } from "./segments.js";
8
+ /**
9
+ * Drain a worker's batched messages into an async iterator. Listeners attach **eagerly** (messages posted before
10
+ * iteration starts are buffered, not lost) and draining uses a `batches[] + head` pointer (no `Array.shift()`).
11
+ * `onBatchConsumed` fires once per batch after its records are yielded — the ack hook for backpressure. An `error`
12
+ * message or worker `error` rejects the iterator.
13
+ */
14
+ export function workerToIterable(worker, onBatchConsumed) {
15
+ const batches = [];
16
+ let head = 0;
17
+ let done = false;
18
+ let error;
19
+ let wake;
20
+ const signal = () => {
21
+ wake?.();
22
+ wake = undefined;
23
+ };
24
+ worker.on("message", (msg) => {
25
+ const m = msg;
26
+ if (m.type === "batch")
27
+ batches.push(m.records);
28
+ else if (m.type === "done")
29
+ done = true;
30
+ else if (m.type === "error") {
31
+ error = new Error(m.message);
32
+ done = true;
33
+ }
34
+ signal();
35
+ });
36
+ worker.on("error", (err) => {
37
+ error = err;
38
+ done = true;
39
+ signal();
40
+ });
41
+ async function* drain() {
42
+ for (;;) {
43
+ if (head < batches.length) {
44
+ const batch = batches[head++];
45
+ for (const record of batch)
46
+ yield record;
47
+ onBatchConsumed();
48
+ continue;
49
+ }
50
+ if (error)
51
+ throw error;
52
+ if (done)
53
+ return;
54
+ await new Promise((resolve) => (wake = resolve));
55
+ }
56
+ }
57
+ return drain();
58
+ }
59
+ /**
60
+ * Spawn one worker per delimiter-aligned segment, each running the `worker` handler module over its own handle, and
61
+ * merge their results into a single async iterator. Results interleave across segments. Sends an `ack` per consumed
62
+ * batch (backpressure); terminates all workers on completion, error, or early return.
63
+ */
64
+ export async function* runSegmentWorkers(source, options) {
65
+ if (typeof source !== "string" && !(source instanceof URL)) {
66
+ throw new TypeError("asManyWorkers requires a file path or URL — file handles cannot cross threads.");
67
+ }
68
+ const handlerUrl = options.worker instanceof URL ? options.worker.href : new URL(options.worker, `file://${process.cwd()}/`).href;
69
+ const sourcePath = source instanceof URL ? source.href : source;
70
+ const segments = await computeSegments(source, {
71
+ delimiter: options.delimiter,
72
+ concurrency: options.concurrency,
73
+ probeSize: options.probeSize,
74
+ });
75
+ const workers = [];
76
+ const entryUrl = new URL("./segment-worker-entry.js", import.meta.url);
77
+ try {
78
+ const iterables = segments.map(([start, end], segmentIndex) => {
79
+ const worker = new Worker(entryUrl, {
80
+ workerData: {
81
+ source: sourcePath,
82
+ handlerUrl,
83
+ start,
84
+ end,
85
+ delimiter: options.delimiter ?? null,
86
+ segmentIndex,
87
+ batchSize: options.batchSize ?? 256,
88
+ maxInFlight: options.maxInFlight ?? 4,
89
+ userData: options.workerData,
90
+ },
91
+ });
92
+ workers.push(worker);
93
+ return workerToIterable(worker, () => worker.postMessage("ack"));
94
+ });
95
+ // Each worker runs concurrently and fills ahead (bounded by maxInFlight); draining their
96
+ // iterators in turn still interleaves wall-clock work. Order across segments is not guaranteed.
97
+ for (const iterable of iterables) {
98
+ yield* iterable;
99
+ }
100
+ }
101
+ finally {
102
+ await Promise.all(workers.map((w) => w.terminate()));
103
+ }
104
+ }
105
+ //# sourceMappingURL=segment-workers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segment-workers.js","sourceRoot":"","sources":["../../lib/segment-workers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license MIT
4
+ * @author Teffen Ellis, et al.
5
+ */
6
+ import { type CharacterSequenceInput } from "./CharacterSequence.js";
7
+ import type { AsyncDataResource, ByteRange } from "./shared.js";
8
+ export interface SegmentOptions {
9
+ /** The record delimiter. @default LineFeed */
10
+ delimiter?: CharacterSequenceInput;
11
+ /** Desired number of segments. Clamped to ≥ 1; the result may be fewer. */
12
+ concurrency: number;
13
+ /** Bytes read at each ideal boundary to find the next delimiter. @default 65536 */
14
+ probeSize?: number;
15
+ }
16
+ /**
17
+ * Divide `source` into up to `concurrency` delimiter-aligned byte ranges. Each internal boundary is placed immediately
18
+ * after the first delimiter at or past the ideal cut, so concatenating each segment's records reproduces the file
19
+ * exactly — no record is split or duplicated.
20
+ *
21
+ * A probe window with no delimiter (a record longer than `probeSize`) collapses that boundary, so the result may have
22
+ * fewer than `concurrency` segments. An empty file yields no segments.
23
+ */
24
+ export declare function computeSegments(source: AsyncDataResource, options: SegmentOptions): Promise<ByteRange[]>;
25
+ //# sourceMappingURL=segments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segments.d.ts","sourceRoot":"","sources":["../../lib/segments.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAqB,KAAK,sBAAsB,EAAE,MAAM,wBAAwB,CAAA;AACvF,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAE/D,MAAM,WAAW,cAAc;IAC9B,8CAA8C;IAC9C,SAAS,CAAC,EAAE,sBAAsB,CAAA;IAClC,2EAA2E;IAC3E,WAAW,EAAE,MAAM,CAAA;IACnB,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CA4C9G"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license MIT
4
+ * @author Teffen Ellis, et al.
5
+ */
6
+ import { CharacterSequence } from "./CharacterSequence.js";
7
+ /**
8
+ * Divide `source` into up to `concurrency` delimiter-aligned byte ranges. Each internal boundary is placed immediately
9
+ * after the first delimiter at or past the ideal cut, so concatenating each segment's records reproduces the file
10
+ * exactly — no record is split or duplicated.
11
+ *
12
+ * A probe window with no delimiter (a record longer than `probeSize`) collapses that boundary, so the result may have
13
+ * fewer than `concurrency` segments. An empty file yields no segments.
14
+ */
15
+ export async function computeSegments(source, options) {
16
+ const { readFileSize, readBytes } = await import("spliterator/node/fs");
17
+ const needle = new CharacterSequence(options.delimiter);
18
+ const probeSize = options.probeSize ?? 65536;
19
+ const concurrency = Math.max(1, Math.floor(options.concurrency));
20
+ const fileSize = await readFileSize(source);
21
+ if (fileSize === 0)
22
+ return [];
23
+ if (concurrency === 1)
24
+ return [[0, fileSize]];
25
+ const idealCuts = Array.from({ length: concurrency - 1 }, (_, i) => Math.round(((i + 1) * fileSize) / concurrency));
26
+ const alignedCuts = await Promise.all(idealCuts.map(async (cut) => {
27
+ if (cut <= 0 || cut >= fileSize)
28
+ return null;
29
+ const window = await readBytes(source, cut, probeSize);
30
+ const index = needle.search(window, 0, window.length);
31
+ if (index === -1)
32
+ return null;
33
+ return cut + index + needle.length;
34
+ }));
35
+ const boundaries = new Set([0, fileSize]);
36
+ for (const cut of alignedCuts) {
37
+ if (cut !== null && cut > 0 && cut < fileSize)
38
+ boundaries.add(cut);
39
+ }
40
+ const sorted = Array.from(boundaries).sort((a, b) => a - b);
41
+ const segments = [];
42
+ for (let i = 1; i < sorted.length; i++) {
43
+ const start = sorted[i - 1];
44
+ const end = sorted[i];
45
+ if (end > start)
46
+ segments.push([start, end]);
47
+ }
48
+ return segments;
49
+ }
50
+ //# sourceMappingURL=segments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segments.js","sourceRoot":"","sources":["../../lib/segments.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,iBAAiB,EAA+B,MAAM,wBAAwB,CAAA;AAYvF;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAyB,EAAE,OAAuB;IACvF,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAA;IACvE,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IACvD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAA;IAC5C,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAA;IAEhE,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,CAAA;IAE3C,IAAI,QAAQ,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IAE7B,IAAI,WAAW,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAA;IAE7C,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,WAAW,CAAC,CAAC,CAAA;IAEnH,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,GAAG,CACpC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QAC3B,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,QAAQ;YAAE,OAAO,IAAI,CAAA;QAE5C,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE,SAAS,CAAC,CAAA;QACtD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;QAErD,IAAI,KAAK,KAAK,CAAC,CAAC;YAAE,OAAO,IAAI,CAAA;QAE7B,OAAO,GAAG,GAAG,KAAK,GAAG,MAAM,CAAC,MAAM,CAAA;IACnC,CAAC,CAAC,CACF,CAAA;IAED,MAAM,UAAU,GAAG,IAAI,GAAG,CAAS,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAA;IAEjD,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC/B,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,GAAG,CAAC,IAAI,GAAG,GAAG,QAAQ;YAAE,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACnE,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IAC3D,MAAM,QAAQ,GAAgB,EAAE,CAAA;IAEhC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAE,CAAA;QAC5B,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAE,CAAA;QAEtB,IAAI,GAAG,GAAG,KAAK;YAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAA;IAC7C,CAAC;IAED,OAAO,QAAQ,CAAA;AAChB,CAAC"}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @copyright Sister Software
3
- * @license AGPL-3.0
3
+ * @license MIT
4
4
  * @author Teffen Ellis, et al.
5
5
  */
6
6
  import { type Stats } from "node:fs";
package/out/lib/shared.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @copyright Sister Software
3
- * @license AGPL-3.0
3
+ * @license MIT
4
4
  * @author Teffen Ellis, et al.
5
5
  */
6
6
  // eslint-disable-next-line no-restricted-imports
package/out/lib/take.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @copyright Sister Software
3
- * @license AGPL-3.0
3
+ * @license MIT
4
4
  * @author Teffen Ellis, et al.
5
5
  */
6
6
  /**
package/out/lib/take.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @copyright Sister Software
3
- * @license AGPL-3.0
3
+ * @license MIT
4
4
  * @author Teffen Ellis, et al.
5
5
  */
6
6
  /**
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license MIT
4
+ * @author Teffen Ellis, et al.
5
+ * Base64-encoded WASM module for SIMD-accelerated delimiter scanning.
6
+ * Generated by wasm/build.sh — do not edit by hand.
7
+ * The module exports:
8
+ * - memory: WebAssembly.Memory (1 page = 64KB initial, grows on demand, no fixed maximum)
9
+ * - find_delimiter(haystack_offset, haystack_len, pattern_offset, pattern_len) → i32
10
+ * Returns the byte offset of the first match, or -1.
11
+ * - find_all_delimiters(haystack_offset, haystack_len, pattern_offset, pattern_len,
12
+ * results_offset, max_results) → usize
13
+ * Writes (start, end) i32 pairs to results_offset, returns count.
14
+ */
15
+ export declare const WASM_BASE64 = "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";
16
+ //# sourceMappingURL=wasm_base64.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wasm_base64.d.ts","sourceRoot":"","sources":["../../lib/wasm_base64.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,WAAW,ytEAC+rE,CAAA"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license MIT
4
+ * @author Teffen Ellis, et al.
5
+ * Base64-encoded WASM module for SIMD-accelerated delimiter scanning.
6
+ * Generated by wasm/build.sh — do not edit by hand.
7
+ * The module exports:
8
+ * - memory: WebAssembly.Memory (1 page = 64KB initial, grows on demand, no fixed maximum)
9
+ * - find_delimiter(haystack_offset, haystack_len, pattern_offset, pattern_len) → i32
10
+ * Returns the byte offset of the first match, or -1.
11
+ * - find_all_delimiters(haystack_offset, haystack_len, pattern_offset, pattern_len,
12
+ * results_offset, max_results) → usize
13
+ * Writes (start, end) i32 pairs to results_offset, returns count.
14
+ */
15
+ export const WASM_BASE64 = "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";
16
+ //# sourceMappingURL=wasm_base64.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wasm_base64.js","sourceRoot":"","sources":["../../lib/wasm_base64.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,WAAW,GACvB,stEAAstE,CAAA"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license MIT
4
+ * @author Teffen Ellis, et al.
5
+ */
6
+ export declare function loadWasmModule(): Promise<WasmDelimiterScanner | null>;
7
+ type WasmFindDelimiter = (ho: number, hl: number, po: number, pl: number) => number;
8
+ type WasmFindAllDelimiters = (ho: number, hl: number, po: number, pl: number, ro: number, mr: number) => number;
9
+ type WasmFindAllMatches = (ho: number, hl: number, p1o: number, p1l: number, p2l: number, ro: number, mr: number) => number;
10
+ export interface WasmMemory {
11
+ readonly buffer: ArrayBuffer;
12
+ grow(pages: number): number;
13
+ }
14
+ export interface WasmDelimiterScanner {
15
+ memory: WasmMemory;
16
+ findDelimiter: WasmFindDelimiter;
17
+ findAllDelimiters: WasmFindAllDelimiters;
18
+ findAllMatches: WasmFindAllMatches;
19
+ }
20
+ /** Match result from find_all_matches: [offset, pattern_id]. */
21
+ export interface MatchResult {
22
+ /** Byte offset of the match within the haystack. */
23
+ offset: number;
24
+ /** 0 = pattern 1 (delimiter), 1 = pattern 2 (quote). */
25
+ patternId: number;
26
+ }
27
+ /**
28
+ * Minimum haystack size (bytes) at which the WASM SIMD scanner is used instead of the JS scan, once the module has
29
+ * loaded. Empirically WASM wins well below this — ~8x for single-byte `searchAll` and ~3x for multi-byte `search` at
30
+ * 512 bytes, with sub-µs fixed overhead — so 512 captures typical delimited rows while skipping only the tiny-buffer
31
+ * regime where it doesn't matter.
32
+ */
33
+ export declare const WASM_THRESHOLD = 512;
34
+ export declare const WASM_MAX_RESULTS = 4096;
35
+ export {};
36
+ //# sourceMappingURL=wasm_module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wasm_module.d.ts","sourceRoot":"","sources":["../../lib/wasm_module.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAiBH,wBAAsB,cAAc,IAAI,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAkB3E;AAED,KAAK,iBAAiB,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,MAAM,CAAA;AAEnF,KAAK,qBAAqB,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,MAAM,CAAA;AAE/G,KAAK,kBAAkB,GAAG,CACzB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,KACN,MAAM,CAAA;AAEX,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,oBAAoB;IACpC,MAAM,EAAE,UAAU,CAAA;IAClB,aAAa,EAAE,iBAAiB,CAAA;IAChC,iBAAiB,EAAE,qBAAqB,CAAA;IACxC,cAAc,EAAE,kBAAkB,CAAA;CAClC;AAED,gEAAgE;AAChE,MAAM,WAAW,WAAW;IAC3B,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAA;IACd,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAA;CACjB;AAED;;;;;GAKG;AACH,eAAO,MAAM,cAAc,MAAM,CAAA;AACjC,eAAO,MAAM,gBAAgB,OAAO,CAAA"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license MIT
4
+ * @author Teffen Ellis, et al.
5
+ */
6
+ import { WASM_BASE64 } from "./wasm_base64.js";
7
+ export async function loadWasmModule() {
8
+ if (!WASM_BASE64)
9
+ return null;
10
+ try {
11
+ const bytes = Uint8Array.from(atob(WASM_BASE64), (c) => c.charCodeAt(0));
12
+ const module = await WebAssembly.compile(bytes);
13
+ const instance = await WebAssembly.instantiate(module, {});
14
+ const e = instance.exports;
15
+ const memory = e.memory;
16
+ const findDelimiter = e.find_delimiter;
17
+ const findAllDelimiters = e.find_all_delimiters;
18
+ const findAllMatches = e.find_all_matches;
19
+ return { memory, findDelimiter, findAllDelimiters, findAllMatches };
20
+ }
21
+ catch {
22
+ return null;
23
+ }
24
+ }
25
+ /**
26
+ * Minimum haystack size (bytes) at which the WASM SIMD scanner is used instead of the JS scan, once the module has
27
+ * loaded. Empirically WASM wins well below this — ~8x for single-byte `searchAll` and ~3x for multi-byte `search` at
28
+ * 512 bytes, with sub-µs fixed overhead — so 512 captures typical delimited rows while skipping only the tiny-buffer
29
+ * regime where it doesn't matter.
30
+ */
31
+ export const WASM_THRESHOLD = 512;
32
+ export const WASM_MAX_RESULTS = 4096;
33
+ //# sourceMappingURL=wasm_module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wasm_module.js","sourceRoot":"","sources":["../../lib/wasm_module.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAe9C,MAAM,CAAC,KAAK,UAAU,cAAc;IACnC,IAAI,CAAC,WAAW;QAAE,OAAO,IAAI,CAAA;IAE7B,IAAI,CAAC;QACJ,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAA;QACxE,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QAC/C,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;QAC1D,MAAM,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAA;QAE1B,MAAM,MAAM,GAAG,CAAC,CAAC,MAAoB,CAAA;QACrC,MAAM,aAAa,GAAG,CAAC,CAAC,cAAmC,CAAA;QAC3D,MAAM,iBAAiB,GAAG,CAAC,CAAC,mBAA4C,CAAA;QACxE,MAAM,cAAc,GAAG,CAAC,CAAC,gBAAsC,CAAA;QAE/D,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,iBAAiB,EAAE,cAAc,EAAE,CAAA;IACpE,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAA;IACZ,CAAC;AACF,CAAC;AAoCD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,CAAA;AACjC,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAA"}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @copyright Sister Software
3
- * @license AGPL-3.0
3
+ * @license MIT
4
4
  * @author Teffen Ellis, et al.
5
5
  */
6
6
  import { type PathLike, WriteStream } from "node:fs";
package/out/lib/writer.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @copyright Sister Software
3
- * @license AGPL-3.0
3
+ * @license MIT
4
4
  * @author Teffen Ellis, et al.
5
5
  */
6
6
  import { createWriteStream, WriteStream } from "node:fs";
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @copyright Sister Software
3
- * @license AGPL-3.0
3
+ * @license MIT
4
4
  * @author Teffen Ellis, et al.
5
5
  * @file Yargs command to split a CSV file.
6
6
  */
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @copyright Sister Software
3
- * @license AGPL-3.0
3
+ * @license MIT
4
4
  * @author Teffen Ellis, et al.
5
5
  * @file Yargs command to split a CSV file.
6
6
  */
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @copyright Sister Software
3
- * @license AGPL-3.0
3
+ * @license MIT
4
4
  * @author Teffen Ellis, et al.
5
5
  */
6
6
  import type { ArgumentsCamelCase, Argv } from "yargs";
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @copyright Sister Software
3
- * @license AGPL-3.0
3
+ * @license MIT
4
4
  * @author Teffen Ellis, et al.
5
5
  */
6
6
  import { resolve as resolvePath } from "node:path";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * @copyright Sister Software
4
- * @license AGPL-3.0
4
+ * @license MIT
5
5
  * @author Teffen Ellis, et al.
6
6
  * @file CLI entry point for the Spliterator library.
7
7
  */
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * @copyright Sister Software
4
- * @license AGPL-3.0
4
+ * @license MIT
5
5
  * @author Teffen Ellis, et al.
6
6
  * @file CLI entry point for the Spliterator library.
7
7
  */
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @copyright Sister Software
3
- * @license AGPL-3.0
3
+ * @license MIT
4
4
  * @author Teffen Ellis, et al.
5
5
  */
6
6
  import type { Argv } from "yargs";
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @copyright Sister Software
3
- * @license AGPL-3.0
3
+ * @license MIT
4
4
  * @author Teffen Ellis, et al.
5
5
  */
6
6
  export const commonCommandsBuilder = (argv) => {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @copyright Sister Software
3
- * @license AGPL-3.0
3
+ * @license MIT
4
4
  * @author Teffen Ellis, et al.
5
5
  */
6
6
  import { type CreateWriteStreamOptions } from "node:fs/promises";
@@ -37,6 +37,11 @@ export interface CreateChunkIteratorOptions {
37
37
  * The byte position to start reading from.
38
38
  */
39
39
  start?: number;
40
+ /**
41
+ * The byte position to stop reading at, **inclusive** (matches Node `createReadStream({ end })`). To read the
42
+ * half-open range `[start, end)`, pass `{ start, end: end - 1 }`.
43
+ */
44
+ end?: number;
40
45
  }
41
46
  /**
42
47
  * Read the size of a file from a source.
@@ -47,12 +52,19 @@ export interface CreateChunkIteratorOptions {
47
52
  * @internal
48
53
  */
49
54
  export declare function readFileSize(source: AsyncDataResource): Promise<number>;
55
+ /**
56
+ * Read a fixed-length window of bytes from `start`. The result is EOF-clamped, so it may be shorter than `length`. Used
57
+ * for delimiter-boundary probing.
58
+ *
59
+ * @internal
60
+ */
61
+ export declare function readBytes(source: AsyncDataResource, start: number, length: number): Promise<Uint8Array>;
50
62
  /**
51
63
  * Create an async chunk iterator from a source.
52
64
  *
53
65
  * @param source The source to create the chunk iterator from.
54
66
  * @internal
55
67
  */
56
- export declare function createChunkIterator(source: AsyncDataResource | AsyncChunkIterator, { highWaterMark, start }?: CreateChunkIteratorOptions): Promise<AsyncChunkIterator>;
68
+ export declare function createChunkIterator(source: AsyncDataResource | AsyncChunkIterator, { highWaterMark, start, end }?: CreateChunkIteratorOptions): Promise<AsyncChunkIterator>;
57
69
  export default createChunkIterator;
58
70
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../node/fs/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,wBAAwB,EAAc,MAAM,kBAAkB,CAAA;AAE5E,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEhD,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAoB,MAAM,qBAAqB,CAAA;AAEvG;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAgB1G;AAED;;;;;;;;;GASG;AACH,wBAAsB,wBAAwB,CAC7C,WAAW,EAAE,OAAO,EACpB,OAAO,GAAE,wBAA6B,GACpC,OAAO,CAAC,cAAc,CAAC,CAkDzB;AAED,MAAM,WAAW,0BAA0B;IAC1C;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IAEtB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAU7E;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACxC,MAAM,EAAE,iBAAiB,GAAG,kBAAkB,EAC9C,EAAE,aAAyB,EAAE,KAAS,EAAE,GAAE,0BAA+B,GACvE,OAAO,CAAC,kBAAkB,CAAC,CAiD7B;AAED,eAAe,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../node/fs/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,wBAAwB,EAAc,MAAM,kBAAkB,CAAA;AAE5E,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEhD,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAoB,MAAM,qBAAqB,CAAA;AAEvG;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAgB1G;AAED;;;;;;;;;GASG;AACH,wBAAsB,wBAAwB,CAC7C,WAAW,EAAE,OAAO,EACpB,OAAO,GAAE,wBAA6B,GACpC,OAAO,CAAC,cAAc,CAAC,CAkDzB;AAED,MAAM,WAAW,0BAA0B;IAC1C;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IAEtB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;CACZ;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAU7E;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAgB7G;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACxC,MAAM,EAAE,iBAAiB,GAAG,kBAAkB,EAC9C,EAAE,aAAyB,EAAE,KAAS,EAAE,GAAG,EAAE,GAAE,0BAA+B,GAC5E,OAAO,CAAC,kBAAkB,CAAC,CAmD7B;AAED,eAAe,mBAAmB,CAAA"}