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.
- package/README.md +302 -9
- package/dist/cli/commands/diff.d.ts +30 -0
- package/dist/cli/commands/diff.d.ts.map +1 -0
- package/dist/cli/commands/diff.js +143 -0
- package/dist/cli/commands/diff.js.map +1 -0
- package/dist/cli/commands/files.d.ts +35 -0
- package/dist/cli/commands/files.d.ts.map +1 -0
- package/dist/cli/commands/files.js +93 -0
- package/dist/cli/commands/files.js.map +1 -0
- package/dist/cli/index.js +85 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/core/errors.d.ts +23 -0
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +38 -0
- package/dist/core/errors.js.map +1 -1
- package/dist/core/types.d.ts +2 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/diff/comparator.d.ts +17 -0
- package/dist/diff/comparator.d.ts.map +1 -0
- package/dist/diff/comparator.js +158 -0
- package/dist/diff/comparator.js.map +1 -0
- package/dist/diff/engine.d.ts +10 -0
- package/dist/diff/engine.d.ts.map +1 -0
- package/dist/diff/engine.js +333 -0
- package/dist/diff/engine.js.map +1 -0
- package/dist/diff/hash.d.ts +6 -0
- package/dist/diff/hash.d.ts.map +1 -0
- package/dist/diff/hash.js +50 -0
- package/dist/diff/hash.js.map +1 -0
- package/dist/diff/key.d.ts +21 -0
- package/dist/diff/key.d.ts.map +1 -0
- package/dist/diff/key.js +107 -0
- package/dist/diff/key.js.map +1 -0
- package/dist/diff/reporter.d.ts +18 -0
- package/dist/diff/reporter.d.ts.map +1 -0
- package/dist/diff/reporter.js +133 -0
- package/dist/diff/reporter.js.map +1 -0
- package/dist/diff/schema.d.ts +7 -0
- package/dist/diff/schema.d.ts.map +1 -0
- package/dist/diff/schema.js +65 -0
- package/dist/diff/schema.js.map +1 -0
- package/dist/diff/storage/disk-index.d.ts +28 -0
- package/dist/diff/storage/disk-index.d.ts.map +1 -0
- package/dist/diff/storage/disk-index.js +105 -0
- package/dist/diff/storage/disk-index.js.map +1 -0
- package/dist/diff/storage/memory-index.d.ts +23 -0
- package/dist/diff/storage/memory-index.d.ts.map +1 -0
- package/dist/diff/storage/memory-index.js +69 -0
- package/dist/diff/storage/memory-index.js.map +1 -0
- package/dist/diff/storage/spillable-index.d.ts +30 -0
- package/dist/diff/storage/spillable-index.d.ts.map +1 -0
- package/dist/diff/storage/spillable-index.js +108 -0
- package/dist/diff/storage/spillable-index.js.map +1 -0
- package/dist/diff/types.d.ts +127 -0
- package/dist/diff/types.d.ts.map +1 -0
- package/dist/diff/types.js +2 -0
- package/dist/diff/types.js.map +1 -0
- package/dist/files/glob.d.ts +21 -0
- package/dist/files/glob.d.ts.map +1 -0
- package/dist/files/glob.js +132 -0
- package/dist/files/glob.js.map +1 -0
- package/dist/files/hash.d.ts +10 -0
- package/dist/files/hash.d.ts.map +1 -0
- package/dist/files/hash.js +67 -0
- package/dist/files/hash.js.map +1 -0
- package/dist/files/index.d.ts +6 -0
- package/dist/files/index.d.ts.map +1 -0
- package/dist/files/index.js +6 -0
- package/dist/files/index.js.map +1 -0
- package/dist/files/mime.d.ts +9 -0
- package/dist/files/mime.d.ts.map +1 -0
- package/dist/files/mime.js +128 -0
- package/dist/files/mime.js.map +1 -0
- package/dist/files/reader.d.ts +19 -0
- package/dist/files/reader.d.ts.map +1 -0
- package/dist/files/reader.js +344 -0
- package/dist/files/reader.js.map +1 -0
- package/dist/files/types.d.ts +47 -0
- package/dist/files/types.d.ts.map +1 -0
- package/dist/files/types.js +2 -0
- package/dist/files/types.js.map +1 -0
- package/dist/index.d.ts +16 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -1
- package/dist/index.js.map +1 -1
- package/dist/readers/csv.d.ts.map +1 -1
- package/dist/readers/csv.js +39 -19
- package/dist/readers/csv.js.map +1 -1
- package/dist/readers/index.d.ts +1 -0
- package/dist/readers/index.d.ts.map +1 -1
- package/dist/readers/index.js +28 -0
- package/dist/readers/index.js.map +1 -1
- package/dist/transforms/expression.d.ts.map +1 -1
- package/dist/transforms/expression.js +73 -7
- package/dist/transforms/expression.js.map +1 -1
- package/dist/writers/csv.d.ts.map +1 -1
- package/dist/writers/csv.js +21 -7
- package/dist/writers/csv.js.map +1 -1
- package/package.json +4 -2
- package/skills/rowpipe/SKILL.md +82 -0
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import { DuplicateKeyError, InvalidArgumentError } from "../core/errors.js";
|
|
2
|
+
import { createReader } from "../readers/index.js";
|
|
3
|
+
import { compareRows } from "./comparator.js";
|
|
4
|
+
import { computeRowFingerprint } from "./hash.js";
|
|
5
|
+
import { encodeCompositeKey } from "./key.js";
|
|
6
|
+
import { computeSchemaDiff } from "./schema.js";
|
|
7
|
+
import { SpillableDiffIndex } from "./storage/spillable-index.js";
|
|
8
|
+
function createReaderFromSource(source, options) {
|
|
9
|
+
if (typeof source === "string") {
|
|
10
|
+
return {
|
|
11
|
+
reader: createReader(source, options),
|
|
12
|
+
sourceName: source,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
reader: source,
|
|
17
|
+
sourceName: options?.filePath || "stream",
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Streams fine-grained diff events (added, removed, changed, unchanged) between two datasets.
|
|
22
|
+
*/
|
|
23
|
+
export async function* diffRows(options) {
|
|
24
|
+
const { keys, ignore = [], columns, duplicateKey = "error" } = options;
|
|
25
|
+
if (!keys || keys.length === 0) {
|
|
26
|
+
throw new InvalidArgumentError("At least one key column must be specified with --key");
|
|
27
|
+
}
|
|
28
|
+
// Validate that key columns are not in ignore list
|
|
29
|
+
for (const k of keys) {
|
|
30
|
+
if (ignore.includes(k)) {
|
|
31
|
+
throw new InvalidArgumentError(`Cannot ignore key column "${k}" in diff.`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const leftInput = options.left ?? options.leftPath;
|
|
35
|
+
const rightInput = options.right ?? options.rightPath;
|
|
36
|
+
if (!leftInput) {
|
|
37
|
+
throw new InvalidArgumentError("Left source is required for diff.");
|
|
38
|
+
}
|
|
39
|
+
if (!rightInput) {
|
|
40
|
+
throw new InvalidArgumentError("Right source is required for diff.");
|
|
41
|
+
}
|
|
42
|
+
const leftOpts = {
|
|
43
|
+
...options.leftOptions,
|
|
44
|
+
format: options.fromLeft ?? options.leftOptions?.format,
|
|
45
|
+
};
|
|
46
|
+
const rightOpts = {
|
|
47
|
+
...options.rightOptions,
|
|
48
|
+
format: options.fromRight ?? options.rightOptions?.format,
|
|
49
|
+
};
|
|
50
|
+
const { reader: leftReader, sourceName: leftSource } = createReaderFromSource(leftInput, leftOpts);
|
|
51
|
+
const { reader: rightReader, sourceName: rightSource } = createReaderFromSource(rightInput, rightOpts);
|
|
52
|
+
const index = new SpillableDiffIndex(options.memoryLimitBytes);
|
|
53
|
+
const startTime = Date.now();
|
|
54
|
+
let leftRowsCount = 0;
|
|
55
|
+
let rightRowsCount = 0;
|
|
56
|
+
let addedCount = 0;
|
|
57
|
+
let removedCount = 0;
|
|
58
|
+
let changedCount = 0;
|
|
59
|
+
let unchangedCount = 0;
|
|
60
|
+
// Track discovered columns
|
|
61
|
+
const allDiscoveredColumns = new Set();
|
|
62
|
+
const seenLeftKeys = new Map();
|
|
63
|
+
const reportProgress = (phase) => {
|
|
64
|
+
if (options.onProgress) {
|
|
65
|
+
const spillStats = index.getSpillStats?.();
|
|
66
|
+
options.onProgress({
|
|
67
|
+
phase,
|
|
68
|
+
leftRowsProcessed: leftRowsCount,
|
|
69
|
+
rightRowsProcessed: rightRowsCount,
|
|
70
|
+
addedCount,
|
|
71
|
+
removedCount,
|
|
72
|
+
changedCount,
|
|
73
|
+
unchangedCount,
|
|
74
|
+
elapsedMs: Date.now() - startTime,
|
|
75
|
+
isSpilled: spillStats?.isSpilled,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
try {
|
|
80
|
+
// ---------------------------------------------------------
|
|
81
|
+
// Phase 1: Stream and Index Left Dataset
|
|
82
|
+
// ---------------------------------------------------------
|
|
83
|
+
for await (const batch of leftReader.read(options.leftOptions)) {
|
|
84
|
+
for (let i = 0; i < batch.rows.length; i++) {
|
|
85
|
+
leftRowsCount++;
|
|
86
|
+
const row = batch.rows[i];
|
|
87
|
+
for (const col of Object.keys(row)) {
|
|
88
|
+
allDiscoveredColumns.add(col);
|
|
89
|
+
}
|
|
90
|
+
const { encoded, rawKey } = encodeCompositeKey(row, keys, { coerce: options.coerce });
|
|
91
|
+
const firstSeenRow = seenLeftKeys.get(encoded);
|
|
92
|
+
if (firstSeenRow !== undefined) {
|
|
93
|
+
if (duplicateKey === "error") {
|
|
94
|
+
const keyStr = Object.entries(rawKey)
|
|
95
|
+
.map(([k, v]) => `${k}=${v}`)
|
|
96
|
+
.join(", ");
|
|
97
|
+
throw new DuplicateKeyError({
|
|
98
|
+
dataset: "left",
|
|
99
|
+
key: keyStr,
|
|
100
|
+
rows: [firstSeenRow, leftRowsCount],
|
|
101
|
+
filePath: leftSource,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
if (duplicateKey === "first") {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
seenLeftKeys.set(encoded, leftRowsCount);
|
|
110
|
+
}
|
|
111
|
+
// Determine compared columns for this row
|
|
112
|
+
const rowCompareCols = getEffectiveCompareColumns(Object.keys(row), keys, columns, ignore);
|
|
113
|
+
const hash = computeRowFingerprint(row, rowCompareCols);
|
|
114
|
+
await index.set(encoded, {
|
|
115
|
+
rowNumber: leftRowsCount,
|
|
116
|
+
row,
|
|
117
|
+
hash,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
reportProgress("indexing_left");
|
|
121
|
+
}
|
|
122
|
+
// ---------------------------------------------------------
|
|
123
|
+
// Phase 2: Stream and Compare Right Dataset
|
|
124
|
+
// ---------------------------------------------------------
|
|
125
|
+
const seenRightKeys = new Map();
|
|
126
|
+
for await (const batch of rightReader.read(options.rightOptions)) {
|
|
127
|
+
for (let i = 0; i < batch.rows.length; i++) {
|
|
128
|
+
rightRowsCount++;
|
|
129
|
+
const rightRow = batch.rows[i];
|
|
130
|
+
for (const col of Object.keys(rightRow)) {
|
|
131
|
+
allDiscoveredColumns.add(col);
|
|
132
|
+
}
|
|
133
|
+
const { encoded, rawKey } = encodeCompositeKey(rightRow, keys, { coerce: options.coerce });
|
|
134
|
+
const firstSeenRightRow = seenRightKeys.get(encoded);
|
|
135
|
+
if (firstSeenRightRow !== undefined) {
|
|
136
|
+
if (duplicateKey === "error") {
|
|
137
|
+
const keyStr = Object.entries(rawKey)
|
|
138
|
+
.map(([k, v]) => `${k}=${v}`)
|
|
139
|
+
.join(", ");
|
|
140
|
+
throw new DuplicateKeyError({
|
|
141
|
+
dataset: "right",
|
|
142
|
+
key: keyStr,
|
|
143
|
+
rows: [firstSeenRightRow, rightRowsCount],
|
|
144
|
+
filePath: rightSource,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
if (duplicateKey === "first") {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
seenRightKeys.set(encoded, rightRowsCount);
|
|
153
|
+
}
|
|
154
|
+
const indexed = await index.get(encoded);
|
|
155
|
+
if (!indexed) {
|
|
156
|
+
// Key not in left dataset -> ADDED
|
|
157
|
+
addedCount++;
|
|
158
|
+
yield {
|
|
159
|
+
type: "added",
|
|
160
|
+
key: rawKey,
|
|
161
|
+
encodedKey: encoded,
|
|
162
|
+
row: rightRow,
|
|
163
|
+
rowNumber: rightRowsCount,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
// Key exists in left dataset -> Check for Changes
|
|
168
|
+
const leftRow = indexed.row;
|
|
169
|
+
const combinedKeys = Array.from(new Set([...Object.keys(leftRow), ...Object.keys(rightRow)]));
|
|
170
|
+
const compareCols = getEffectiveCompareColumns(combinedKeys, keys, columns, ignore);
|
|
171
|
+
const comparisonOptions = {
|
|
172
|
+
coerce: options.coerce,
|
|
173
|
+
epsilon: options.epsilon,
|
|
174
|
+
ignoreCase: options.ignoreCase,
|
|
175
|
+
trim: options.trim,
|
|
176
|
+
};
|
|
177
|
+
const changes = compareRows(leftRow, rightRow, compareCols, comparisonOptions);
|
|
178
|
+
if (changes.length > 0) {
|
|
179
|
+
changedCount++;
|
|
180
|
+
yield {
|
|
181
|
+
type: "changed",
|
|
182
|
+
key: rawKey,
|
|
183
|
+
encodedKey: encoded,
|
|
184
|
+
changes,
|
|
185
|
+
leftRow,
|
|
186
|
+
rightRow,
|
|
187
|
+
leftRowNumber: indexed.rowNumber,
|
|
188
|
+
rightRowNumber: rightRowsCount,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
unchangedCount++;
|
|
193
|
+
yield {
|
|
194
|
+
type: "unchanged",
|
|
195
|
+
key: rawKey,
|
|
196
|
+
encodedKey: encoded,
|
|
197
|
+
row: rightRow,
|
|
198
|
+
leftRowNumber: indexed.rowNumber,
|
|
199
|
+
rightRowNumber: rightRowsCount,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
// Delete matched entry from index
|
|
203
|
+
await index.delete(encoded);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
reportProgress("comparing_right");
|
|
207
|
+
}
|
|
208
|
+
// ---------------------------------------------------------
|
|
209
|
+
// Phase 3: Remaining Left Entries -> REMOVED
|
|
210
|
+
// ---------------------------------------------------------
|
|
211
|
+
for await (const [encodedKey, indexed] of index.entries()) {
|
|
212
|
+
removedCount++;
|
|
213
|
+
const rawKey = {};
|
|
214
|
+
for (const k of keys) {
|
|
215
|
+
rawKey[k] = indexed.row[k];
|
|
216
|
+
}
|
|
217
|
+
yield {
|
|
218
|
+
type: "removed",
|
|
219
|
+
key: rawKey,
|
|
220
|
+
encodedKey,
|
|
221
|
+
row: indexed.row,
|
|
222
|
+
rowNumber: indexed.rowNumber,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
reportProgress("finishing");
|
|
226
|
+
}
|
|
227
|
+
finally {
|
|
228
|
+
await index.close();
|
|
229
|
+
if (leftReader?.close)
|
|
230
|
+
await leftReader.close();
|
|
231
|
+
if (rightReader?.close)
|
|
232
|
+
await rightReader.close();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function getEffectiveCompareColumns(rowKeys, keyColumns, explicitColumns, ignoreColumns = []) {
|
|
236
|
+
let targetCols = explicitColumns && explicitColumns.length > 0 ? explicitColumns : rowKeys;
|
|
237
|
+
return targetCols.filter((col) => !keyColumns.includes(col) && !ignoreColumns.includes(col));
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Computes a complete DiffSummary by consuming the diff stream.
|
|
241
|
+
*/
|
|
242
|
+
export async function computeDiff(options) {
|
|
243
|
+
const startTime = Date.now();
|
|
244
|
+
const columnChangesCount = {};
|
|
245
|
+
let added = 0;
|
|
246
|
+
let removed = 0;
|
|
247
|
+
let changed = 0;
|
|
248
|
+
let unchanged = 0;
|
|
249
|
+
let totalLeft = 0;
|
|
250
|
+
let totalRight = 0;
|
|
251
|
+
let recordedSpillStats = undefined;
|
|
252
|
+
const originalOnProgress = options.onProgress;
|
|
253
|
+
const wrappedOptions = {
|
|
254
|
+
...options,
|
|
255
|
+
onProgress: (info) => {
|
|
256
|
+
if (info.isSpilled) {
|
|
257
|
+
recordedSpillStats = { isSpilled: true, spilledBytes: 0 };
|
|
258
|
+
}
|
|
259
|
+
if (originalOnProgress)
|
|
260
|
+
originalOnProgress(info);
|
|
261
|
+
},
|
|
262
|
+
};
|
|
263
|
+
for await (const event of diffRows(wrappedOptions)) {
|
|
264
|
+
switch (event.type) {
|
|
265
|
+
case "added":
|
|
266
|
+
added++;
|
|
267
|
+
totalRight++;
|
|
268
|
+
break;
|
|
269
|
+
case "removed":
|
|
270
|
+
removed++;
|
|
271
|
+
totalLeft++;
|
|
272
|
+
break;
|
|
273
|
+
case "changed":
|
|
274
|
+
changed++;
|
|
275
|
+
totalLeft++;
|
|
276
|
+
totalRight++;
|
|
277
|
+
for (const ch of event.changes) {
|
|
278
|
+
if (!columnChangesCount[ch.column]) {
|
|
279
|
+
columnChangesCount[ch.column] = { changed: 0 };
|
|
280
|
+
}
|
|
281
|
+
columnChangesCount[ch.column].changed++;
|
|
282
|
+
}
|
|
283
|
+
break;
|
|
284
|
+
case "unchanged":
|
|
285
|
+
unchanged++;
|
|
286
|
+
totalLeft++;
|
|
287
|
+
totalRight++;
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
// Schema diff if requested
|
|
292
|
+
let schemaDiffResult = undefined;
|
|
293
|
+
const leftInput = options.left ?? options.leftPath;
|
|
294
|
+
const rightInput = options.right ?? options.rightPath;
|
|
295
|
+
if (options.includeSchema !== false && leftInput && rightInput) {
|
|
296
|
+
try {
|
|
297
|
+
const leftOpts = {
|
|
298
|
+
...options.leftOptions,
|
|
299
|
+
format: options.fromLeft ?? options.leftOptions?.format,
|
|
300
|
+
};
|
|
301
|
+
const rightOpts = {
|
|
302
|
+
...options.rightOptions,
|
|
303
|
+
format: options.fromRight ?? options.rightOptions?.format,
|
|
304
|
+
};
|
|
305
|
+
const { reader: lReader } = createReaderFromSource(leftInput, leftOpts);
|
|
306
|
+
const { reader: rReader } = createReaderFromSource(rightInput, rightOpts);
|
|
307
|
+
schemaDiffResult = await computeSchemaDiff(lReader, rReader);
|
|
308
|
+
}
|
|
309
|
+
catch {
|
|
310
|
+
// Ignore schema diff failure
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
const leftSourceName = typeof leftInput === "string" ? leftInput : options.leftOptions?.filePath || "left";
|
|
314
|
+
const rightSourceName = typeof rightInput === "string" ? rightInput : options.rightOptions?.filePath || "right";
|
|
315
|
+
return {
|
|
316
|
+
leftSource: leftSourceName,
|
|
317
|
+
rightSource: rightSourceName,
|
|
318
|
+
keyColumns: options.keys,
|
|
319
|
+
rows: {
|
|
320
|
+
added,
|
|
321
|
+
removed,
|
|
322
|
+
changed,
|
|
323
|
+
unchanged,
|
|
324
|
+
totalLeft,
|
|
325
|
+
totalRight,
|
|
326
|
+
},
|
|
327
|
+
columns: columnChangesCount,
|
|
328
|
+
schema: schemaDiffResult,
|
|
329
|
+
executionTimeMs: Date.now() - startTime,
|
|
330
|
+
spillStats: recordedSpillStats,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/diff/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Row } from "../core/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Computes a fast deterministic 32-bit FNV-1a hash over canonicalized column-value pairs in a row.
|
|
4
|
+
*/
|
|
5
|
+
export declare function computeRowFingerprint(row: Row, compareColumns: string[]): number;
|
|
6
|
+
//# sourceMappingURL=hash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/diff/hash.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAE5C;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,MAAM,CA+ChF"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Computes a fast deterministic 32-bit FNV-1a hash over canonicalized column-value pairs in a row.
|
|
3
|
+
*/
|
|
4
|
+
export function computeRowFingerprint(row, compareColumns) {
|
|
5
|
+
let hash = 2166136261;
|
|
6
|
+
for (let i = 0; i < compareColumns.length; i++) {
|
|
7
|
+
const col = compareColumns[i];
|
|
8
|
+
const val = row[col];
|
|
9
|
+
// Hash column name
|
|
10
|
+
for (let c = 0; c < col.length; c++) {
|
|
11
|
+
hash ^= col.charCodeAt(c);
|
|
12
|
+
hash = Math.imul(hash, 16777619);
|
|
13
|
+
}
|
|
14
|
+
// Hash separator
|
|
15
|
+
hash ^= 58; // ':'
|
|
16
|
+
hash = Math.imul(hash, 16777619);
|
|
17
|
+
// Hash value representation
|
|
18
|
+
if (val === undefined) {
|
|
19
|
+
hash ^= 85; // 'U'
|
|
20
|
+
hash = Math.imul(hash, 16777619);
|
|
21
|
+
}
|
|
22
|
+
else if (val === null) {
|
|
23
|
+
hash ^= 78; // 'N'
|
|
24
|
+
hash = Math.imul(hash, 16777619);
|
|
25
|
+
}
|
|
26
|
+
else if (typeof val === "number") {
|
|
27
|
+
// Convert number to integer or float representation
|
|
28
|
+
const str = String(val);
|
|
29
|
+
for (let c = 0; c < str.length; c++) {
|
|
30
|
+
hash ^= str.charCodeAt(c);
|
|
31
|
+
hash = Math.imul(hash, 16777619);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
else if (typeof val === "boolean") {
|
|
35
|
+
hash ^= val ? 49 : 48; // '1' or '0'
|
|
36
|
+
hash = Math.imul(hash, 16777619);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
const str = typeof val === "string" ? val : JSON.stringify(val);
|
|
40
|
+
for (let c = 0; c < str.length; c++) {
|
|
41
|
+
hash ^= str.charCodeAt(c);
|
|
42
|
+
hash = Math.imul(hash, 16777619);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
hash ^= 124; // '|'
|
|
46
|
+
hash = Math.imul(hash, 16777619);
|
|
47
|
+
}
|
|
48
|
+
return hash >>> 0;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=hash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/diff/hash.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAQ,EAAE,cAAwB;IACtE,IAAI,IAAI,GAAG,UAAU,CAAC;IAEtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/C,MAAM,GAAG,GAAG,cAAc,CAAC,CAAC,CAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QAErB,mBAAmB;QACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACpC,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAC1B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACnC,CAAC;QAED,iBAAiB;QACjB,IAAI,IAAI,EAAE,CAAC,CAAC,MAAM;QAClB,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAEjC,4BAA4B;QAC5B,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,IAAI,IAAI,EAAE,CAAC,CAAC,MAAM;YAClB,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACnC,CAAC;aAAM,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACxB,IAAI,IAAI,EAAE,CAAC,CAAC,MAAM;YAClB,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACnC,CAAC;aAAM,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YACnC,oDAAoD;YACpD,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;YACxB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACpC,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;gBAC1B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;aAAM,IAAI,OAAO,GAAG,KAAK,SAAS,EAAE,CAAC;YACpC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,aAAa;YACpC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YAChE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACpC,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;gBAC1B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;QAED,IAAI,IAAI,GAAG,CAAC,CAAC,MAAM;QACnB,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACnC,CAAC;IAED,OAAO,IAAI,KAAK,CAAC,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Row } from "../core/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Encodes a single primitive key value into a collision-free typed string.
|
|
4
|
+
*/
|
|
5
|
+
export declare function encodeSingleKeyValue(value: unknown, coerce?: boolean): string;
|
|
6
|
+
export interface EncodedKeyResult {
|
|
7
|
+
encoded: string;
|
|
8
|
+
rawKey: Record<string, unknown>;
|
|
9
|
+
hasMissingOrNull: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Encodes row key columns into a deterministic, collision-proof typed composite key string.
|
|
13
|
+
*/
|
|
14
|
+
export declare function encodeCompositeKey(row: Row, keyColumns: string[], options?: {
|
|
15
|
+
coerce?: boolean;
|
|
16
|
+
}): EncodedKeyResult;
|
|
17
|
+
/**
|
|
18
|
+
* Formats a key object for human-readable output (e.g. "id=42" or "country=TR, id=101").
|
|
19
|
+
*/
|
|
20
|
+
export declare function formatKeyForDisplay(rawKey: Record<string, unknown>): string;
|
|
21
|
+
//# sourceMappingURL=key.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key.d.ts","sourceRoot":"","sources":["../../src/diff/key.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAE5C;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,UAAQ,GAAG,MAAM,CA6C3E;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,GAAG,EACR,UAAU,EAAE,MAAM,EAAE,EACpB,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,gBAAgB,CAoClB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAkB3E"}
|
package/dist/diff/key.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encodes a single primitive key value into a collision-free typed string.
|
|
3
|
+
*/
|
|
4
|
+
export function encodeSingleKeyValue(value, coerce = false) {
|
|
5
|
+
if (value === undefined) {
|
|
6
|
+
return "U";
|
|
7
|
+
}
|
|
8
|
+
if (value === null) {
|
|
9
|
+
return "N";
|
|
10
|
+
}
|
|
11
|
+
if (typeof value === "boolean") {
|
|
12
|
+
return value ? "B:1" : "B:0";
|
|
13
|
+
}
|
|
14
|
+
if (typeof value === "number") {
|
|
15
|
+
if (coerce) {
|
|
16
|
+
// In coerce mode, represent numeric values uniformly
|
|
17
|
+
return `NUM:${value}`;
|
|
18
|
+
}
|
|
19
|
+
return Number.isInteger(value) ? `I:${value}` : `D:${value}`;
|
|
20
|
+
}
|
|
21
|
+
if (typeof value === "string") {
|
|
22
|
+
if (coerce) {
|
|
23
|
+
const trimmed = value.trim();
|
|
24
|
+
const lower = trimmed.toLowerCase();
|
|
25
|
+
if (lower === "true")
|
|
26
|
+
return "B:1";
|
|
27
|
+
if (lower === "false")
|
|
28
|
+
return "B:0";
|
|
29
|
+
// Test integer / float
|
|
30
|
+
if (/^-?\d+$/.test(trimmed)) {
|
|
31
|
+
return `NUM:${Number.parseInt(trimmed, 10)}`;
|
|
32
|
+
}
|
|
33
|
+
if (/^-?\d+\.\d+$/.test(trimmed)) {
|
|
34
|
+
return `NUM:${Number.parseFloat(trimmed)}`;
|
|
35
|
+
}
|
|
36
|
+
return `S:${trimmed.length}:${trimmed}`;
|
|
37
|
+
}
|
|
38
|
+
return `S:${value.length}:${value}`;
|
|
39
|
+
}
|
|
40
|
+
if (value instanceof Date) {
|
|
41
|
+
return `T:${value.getTime()}`;
|
|
42
|
+
}
|
|
43
|
+
const json = JSON.stringify(value);
|
|
44
|
+
return `O:${json.length}:${json}`;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Encodes row key columns into a deterministic, collision-proof typed composite key string.
|
|
48
|
+
*/
|
|
49
|
+
export function encodeCompositeKey(row, keyColumns, options = {}) {
|
|
50
|
+
if (keyColumns.length === 1) {
|
|
51
|
+
const col = keyColumns[0];
|
|
52
|
+
const val = row[col];
|
|
53
|
+
return {
|
|
54
|
+
encoded: encodeSingleKeyValue(val, options.coerce),
|
|
55
|
+
rawKey: { [col]: val },
|
|
56
|
+
hasMissingOrNull: val === null || val === undefined,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
const rawKey = {};
|
|
60
|
+
let encoded = "";
|
|
61
|
+
let hasMissingOrNull = false;
|
|
62
|
+
for (let i = 0; i < keyColumns.length; i++) {
|
|
63
|
+
const col = keyColumns[i];
|
|
64
|
+
const val = row[col];
|
|
65
|
+
rawKey[col] = val;
|
|
66
|
+
if (val === null || val === undefined) {
|
|
67
|
+
hasMissingOrNull = true;
|
|
68
|
+
}
|
|
69
|
+
const encodedVal = encodeSingleKeyValue(val, options.coerce);
|
|
70
|
+
if (i > 0) {
|
|
71
|
+
encoded += "|";
|
|
72
|
+
}
|
|
73
|
+
encoded += encodedVal;
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
encoded,
|
|
77
|
+
rawKey,
|
|
78
|
+
hasMissingOrNull,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Formats a key object for human-readable output (e.g. "id=42" or "country=TR, id=101").
|
|
83
|
+
*/
|
|
84
|
+
export function formatKeyForDisplay(rawKey) {
|
|
85
|
+
const entries = Object.entries(rawKey);
|
|
86
|
+
if (entries.length === 0)
|
|
87
|
+
return "(none)";
|
|
88
|
+
return entries
|
|
89
|
+
.map(([col, val]) => {
|
|
90
|
+
let displayVal;
|
|
91
|
+
if (val === undefined) {
|
|
92
|
+
displayVal = "<missing>";
|
|
93
|
+
}
|
|
94
|
+
else if (val === null) {
|
|
95
|
+
displayVal = "null";
|
|
96
|
+
}
|
|
97
|
+
else if (typeof val === "object") {
|
|
98
|
+
displayVal = JSON.stringify(val);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
displayVal = String(val);
|
|
102
|
+
}
|
|
103
|
+
return `${col}=${displayVal}`;
|
|
104
|
+
})
|
|
105
|
+
.join(", ");
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=key.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key.js","sourceRoot":"","sources":["../../src/diff/key.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { DiffEvent, DiffSummary } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Formats a single DiffEvent for --format rows output.
|
|
4
|
+
*/
|
|
5
|
+
export declare function formatRowEvent(event: DiffEvent): string | null;
|
|
6
|
+
/**
|
|
7
|
+
* Formats a single DiffEvent for --format patch (JSONL) output.
|
|
8
|
+
*/
|
|
9
|
+
export declare function formatPatchEvent(event: DiffEvent): string | null;
|
|
10
|
+
/**
|
|
11
|
+
* Formats complete DiffSummary as human-readable ASCII text.
|
|
12
|
+
*/
|
|
13
|
+
export declare function formatSummary(summary: DiffSummary): string;
|
|
14
|
+
/**
|
|
15
|
+
* Formats complete DiffSummary as JSON string.
|
|
16
|
+
*/
|
|
17
|
+
export declare function formatJson(summary: DiffSummary): string;
|
|
18
|
+
//# sourceMappingURL=reporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../../src/diff/reporter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AASzD;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CA0B9D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAwChE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAwD1D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAWvD"}
|