rowpipe 1.1.0 → 1.2.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 (100) hide show
  1. package/README.md +302 -9
  2. package/dist/cli/commands/diff.d.ts +30 -0
  3. package/dist/cli/commands/diff.d.ts.map +1 -0
  4. package/dist/cli/commands/diff.js +143 -0
  5. package/dist/cli/commands/diff.js.map +1 -0
  6. package/dist/cli/commands/files.d.ts +35 -0
  7. package/dist/cli/commands/files.d.ts.map +1 -0
  8. package/dist/cli/commands/files.js +93 -0
  9. package/dist/cli/commands/files.js.map +1 -0
  10. package/dist/cli/index.js +85 -1
  11. package/dist/cli/index.js.map +1 -1
  12. package/dist/core/errors.d.ts +23 -0
  13. package/dist/core/errors.d.ts.map +1 -1
  14. package/dist/core/errors.js +38 -0
  15. package/dist/core/errors.js.map +1 -1
  16. package/dist/core/types.d.ts +2 -0
  17. package/dist/core/types.d.ts.map +1 -1
  18. package/dist/diff/comparator.d.ts +17 -0
  19. package/dist/diff/comparator.d.ts.map +1 -0
  20. package/dist/diff/comparator.js +158 -0
  21. package/dist/diff/comparator.js.map +1 -0
  22. package/dist/diff/engine.d.ts +10 -0
  23. package/dist/diff/engine.d.ts.map +1 -0
  24. package/dist/diff/engine.js +333 -0
  25. package/dist/diff/engine.js.map +1 -0
  26. package/dist/diff/hash.d.ts +6 -0
  27. package/dist/diff/hash.d.ts.map +1 -0
  28. package/dist/diff/hash.js +50 -0
  29. package/dist/diff/hash.js.map +1 -0
  30. package/dist/diff/key.d.ts +21 -0
  31. package/dist/diff/key.d.ts.map +1 -0
  32. package/dist/diff/key.js +107 -0
  33. package/dist/diff/key.js.map +1 -0
  34. package/dist/diff/reporter.d.ts +18 -0
  35. package/dist/diff/reporter.d.ts.map +1 -0
  36. package/dist/diff/reporter.js +133 -0
  37. package/dist/diff/reporter.js.map +1 -0
  38. package/dist/diff/schema.d.ts +7 -0
  39. package/dist/diff/schema.d.ts.map +1 -0
  40. package/dist/diff/schema.js +65 -0
  41. package/dist/diff/schema.js.map +1 -0
  42. package/dist/diff/storage/disk-index.d.ts +28 -0
  43. package/dist/diff/storage/disk-index.d.ts.map +1 -0
  44. package/dist/diff/storage/disk-index.js +105 -0
  45. package/dist/diff/storage/disk-index.js.map +1 -0
  46. package/dist/diff/storage/memory-index.d.ts +23 -0
  47. package/dist/diff/storage/memory-index.d.ts.map +1 -0
  48. package/dist/diff/storage/memory-index.js +69 -0
  49. package/dist/diff/storage/memory-index.js.map +1 -0
  50. package/dist/diff/storage/spillable-index.d.ts +30 -0
  51. package/dist/diff/storage/spillable-index.d.ts.map +1 -0
  52. package/dist/diff/storage/spillable-index.js +108 -0
  53. package/dist/diff/storage/spillable-index.js.map +1 -0
  54. package/dist/diff/types.d.ts +127 -0
  55. package/dist/diff/types.d.ts.map +1 -0
  56. package/dist/diff/types.js +2 -0
  57. package/dist/diff/types.js.map +1 -0
  58. package/dist/files/glob.d.ts +21 -0
  59. package/dist/files/glob.d.ts.map +1 -0
  60. package/dist/files/glob.js +132 -0
  61. package/dist/files/glob.js.map +1 -0
  62. package/dist/files/hash.d.ts +10 -0
  63. package/dist/files/hash.d.ts.map +1 -0
  64. package/dist/files/hash.js +67 -0
  65. package/dist/files/hash.js.map +1 -0
  66. package/dist/files/index.d.ts +6 -0
  67. package/dist/files/index.d.ts.map +1 -0
  68. package/dist/files/index.js +6 -0
  69. package/dist/files/index.js.map +1 -0
  70. package/dist/files/mime.d.ts +9 -0
  71. package/dist/files/mime.d.ts.map +1 -0
  72. package/dist/files/mime.js +128 -0
  73. package/dist/files/mime.js.map +1 -0
  74. package/dist/files/reader.d.ts +19 -0
  75. package/dist/files/reader.d.ts.map +1 -0
  76. package/dist/files/reader.js +344 -0
  77. package/dist/files/reader.js.map +1 -0
  78. package/dist/files/types.d.ts +47 -0
  79. package/dist/files/types.d.ts.map +1 -0
  80. package/dist/files/types.js +2 -0
  81. package/dist/files/types.js.map +1 -0
  82. package/dist/index.d.ts +16 -1
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +18 -1
  85. package/dist/index.js.map +1 -1
  86. package/dist/readers/csv.d.ts.map +1 -1
  87. package/dist/readers/csv.js +39 -19
  88. package/dist/readers/csv.js.map +1 -1
  89. package/dist/readers/index.d.ts +1 -0
  90. package/dist/readers/index.d.ts.map +1 -1
  91. package/dist/readers/index.js +28 -0
  92. package/dist/readers/index.js.map +1 -1
  93. package/dist/transforms/expression.d.ts.map +1 -1
  94. package/dist/transforms/expression.js +73 -7
  95. package/dist/transforms/expression.js.map +1 -1
  96. package/dist/writers/csv.d.ts.map +1 -1
  97. package/dist/writers/csv.js +21 -7
  98. package/dist/writers/csv.js.map +1 -1
  99. package/package.json +4 -2
  100. package/skills/rowpipe/SKILL.md +82 -0
