rowpipe 1.1.0 → 2.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 (107) 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 +36 -0
  7. package/dist/cli/commands/files.d.ts.map +1 -0
  8. package/dist/cli/commands/files.js +94 -0
  9. package/dist/cli/commands/files.js.map +1 -0
  10. package/dist/cli/index.js +86 -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 +348 -0
  77. package/dist/files/reader.js.map +1 -0
  78. package/dist/files/types.d.ts +49 -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 +88 -7
  95. package/dist/transforms/expression.js.map +1 -1
  96. package/dist/utils/formatting.d.ts +1 -0
  97. package/dist/utils/formatting.d.ts.map +1 -1
  98. package/dist/utils/formatting.js +34 -4
  99. package/dist/utils/formatting.js.map +1 -1
  100. package/dist/writers/csv.d.ts.map +1 -1
  101. package/dist/writers/csv.js +21 -7
  102. package/dist/writers/csv.js.map +1 -1
  103. package/dist/writers/markdown.d.ts.map +1 -1
  104. package/dist/writers/markdown.js +41 -12
  105. package/dist/writers/markdown.js.map +1 -1
  106. package/package.json +4 -2
  107. package/skills/rowpipe/SKILL.md +91 -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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"}