@@ -0,0 +1,133 @@
1
+ import { formatNumber } from "../utils/formatting.js";
2
+ import { formatKeyForDisplay } from "./key.js";
3
+ function formatValueForDisplay(val) {
4
+ if (val === undefined)
5
+ return "<missing>";
6
+ if (val === null)
7
+ return "null";
8
+ if (typeof val === "object")
9
+ return JSON.stringify(val);
10
+ return String(val);
11
+ }
12
+ /**
13
+ * Formats a single DiffEvent for --format rows output.
14
+ */
15
+ export function formatRowEvent(event) {
16
+ const keyStr = formatKeyForDisplay(event.key);
17
+ switch (event.type) {
18
+ case "added":
19
+ return `ADDED ${keyStr}\n`;
20
+ case "removed":
21
+ return `REMOVED ${keyStr}\n`;
22
+ case "changed": {
23
+ let output = `CHANGED ${keyStr}\n`;
24
+ for (const ch of event.changes) {
25
+ const oldDisplay = formatValueForDisplay(ch.oldVal);
26
+ const newDisplay = formatValueForDisplay(ch.newVal);
27
+ output += ` ${ch.column}: ${oldDisplay} -> ${newDisplay}\n`;
28
+ }
29
+ return output;
30
+ }
31
+ case "unchanged":
32
+ return `UNCHANGED ${keyStr}\n`;
33
+ default:
34
+ return null;
35
+ }
36
+ }
37
+ /**
38
+ * Formats a single DiffEvent for --format patch (JSONL) output.
39
+ */
40
+ export function formatPatchEvent(event) {
41
+ switch (event.type) {
42
+ case "added":
43
+ return (JSON.stringify({
44
+ op: "insert",
45
+ key: event.key,
46
+ row: event.row,
47
+ }) + "\n");
48
+ case "removed":
49
+ return (JSON.stringify({
50
+ op: "delete",
51
+ key: event.key,
52
+ row: event.row,
53
+ }) + "\n");
54
+ case "changed": {
55
+ const changesObj = {};
56
+ for (const ch of event.changes) {
57
+ changesObj[ch.column] = {
58
+ old: ch.oldVal,
59
+ new: ch.newVal,
60
+ };
61
+ }
62
+ return (JSON.stringify({
63
+ op: "update",
64
+ key: event.key,
65
+ changes: changesObj,
66
+ }) + "\n");
67
+ }
68
+ default:
69
+ return null;
70
+ }
71
+ }
72
+ /**
73
+ * Formats complete DiffSummary as human-readable ASCII text.
74
+ */
75
+ export function formatSummary(summary) {
76
+ const lines = [];
77
+ lines.push("Comparing:");
78
+ lines.push(` ${summary.leftSource}`);
79
+ lines.push(` ${summary.rightSource}`);
80
+ lines.push("");
81
+ lines.push(`Key: ${summary.keyColumns.join(", ")}`);
82
+ lines.push("");
83
+ lines.push("Rows");
84
+ const maxNumLen = Math.max(formatNumber(summary.rows.added).length, formatNumber(summary.rows.removed).length, formatNumber(summary.rows.changed).length, formatNumber(summary.rows.unchanged).length);
85
+ lines.push(` added ${formatNumber(summary.rows.added).padStart(maxNumLen)}`);
86
+ lines.push(` removed ${formatNumber(summary.rows.removed).padStart(maxNumLen)}`);
87
+ lines.push(` changed ${formatNumber(summary.rows.changed).padStart(maxNumLen)}`);
88
+ lines.push(` unchanged ${formatNumber(summary.rows.unchanged).padStart(maxNumLen)}`);
89
+ // Changed columns breakdown
90
+ const changedCols = Object.entries(summary.columns).sort((a, b) => b[1].changed - a[1].changed);
91
+ if (changedCols.length > 0) {
92
+ lines.push("");
93
+ lines.push("Changed columns");
94
+ const maxColLen = Math.max(...changedCols.map(([c]) => c.length), 10);
95
+ for (const [col, info] of changedCols) {
96
+ lines.push(` ${col.padEnd(maxColLen)} ${formatNumber(info.changed)}`);
97
+ }
98
+ }
99
+ // Schema diff
100
+ if (summary.schema) {
101
+ const { added, removed, changed } = summary.schema;
102
+ if (added.length > 0 || removed.length > 0 || changed.length > 0) {
103
+ lines.push("");
104
+ lines.push("Schema");
105
+ for (const col of added) {
106
+ lines.push(` + ${col.name}: ${col.type}`);
107
+ }
108
+ for (const col of changed) {
109
+ lines.push(` ~ ${col.name}: ${col.leftType} -> ${col.rightType}`);
110
+ }
111
+ for (const col of removed) {
112
+ lines.push(` - ${col.name}: ${col.type}`);
113
+ }
114
+ }
115
+ }
116
+ return lines.join("\n") + "\n";
117
+ }
118
+ /**
119
+ * Formats complete DiffSummary as JSON string.
120
+ */
121
+ export function formatJson(summary) {
122
+ const jsonObject = {
123
+ left: summary.leftSource,
124
+ right: summary.rightSource,
125
+ key: summary.keyColumns,
126
+ rows: summary.rows,
127
+ columns: summary.columns,
128
+ schema: summary.schema,
129
+ executionTimeMs: summary.executionTimeMs,
130
+ };
131
+ return JSON.stringify(jsonObject, null, 2) + "\n";
132
+ }
133
+ //# sourceMappingURL=reporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporter.js","sourceRoot":"","sources":["../../src/diff/reporter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { TabularReader } from "../core/types.js";
2
+ import type { SchemaColumnDiff } from "./types.js";
3
+ /**
4
+ * Computes the schema differences between two tabular readers.
5
+ */
6
+ export declare function computeSchemaDiff(leftReader: TabularReader, rightReader: TabularReader): Promise<SchemaColumnDiff>;
7
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/diff/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAElE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA2CnD;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,aAAa,EACzB,WAAW,EAAE,aAAa,GACzB,OAAO,CAAC,gBAAgB,CAAC,CA4B3B"}
@@ -0,0 +1,65 @@
1
+ import { classifyPrimitiveType } from "../analytics/schema-inference.js";
2
+ async function extractReaderColumns(reader) {
3
+ const map = new Map();
4
+ // 1. Try reader.inspect()
5
+ if (typeof reader.inspect === "function") {
6
+ try {
7
+ const meta = await reader.inspect({ maxRows: 1000 });
8
+ if (meta.columns && meta.columns.length > 0) {
9
+ for (const col of meta.columns) {
10
+ map.set(col.name, col.type);
11
+ }
12
+ return map;
13
+ }
14
+ }
15
+ catch {
16
+ // Fallback to reading first batch
17
+ }
18
+ }
19
+ // 2. Read first batch
20
+ try {
21
+ for await (const batch of reader.read({ batchSize: 100 })) {
22
+ if (batch.rows.length > 0) {
23
+ const firstRow = batch.rows[0];
24
+ for (const [k, v] of Object.entries(firstRow)) {
25
+ map.set(k, classifyPrimitiveType(v));
26
+ }
27
+ break;
28
+ }
29
+ }
30
+ }
31
+ catch {
32
+ // Ignore error
33
+ }
34
+ return map;
35
+ }
36
+ /**
37
+ * Computes the schema differences between two tabular readers.
38
+ */
39
+ export async function computeSchemaDiff(leftReader, rightReader) {
40
+ const leftCols = await extractReaderColumns(leftReader);
41
+ const rightCols = await extractReaderColumns(rightReader);
42
+ const added = [];
43
+ const removed = [];
44
+ const changed = [];
45
+ // Detect removed & changed
46
+ for (const [name, leftType] of leftCols.entries()) {
47
+ if (!rightCols.has(name)) {
48
+ removed.push({ name, type: leftType });
49
+ }
50
+ else {
51
+ const rightType = rightCols.get(name);
52
+ if (leftType !== rightType && leftType !== "mixed" && rightType !== "mixed") {
53
+ changed.push({ name, leftType, rightType });
54
+ }
55
+ }
56
+ }
57
+ // Detect added
58
+ for (const [name, rightType] of rightCols.entries()) {
59
+ if (!leftCols.has(name)) {
60
+ added.push({ name, type: rightType });
61
+ }
62
+ }
63
+ return { added, removed, changed };
64
+ }
65
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/diff/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { DiffIndex, IndexedRow } from "../types.js";
2
+ /**
3
+ * High-performance Disk-backed Diff Index using an append-only temp file and offset index.
4
+ * Offloads entire row object memory to disk with microsecond random-access lookups.
5
+ */
6
+ export declare class DiskDiffIndex implements DiffIndex {
7
+ private tempFilePath;
8
+ private fd;
9
+ private index;
10
+ private currentOffset;
11
+ private isClosed;
12
+ private cleanupHandler?;
13
+ constructor();
14
+ set(key: string, indexedRow: IndexedRow): Promise<void>;
15
+ get(key: string): Promise<IndexedRow | undefined>;
16
+ has(key: string): Promise<boolean>;
17
+ delete(key: string): Promise<boolean>;
18
+ entries(): AsyncIterable<[string, IndexedRow]>;
19
+ count(): number;
20
+ getSpillStats(): {
21
+ isSpilled: boolean;
22
+ spilledBytes: number;
23
+ entryCount: number;
24
+ };
25
+ private cleanupSync;
26
+ close(): Promise<void>;
27
+ }
28
+ //# sourceMappingURL=disk-index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disk-index.d.ts","sourceRoot":"","sources":["../../../src/diff/storage/disk-index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AASzD;;;GAGG;AACH,qBAAa,aAAc,YAAW,SAAS;IAC7C,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,EAAE,CAAS;IACnB,OAAO,CAAC,KAAK,CAAsC;IACnD,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,cAAc,CAAC,CAAa;;IAe9B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBvD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAejD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIlC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIpC,OAAO,IAAI,aAAa,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IASrD,KAAK,IAAI,MAAM;IAIf,aAAa,IAAI;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE;IAQjF,OAAO,CAAC,WAAW;IAiBb,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAQ7B"}
@@ -0,0 +1,105 @@
1
+ import { closeSync, existsSync, openSync, readSync, unlinkSync, writeSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { randomBytes } from "node:crypto";
5
+ /**
6
+ * High-performance Disk-backed Diff Index using an append-only temp file and offset index.
7
+ * Offloads entire row object memory to disk with microsecond random-access lookups.
8
+ */
9
+ export class DiskDiffIndex {
10
+ tempFilePath;
11
+ fd;
12
+ index = new Map();
13
+ currentOffset = 0;
14
+ isClosed = false;
15
+ cleanupHandler;
16
+ constructor() {
17
+ const randomId = randomBytes(8).toString("hex");
18
+ this.tempFilePath = join(tmpdir(), `rowpipe-diff-${process.pid}-${randomId}.tmp`);
19
+ this.fd = openSync(this.tempFilePath, "w+");
20
+ this.cleanupHandler = () => {
21
+ this.cleanupSync();
22
+ };
23
+ process.once("exit", this.cleanupHandler);
24
+ process.once("SIGINT", this.cleanupHandler);
25
+ process.once("SIGTERM", this.cleanupHandler);
26
+ }
27
+ async set(key, indexedRow) {
28
+ const jsonStr = JSON.stringify(indexedRow.row);
29
+ const buf = Buffer.from(jsonStr, "utf-8");
30
+ const offset = this.currentOffset;
31
+ writeSync(this.fd, buf, 0, buf.length, offset);
32
+ this.currentOffset += buf.length;
33
+ this.index.set(key, {
34
+ offset,
35
+ length: buf.length,
36
+ hash: indexedRow.hash,
37
+ rowNumber: indexedRow.rowNumber,
38
+ });
39
+ }
40
+ async get(key) {
41
+ const meta = this.index.get(key);
42
+ if (!meta)
43
+ return undefined;
44
+ const buf = Buffer.allocUnsafe(meta.length);
45
+ readSync(this.fd, buf, 0, meta.length, meta.offset);
46
+ const row = JSON.parse(buf.toString("utf-8"));
47
+ return {
48
+ rowNumber: meta.rowNumber,
49
+ row,
50
+ hash: meta.hash,
51
+ };
52
+ }
53
+ async has(key) {
54
+ return this.index.has(key);
55
+ }
56
+ async delete(key) {
57
+ return this.index.delete(key);
58
+ }
59
+ async *entries() {
60
+ for (const [key, meta] of this.index.entries()) {
61
+ const buf = Buffer.allocUnsafe(meta.length);
62
+ readSync(this.fd, buf, 0, meta.length, meta.offset);
63
+ const row = JSON.parse(buf.toString("utf-8"));
64
+ yield [key, { rowNumber: meta.rowNumber, row, hash: meta.hash }];
65
+ }
66
+ }
67
+ count() {
68
+ return this.index.size;
69
+ }
70
+ getSpillStats() {
71
+ return {
72
+ isSpilled: true,
73
+ spilledBytes: this.currentOffset,
74
+ entryCount: this.index.size,
75
+ };
76
+ }
77
+ cleanupSync() {
78
+ if (this.isClosed)
79
+ return;
80
+ this.isClosed = true;
81
+ try {
82
+ closeSync(this.fd);
83
+ }
84
+ catch {
85
+ // Ignore
86
+ }
87
+ try {
88
+ if (existsSync(this.tempFilePath)) {
89
+ unlinkSync(this.tempFilePath);
90
+ }
91
+ }
92
+ catch {
93
+ // Ignore
94
+ }
95
+ }
96
+ async close() {
97
+ if (this.cleanupHandler) {
98
+ process.removeListener("exit", this.cleanupHandler);
99
+ process.removeListener("SIGINT", this.cleanupHandler);
100
+ process.removeListener("SIGTERM", this.cleanupHandler);
101
+ }
102
+ this.cleanupSync();
103
+ }
104
+ }
105
+ //# sourceMappingURL=disk-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disk-index.js","sourceRoot":"","sources":["../../../src/diff/storage/disk-index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { DiffIndex, IndexedRow } from "../types.js";
2
+ /**
3
+ * High-performance in-memory Diff Index backed by JavaScript Map.
4
+ */
5
+ export declare class MemoryDiffIndex implements DiffIndex {
6
+ private store;
7
+ private estimatedBytes;
8
+ set(key: string, row: IndexedRow): Promise<void>;
9
+ get(key: string): Promise<IndexedRow | undefined>;
10
+ has(key: string): Promise<boolean>;
11
+ delete(key: string): Promise<boolean>;
12
+ entries(): AsyncIterable<[string, IndexedRow]>;
13
+ count(): number;
14
+ getEstimatedBytes(): number;
15
+ getSpillStats(): {
16
+ isSpilled: boolean;
17
+ spilledBytes: number;
18
+ entryCount: number;
19
+ };
20
+ close(): Promise<void>;
21
+ private estimateRowBytes;
22
+ }
23
+ //# sourceMappingURL=memory-index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-index.d.ts","sourceRoot":"","sources":["../../../src/diff/storage/memory-index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzD;;GAEG;AACH,qBAAa,eAAgB,YAAW,SAAS;IAC/C,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,cAAc,CAAK;IAErB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAShD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAIjD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIlC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASpC,OAAO,IAAI,aAAa,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAMrD,KAAK,IAAI,MAAM;IAIf,iBAAiB,IAAI,MAAM;IAI3B,aAAa,IAAI;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE;IAQ3E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5B,OAAO,CAAC,gBAAgB;CAezB"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * High-performance in-memory Diff Index backed by JavaScript Map.
3
+ */
4
+ export class MemoryDiffIndex {
5
+ store = new Map();
6
+ estimatedBytes = 0;
7
+ async set(key, row) {
8
+ const existing = this.store.get(key);
9
+ if (existing) {
10
+ this.estimatedBytes -= this.estimateRowBytes(key, existing);
11
+ }
12
+ this.store.set(key, row);
13
+ this.estimatedBytes += this.estimateRowBytes(key, row);
14
+ }
15
+ async get(key) {
16
+ return this.store.get(key);
17
+ }
18
+ async has(key) {
19
+ return this.store.has(key);
20
+ }
21
+ async delete(key) {
22
+ const existing = this.store.get(key);
23
+ if (existing) {
24
+ this.estimatedBytes -= this.estimateRowBytes(key, existing);
25
+ return this.store.delete(key);
26
+ }
27
+ return false;
28
+ }
29
+ async *entries() {
30
+ for (const entry of this.store.entries()) {
31
+ yield entry;
32
+ }
33
+ }
34
+ count() {
35
+ return this.store.size;
36
+ }
37
+ getEstimatedBytes() {
38
+ return this.estimatedBytes;
39
+ }
40
+ getSpillStats() {
41
+ return {
42
+ isSpilled: false,
43
+ spilledBytes: 0,
44
+ entryCount: this.store.size,
45
+ };
46
+ }
47
+ async close() {
48
+ this.store.clear();
49
+ this.estimatedBytes = 0;
50
+ }
51
+ estimateRowBytes(key, item) {
52
+ // Key string bytes + row keys/values + Map object entry overhead in V8 (~128 bytes)
53
+ let bytes = key.length * 2 + 128;
54
+ for (const [k, v] of Object.entries(item.row)) {
55
+ bytes += k.length * 2 + 48;
56
+ if (typeof v === "string") {
57
+ bytes += v.length * 2 + 32;
58
+ }
59
+ else if (typeof v === "number" || typeof v === "boolean") {
60
+ bytes += 16;
61
+ }
62
+ else if (v !== null && v !== undefined) {
63
+ bytes += JSON.stringify(v).length * 2 + 48;
64
+ }
65
+ }
66
+ return bytes;
67
+ }
68
+ }
69
+ //# sourceMappingURL=memory-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-index.js","sourceRoot":"","sources":["../../../src/diff/storage/memory-index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { DiffIndex, IndexedRow } from "../types.js";
2
+ /**
3
+ * Parses a human-readable memory limit string (e.g. "256mb", "1gb", "64MB") into bytes.
4
+ */
5
+ export declare function parseMemoryLimit(input?: string | number, defaultBytes?: number): number;
6
+ /**
7
+ * Hybrid Spillable Diff Index that stays in memory for high speed,
8
+ * and automatically spills to partitioned disk storage when memory exceeds the threshold.
9
+ */
10
+ export declare class SpillableDiffIndex implements DiffIndex {
11
+ private memoryIndex;
12
+ private diskIndex?;
13
+ private memoryLimitBytes;
14
+ private isSpilled;
15
+ constructor(memoryLimit?: number | string);
16
+ private spillToDisk;
17
+ set(key: string, row: IndexedRow): Promise<void>;
18
+ get(key: string): Promise<IndexedRow | undefined>;
19
+ has(key: string): Promise<boolean>;
20
+ delete(key: string): Promise<boolean>;
21
+ entries(): AsyncIterable<[string, IndexedRow]>;
22
+ count(): number;
23
+ getSpillStats(): {
24
+ isSpilled: boolean;
25
+ spilledBytes: number;
26
+ entryCount: number;
27
+ };
28
+ close(): Promise<void>;
29
+ }
30
+ //# sourceMappingURL=spillable-index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spillable-index.d.ts","sourceRoot":"","sources":["../../../src/diff/storage/spillable-index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAIzD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,YAAY,SAAoB,GAAG,MAAM,CAwBlG;AAED;;;GAGG;AACH,qBAAa,kBAAmB,YAAW,SAAS;IAClD,OAAO,CAAC,WAAW,CAAyB;IAC5C,OAAO,CAAC,SAAS,CAAC,CAAgB;IAClC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,SAAS,CAAS;gBAEd,WAAW,GAAE,MAAM,GAAG,MAA0B;YAI9C,WAAW;IAYnB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAahD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAOjD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAOlC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAOpC,OAAO,IAAI,aAAa,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAQrD,KAAK,IAAI,MAAM;IAOf,aAAa,IAAI;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE;IAO3E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAM7B"}
@@ -0,0 +1,108 @@
1
+ import { DiskDiffIndex } from "./disk-index.js";
2
+ import { MemoryDiffIndex } from "./memory-index.js";
3
+ /**
4
+ * Parses a human-readable memory limit string (e.g. "256mb", "1gb", "64MB") into bytes.
5
+ */
6
+ export function parseMemoryLimit(input, defaultBytes = 256 * 1024 * 1024) {
7
+ if (!input)
8
+ return defaultBytes;
9
+ if (typeof input === "number")
10
+ return input;
11
+ const str = input.trim().toLowerCase();
12
+ const match = /^(\d+(?:\.\d+)?)\s*([a-z]+)?$/.exec(str);
13
+ if (!match)
14
+ return defaultBytes;
15
+ const val = Number.parseFloat(match[1]);
16
+ const unit = match[2] || "b";
17
+ switch (unit) {
18
+ case "gb":
19
+ case "g":
20
+ return Math.round(val * 1024 * 1024 * 1024);
21
+ case "mb":
22
+ case "m":
23
+ return Math.round(val * 1024 * 1024);
24
+ case "kb":
25
+ case "k":
26
+ return Math.round(val * 1024);
27
+ default:
28
+ return Math.round(val);
29
+ }
30
+ }
31
+ /**
32
+ * Hybrid Spillable Diff Index that stays in memory for high speed,
33
+ * and automatically spills to partitioned disk storage when memory exceeds the threshold.
34
+ */
35
+ export class SpillableDiffIndex {
36
+ memoryIndex = new MemoryDiffIndex();
37
+ diskIndex;
38
+ memoryLimitBytes;
39
+ isSpilled = false;
40
+ constructor(memoryLimit = 256 * 1024 * 1024) {
41
+ this.memoryLimitBytes = parseMemoryLimit(memoryLimit);
42
+ }
43
+ async spillToDisk() {
44
+ if (this.isSpilled)
45
+ return;
46
+ this.diskIndex = new DiskDiffIndex();
47
+ for await (const [key, row] of this.memoryIndex.entries()) {
48
+ await this.diskIndex.set(key, row);
49
+ }
50
+ await this.memoryIndex.close();
51
+ this.isSpilled = true;
52
+ }
53
+ async set(key, row) {
54
+ if (this.isSpilled && this.diskIndex) {
55
+ await this.diskIndex.set(key, row);
56
+ return;
57
+ }
58
+ await this.memoryIndex.set(key, row);
59
+ if (this.memoryIndex.getEstimatedBytes() >= this.memoryLimitBytes) {
60
+ await this.spillToDisk();
61
+ }
62
+ }
63
+ async get(key) {
64
+ if (this.isSpilled && this.diskIndex) {
65
+ return this.diskIndex.get(key);
66
+ }
67
+ return this.memoryIndex.get(key);
68
+ }
69
+ async has(key) {
70
+ if (this.isSpilled && this.diskIndex) {
71
+ return this.diskIndex.has(key);
72
+ }
73
+ return this.memoryIndex.has(key);
74
+ }
75
+ async delete(key) {
76
+ if (this.isSpilled && this.diskIndex) {
77
+ return this.diskIndex.delete(key);
78
+ }
79
+ return this.memoryIndex.delete(key);
80
+ }
81
+ async *entries() {
82
+ if (this.isSpilled && this.diskIndex) {
83
+ yield* this.diskIndex.entries();
84
+ }
85
+ else {
86
+ yield* this.memoryIndex.entries();
87
+ }
88
+ }
89
+ count() {
90
+ if (this.isSpilled && this.diskIndex) {
91
+ return this.diskIndex.count();
92
+ }
93
+ return this.memoryIndex.count();
94
+ }
95
+ getSpillStats() {
96
+ if (this.isSpilled && this.diskIndex) {
97
+ return this.diskIndex.getSpillStats();
98
+ }
99
+ return this.memoryIndex.getSpillStats();
100
+ }
101
+ async close() {
102
+ await this.memoryIndex.close();
103
+ if (this.diskIndex) {
104
+ await this.diskIndex.close();
105
+ }
106
+ }
107
+ }
108
+ //# sourceMappingURL=spillable-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spillable-index.js","sourceRoot":"","sources":["../../../src/diff/storage/spillable-index.ts"],"names":[],"mappings":"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"}