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,344 @@
1
+ import { promises as fsPromises } from "node:fs";
2
+ import * as path from "node:path";
3
+ import { FileSystemError } from "../core/errors.js";
4
+ import { createGlobMatcher } from "./glob.js";
5
+ import { computeFileHash } from "./hash.js";
6
+ import { inferMimeAndCategory } from "./mime.js";
7
+ /**
8
+ * Normalizes a relative path to standard forward slashes.
9
+ */
10
+ function normalizeRelativePath(relPath) {
11
+ let normalized = relPath.replace(/\\/g, "/");
12
+ while (normalized.startsWith("./")) {
13
+ normalized = normalized.slice(2);
14
+ }
15
+ return normalized || ".";
16
+ }
17
+ /**
18
+ * First-class streaming filesystem reader.
19
+ * Converts directories and files into streaming tabular DataBatches.
20
+ */
21
+ export class FileSystemReader {
22
+ options;
23
+ constructor(optionsOrRoot) {
24
+ if (typeof optionsOrRoot === "string") {
25
+ this.options = { root: optionsOrRoot };
26
+ }
27
+ else {
28
+ this.options = { ...optionsOrRoot };
29
+ }
30
+ }
31
+ /**
32
+ * Reads the filesystem stream yielding DataBatches.
33
+ */
34
+ async *read(readOptions) {
35
+ const rootPath = path.resolve(this.options.root);
36
+ const recursive = this.options.recursive ?? true;
37
+ const maxDepth = this.options.maxDepth ?? Infinity;
38
+ const includeHidden = this.options.hidden ?? false;
39
+ const followSymlinks = this.options.followSymlinks ?? false;
40
+ const typeFilter = this.options.type ?? "file";
41
+ const hashAlgorithm = this.options.hash ?? false;
42
+ const enableMime = this.options.mime ?? false;
43
+ const concurrency = Math.max(1, this.options.concurrency ?? 8);
44
+ const onError = this.options.onError ?? "fail";
45
+ const deterministic = this.options.deterministic ?? false;
46
+ const batchSize = readOptions?.batchSize ?? this.options.batchSize ?? 1000;
47
+ const includeMatcher = this.options.include ? createGlobMatcher(this.options.include) : () => true;
48
+ const excludeMatcher = this.options.exclude
49
+ ? createGlobMatcher(this.options.exclude)
50
+ : () => false;
51
+ // Check if root exists
52
+ let rootStat;
53
+ try {
54
+ rootStat = await fsPromises.stat(rootPath);
55
+ }
56
+ catch (err) {
57
+ const fsErr = new FileSystemError(`Root path not found or unreadable: "${rootPath}"`, {
58
+ path: rootPath,
59
+ operation: "stat",
60
+ cause: err instanceof Error ? err : String(err),
61
+ });
62
+ if (onError === "fail")
63
+ throw fsErr;
64
+ return;
65
+ }
66
+ let rowsAccumulator = [];
67
+ let offset = 0;
68
+ // Helper to flush batch
69
+ const flushBatch = () => {
70
+ if (rowsAccumulator.length >= batchSize) {
71
+ const batch = {
72
+ rows: rowsAccumulator,
73
+ offset,
74
+ };
75
+ offset += rowsAccumulator.length;
76
+ rowsAccumulator = [];
77
+ return batch;
78
+ }
79
+ return null;
80
+ };
81
+ // Helper to enrich a single entry
82
+ const enrichFileEntry = async (fullPath, relPath, dirPath, name, stat, isSymlink) => {
83
+ try {
84
+ const dotIdx = name.lastIndexOf(".");
85
+ let basename = name;
86
+ let extension = "";
87
+ if (dotIdx > 0) {
88
+ basename = name.slice(0, dotIdx);
89
+ extension = name.slice(dotIdx + 1).toLowerCase();
90
+ }
91
+ let fileType = "file";
92
+ if (isSymlink) {
93
+ fileType = "symlink";
94
+ }
95
+ else if (stat.isDirectory()) {
96
+ fileType = "directory";
97
+ }
98
+ const normRelPath = normalizeRelativePath(relPath);
99
+ const record = {
100
+ path: fullPath,
101
+ relative_path: normRelPath,
102
+ name,
103
+ basename,
104
+ extension,
105
+ directory: dirPath,
106
+ type: fileType,
107
+ size: stat.isDirectory() ? 0 : stat.size,
108
+ created_at: stat.birthtime ? stat.birthtime.toISOString() : stat.ctime.toISOString(),
109
+ modified_at: stat.mtime.toISOString(),
110
+ mode: stat.mode,
111
+ is_file: stat.isFile(),
112
+ is_directory: stat.isDirectory(),
113
+ is_symlink: isSymlink,
114
+ };
115
+ if (!deterministic) {
116
+ record.accessed_at = stat.atime.toISOString();
117
+ }
118
+ if (enableMime || this.options.category) {
119
+ const { mime, category } = inferMimeAndCategory(extension || name);
120
+ if (enableMime)
121
+ record.mime = mime;
122
+ record.category = category;
123
+ }
124
+ if (hashAlgorithm && stat.isFile()) {
125
+ record.hash = await computeFileHash(fullPath, hashAlgorithm);
126
+ }
127
+ return record;
128
+ }
129
+ catch (err) {
130
+ const fsErr = new FileSystemError(`Failed to process file "${fullPath}"`, {
131
+ path: fullPath,
132
+ operation: "enrich",
133
+ cause: err instanceof Error ? err : String(err),
134
+ });
135
+ if (onError === "fail")
136
+ throw fsErr;
137
+ return null;
138
+ }
139
+ };
140
+ // Case 1: Root is a single file
141
+ if (!rootStat.isDirectory()) {
142
+ const name = path.basename(rootPath);
143
+ const dirPath = path.dirname(rootPath);
144
+ const record = await enrichFileEntry(rootPath, name, dirPath, name, rootStat, false);
145
+ if (record) {
146
+ yield {
147
+ rows: [record],
148
+ offset: 0,
149
+ };
150
+ }
151
+ return;
152
+ }
153
+ // Case 2: Root is a directory - walk with bounded memory and concurrency
154
+ const visitedRealPaths = new Set();
155
+ visitedRealPaths.add(rootPath);
156
+ const dirQueue = [{ dirPath: rootPath, depth: 0 }];
157
+ while (dirQueue.length > 0) {
158
+ const current = dirQueue.shift();
159
+ let dirHandle;
160
+ try {
161
+ dirHandle = await fsPromises.opendir(current.dirPath);
162
+ }
163
+ catch (err) {
164
+ const fsErr = new FileSystemError(`Cannot open directory "${current.dirPath}"`, {
165
+ path: current.dirPath,
166
+ operation: "opendir",
167
+ cause: err instanceof Error ? err : String(err),
168
+ });
169
+ if (onError === "fail")
170
+ throw fsErr;
171
+ continue;
172
+ }
173
+ const pendingWork = [];
174
+ try {
175
+ for await (const dirent of dirHandle) {
176
+ const entryName = dirent.name;
177
+ // Hidden file filtering
178
+ if (!includeHidden && entryName.startsWith(".")) {
179
+ continue;
180
+ }
181
+ // Default safe exclusions when not hidden
182
+ if (!includeHidden && (entryName === ".git" || entryName === "node_modules")) {
183
+ continue;
184
+ }
185
+ const fullPath = path.join(current.dirPath, entryName);
186
+ const relPath = normalizeRelativePath(path.relative(rootPath, fullPath));
187
+ // Check excludes
188
+ if (excludeMatcher(relPath)) {
189
+ continue;
190
+ }
191
+ if (dirent.isDirectory()) {
192
+ if (recursive && current.depth + 1 <= maxDepth) {
193
+ dirQueue.push({ dirPath: fullPath, depth: current.depth + 1 });
194
+ }
195
+ if (typeFilter === "directory" || typeFilter === "all") {
196
+ if (includeMatcher(relPath)) {
197
+ pendingWork.push({ fullPath, relPath, dirent });
198
+ }
199
+ }
200
+ }
201
+ else if (dirent.isSymbolicLink()) {
202
+ if (followSymlinks) {
203
+ try {
204
+ const realPath = await fsPromises.realpath(fullPath);
205
+ if (visitedRealPaths.has(realPath)) {
206
+ // Cycle detected, skip
207
+ continue;
208
+ }
209
+ visitedRealPaths.add(realPath);
210
+ const targetStat = await fsPromises.stat(fullPath);
211
+ if (targetStat.isDirectory()) {
212
+ if (recursive && current.depth + 1 <= maxDepth) {
213
+ dirQueue.push({ dirPath: fullPath, depth: current.depth + 1 });
214
+ }
215
+ if (typeFilter === "directory" || typeFilter === "all") {
216
+ if (includeMatcher(relPath)) {
217
+ pendingWork.push({ fullPath, relPath, dirent });
218
+ }
219
+ }
220
+ }
221
+ else if (targetStat.isFile()) {
222
+ if (typeFilter === "file" || typeFilter === "symlink" || typeFilter === "all") {
223
+ if (includeMatcher(relPath)) {
224
+ pendingWork.push({ fullPath, relPath, dirent });
225
+ }
226
+ }
227
+ }
228
+ }
229
+ catch (err) {
230
+ if (onError === "fail") {
231
+ throw new FileSystemError(`Broken symlink at "${fullPath}"`, {
232
+ path: fullPath,
233
+ operation: "realpath",
234
+ cause: err instanceof Error ? err : String(err),
235
+ });
236
+ }
237
+ }
238
+ }
239
+ else {
240
+ if (typeFilter === "symlink" || typeFilter === "all") {
241
+ if (includeMatcher(relPath)) {
242
+ pendingWork.push({ fullPath, relPath, dirent });
243
+ }
244
+ }
245
+ }
246
+ }
247
+ else if (dirent.isFile()) {
248
+ if (typeFilter === "file" || typeFilter === "all") {
249
+ if (includeMatcher(relPath)) {
250
+ pendingWork.push({ fullPath, relPath, dirent });
251
+ }
252
+ }
253
+ }
254
+ }
255
+ }
256
+ finally {
257
+ // opendir automatically closes on iterator completion
258
+ }
259
+ // Process pending work in chunks using bounded concurrency pool
260
+ for (let i = 0; i < pendingWork.length; i += concurrency) {
261
+ const chunk = pendingWork.slice(i, i + concurrency);
262
+ const results = await Promise.all(chunk.map(async (item) => {
263
+ try {
264
+ const isSymlink = item.dirent.isSymbolicLink();
265
+ const stat = isSymlink && !followSymlinks
266
+ ? await fsPromises.lstat(item.fullPath)
267
+ : await fsPromises.stat(item.fullPath);
268
+ return await enrichFileEntry(item.fullPath, item.relPath, current.dirPath, item.dirent.name, stat, isSymlink);
269
+ }
270
+ catch (err) {
271
+ const fsErr = new FileSystemError(`Cannot stat "${item.fullPath}"`, {
272
+ path: item.fullPath,
273
+ operation: "stat",
274
+ cause: err instanceof Error ? err : String(err),
275
+ });
276
+ if (onError === "fail")
277
+ throw fsErr;
278
+ return null;
279
+ }
280
+ }));
281
+ for (const record of results) {
282
+ if (record) {
283
+ rowsAccumulator.push(record);
284
+ const batch = flushBatch();
285
+ if (batch) {
286
+ yield batch;
287
+ }
288
+ }
289
+ }
290
+ }
291
+ }
292
+ // Flush any remaining rows
293
+ if (rowsAccumulator.length > 0) {
294
+ yield {
295
+ rows: rowsAccumulator,
296
+ offset,
297
+ };
298
+ offset += rowsAccumulator.length;
299
+ rowsAccumulator = [];
300
+ }
301
+ }
302
+ /**
303
+ * Inspects filesystem directory metadata without full memory accumulation.
304
+ */
305
+ async inspect(_options) {
306
+ let totalFiles = 0;
307
+ let totalSizeBytes = 0;
308
+ const extensionCounts = new Map();
309
+ for await (const batch of this.read({ batchSize: 5000 })) {
310
+ for (const row of batch.rows) {
311
+ totalFiles += 1;
312
+ totalSizeBytes += Number(row["size"] ?? 0);
313
+ const ext = String(row["extension"] ?? "") || "<none>";
314
+ extensionCounts.set(ext, (extensionCounts.get(ext) ?? 0) + 1);
315
+ }
316
+ }
317
+ const columns = [
318
+ { name: "path", type: "string", nullPercentage: 0 },
319
+ { name: "relative_path", type: "string", nullPercentage: 0 },
320
+ { name: "name", type: "string", nullPercentage: 0 },
321
+ { name: "extension", type: "string", nullPercentage: 0 },
322
+ { name: "type", type: "string", nullPercentage: 0 },
323
+ { name: "size", type: "integer", nullPercentage: 0 },
324
+ { name: "created_at", type: "date", nullPercentage: 0 },
325
+ { name: "modified_at", type: "date", nullPercentage: 0 },
326
+ { name: "is_file", type: "boolean", nullPercentage: 0 },
327
+ { name: "is_directory", type: "boolean", nullPercentage: 0 },
328
+ ];
329
+ if (this.options.hash) {
330
+ columns.push({ name: "hash", type: "string", nullPercentage: 0 });
331
+ }
332
+ if (this.options.mime) {
333
+ columns.push({ name: "mime", type: "string", nullPercentage: 0 });
334
+ }
335
+ return {
336
+ format: "FILESYSTEM",
337
+ rowCount: totalFiles,
338
+ sizeBytes: totalSizeBytes,
339
+ columnCount: columns.length,
340
+ columns,
341
+ };
342
+ }
343
+ }
344
+ //# sourceMappingURL=reader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reader.js","sourceRoot":"","sources":["../../src/files/reader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ export type FileType = "file" | "directory" | "symlink";
2
+ export type FileTypeFilter = "file" | "directory" | "symlink" | "all";
3
+ export type HashAlgorithm = "sha256" | "sha1" | "md5" | "fast";
4
+ export type FileCategory = "image" | "video" | "audio" | "archive" | "document" | "data" | "code" | "executable" | "font" | "other";
5
+ export interface FileRecord {
6
+ path: string;
7
+ relative_path: string;
8
+ name: string;
9
+ basename: string;
10
+ extension: string;
11
+ directory: string;
12
+ type: FileType;
13
+ size: number;
14
+ created_at: string;
15
+ modified_at: string;
16
+ accessed_at?: string;
17
+ mode: number;
18
+ is_file: boolean;
19
+ is_directory: boolean;
20
+ is_symlink: boolean;
21
+ hash?: string;
22
+ mime?: string;
23
+ category?: FileCategory;
24
+ [key: string]: unknown;
25
+ }
26
+ export interface FileSystemReaderOptions {
27
+ root: string;
28
+ recursive?: boolean;
29
+ maxDepth?: number;
30
+ include?: string[];
31
+ exclude?: string[];
32
+ followSymlinks?: boolean;
33
+ hidden?: boolean;
34
+ type?: FileTypeFilter;
35
+ hash?: false | HashAlgorithm;
36
+ mime?: boolean;
37
+ category?: boolean;
38
+ concurrency?: number;
39
+ onError?: "fail" | "skip";
40
+ deterministic?: boolean;
41
+ batchSize?: number;
42
+ }
43
+ export interface FileMetadataEnricher {
44
+ name: string;
45
+ enrich(file: FileRecord): Promise<Record<string, unknown>>;
46
+ }
47
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/files/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;AAExD,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,KAAK,CAAC;AAEtE,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AAE/D,MAAM,MAAM,YAAY,GACpB,OAAO,GACP,OAAO,GACP,OAAO,GACP,SAAS,GACT,UAAU,GACV,MAAM,GACN,MAAM,GACN,YAAY,GACZ,MAAM,GACN,OAAO,CAAC;AAEZ,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,IAAI,CAAC,EAAE,KAAK,GAAG,aAAa,CAAC;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC5D"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/files/types.ts"],"names":[],"mappings":""}
package/dist/index.d.ts CHANGED
@@ -2,7 +2,12 @@ export * from "./core/types.js";
2
2
  export * from "./core/errors.js";
3
3
  export * from "./core/batch.js";
4
4
  export * from "./core/pipeline.js";
5
- export { CSVReader, type CSVReaderOptions, JSONReader, type JSONReaderOptions, JSONLReader, type JSONLReaderOptions, ParquetReader, type ParquetReaderOptions, XLSXReader, type XLSXReaderOptions, createReader, inferFormatFromPath as inferReaderFormatFromPath, } from "./readers/index.js";
5
+ export { CSVReader, type CSVReaderOptions, JSONReader, type JSONReaderOptions, JSONLReader, type JSONLReaderOptions, ParquetReader, type ParquetReaderOptions, XLSXReader, type XLSXReaderOptions, FileSystemReader, createReader, inferFormatFromPath as inferReaderFormatFromPath, } from "./readers/index.js";
6
+ export * from "./files/types.js";
7
+ export * from "./files/glob.js";
8
+ export * from "./files/mime.js";
9
+ export * from "./files/hash.js";
10
+ export * from "./files/reader.js";
6
11
  export { CSVWriter, type CSVWriterOptions, JSONWriter, JSONLWriter, MarkdownWriter, type MarkdownWriterOptions, ParquetWriter, type ParquetWriterOptions, XLSXWriter, type XLSXWriterOptions, createWriter, inferFormatFromPath as inferWriterFormatFromPath, } from "./writers/index.js";
7
12
  export * from "./transforms/select.js";
8
13
  export * from "./transforms/rename.js";
@@ -16,6 +21,16 @@ export * from "./analytics/reduce.js";
16
21
  export * from "./analytics/schema-inference.js";
17
22
  export * from "./analytics/semantic-types.js";
18
23
  export * from "./analytics/validator.js";
24
+ export * from "./diff/types.js";
25
+ export * from "./diff/key.js";
26
+ export * from "./diff/comparator.js";
27
+ export * from "./diff/hash.js";
28
+ export * from "./diff/schema.js";
29
+ export * from "./diff/engine.js";
30
+ export * from "./diff/reporter.js";
31
+ export * from "./diff/storage/memory-index.js";
32
+ export * from "./diff/storage/disk-index.js";
33
+ export * from "./diff/storage/spillable-index.js";
19
34
  export * from "./utils/compression.js";
20
35
  export * from "./utils/formatting.js";
21
36
  export * from "./utils/progress.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AAGnC,OAAO,EACL,SAAS,EACT,KAAK,gBAAgB,EACrB,UAAU,EACV,KAAK,iBAAiB,EACtB,WAAW,EACX,KAAK,kBAAkB,EACvB,aAAa,EACb,KAAK,oBAAoB,EACzB,UAAU,EACV,KAAK,iBAAiB,EACtB,YAAY,EACZ,mBAAmB,IAAI,yBAAyB,GACjD,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,SAAS,EACT,KAAK,gBAAgB,EACrB,UAAU,EACV,WAAW,EACX,cAAc,EACd,KAAK,qBAAqB,EAC1B,aAAa,EACb,KAAK,oBAAoB,EACzB,UAAU,EACV,KAAK,iBAAiB,EACtB,YAAY,EACZ,mBAAmB,IAAI,yBAAyB,GACjD,MAAM,oBAAoB,CAAC;AAG5B,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AAGpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iCAAiC,CAAC;AAChD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AAGzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AAGnC,OAAO,EACL,SAAS,EACT,KAAK,gBAAgB,EACrB,UAAU,EACV,KAAK,iBAAiB,EACtB,WAAW,EACX,KAAK,kBAAkB,EACvB,aAAa,EACb,KAAK,oBAAoB,EACzB,UAAU,EACV,KAAK,iBAAiB,EACtB,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,IAAI,yBAAyB,GACjD,MAAM,oBAAoB,CAAC;AAG5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAIlC,OAAO,EACL,SAAS,EACT,KAAK,gBAAgB,EACrB,UAAU,EACV,WAAW,EACX,cAAc,EACd,KAAK,qBAAqB,EAC1B,aAAa,EACb,KAAK,oBAAoB,EACzB,UAAU,EACV,KAAK,iBAAiB,EACtB,YAAY,EACZ,mBAAmB,IAAI,yBAAyB,GACjD,MAAM,oBAAoB,CAAC;AAG5B,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AAGpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iCAAiC,CAAC;AAChD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AAGzC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,mCAAmC,CAAC;AAGlD,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC"}
package/dist/index.js CHANGED
@@ -4,7 +4,13 @@ export * from "./core/errors.js";
4
4
  export * from "./core/batch.js";
5
5
  export * from "./core/pipeline.js";
6
6
  // Readers
7
- export { CSVReader, JSONReader, JSONLReader, ParquetReader, XLSXReader, createReader, inferFormatFromPath as inferReaderFormatFromPath, } from "./readers/index.js";
7
+ export { CSVReader, JSONReader, JSONLReader, ParquetReader, XLSXReader, FileSystemReader, createReader, inferFormatFromPath as inferReaderFormatFromPath, } from "./readers/index.js";
8
+ // Filesystem Subsystem
9
+ export * from "./files/types.js";
10
+ export * from "./files/glob.js";
11
+ export * from "./files/mime.js";
12
+ export * from "./files/hash.js";
13
+ export * from "./files/reader.js";
8
14
  // Writers
9
15
  export { CSVWriter, JSONWriter, JSONLWriter, MarkdownWriter, ParquetWriter, XLSXWriter, createWriter, inferFormatFromPath as inferWriterFormatFromPath, } from "./writers/index.js";
10
16
  // Transforms
@@ -21,6 +27,17 @@ export * from "./analytics/reduce.js";
21
27
  export * from "./analytics/schema-inference.js";
22
28
  export * from "./analytics/semantic-types.js";
23
29
  export * from "./analytics/validator.js";
30
+ // Diff Engine & Storage
31
+ export * from "./diff/types.js";
32
+ export * from "./diff/key.js";
33
+ export * from "./diff/comparator.js";
34
+ export * from "./diff/hash.js";
35
+ export * from "./diff/schema.js";
36
+ export * from "./diff/engine.js";
37
+ export * from "./diff/reporter.js";
38
+ export * from "./diff/storage/memory-index.js";
39
+ export * from "./diff/storage/disk-index.js";
40
+ export * from "./diff/storage/spillable-index.js";
24
41
  // Utilities
25
42
  export * from "./utils/compression.js";
26
43
  export * from "./utils/formatting.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO;AACP,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AAEnC,UAAU;AACV,OAAO,EACL,SAAS,EAET,UAAU,EAEV,WAAW,EAEX,aAAa,EAEb,UAAU,EAEV,YAAY,EACZ,mBAAmB,IAAI,yBAAyB,GACjD,MAAM,oBAAoB,CAAC;AAE5B,UAAU;AACV,OAAO,EACL,SAAS,EAET,UAAU,EACV,WAAW,EACX,cAAc,EAEd,aAAa,EAEb,UAAU,EAEV,YAAY,EACZ,mBAAmB,IAAI,yBAAyB,GACjD,MAAM,oBAAoB,CAAC;AAE5B,aAAa;AACb,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AAEpC,YAAY;AACZ,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iCAAiC,CAAC;AAChD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AAEzC,YAAY;AACZ,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO;AACP,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AAEnC,UAAU;AACV,OAAO,EACL,SAAS,EAET,UAAU,EAEV,WAAW,EAEX,aAAa,EAEb,UAAU,EAEV,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,IAAI,yBAAyB,GACjD,MAAM,oBAAoB,CAAC;AAE5B,uBAAuB;AACvB,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAGlC,UAAU;AACV,OAAO,EACL,SAAS,EAET,UAAU,EACV,WAAW,EACX,cAAc,EAEd,aAAa,EAEb,UAAU,EAEV,YAAY,EACZ,mBAAmB,IAAI,yBAAyB,GACjD,MAAM,oBAAoB,CAAC;AAE5B,aAAa;AACb,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AAEpC,YAAY;AACZ,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iCAAiC,CAAC;AAChD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AAEzC,wBAAwB;AACxB,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,mCAAmC,CAAC;AAElD,YAAY;AACZ,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"csv.d.ts","sourceRoot":"","sources":["../../src/readers/csv.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,KAAK,EAEV,UAAU,EACV,kBAAkB,EAClB,aAAa,EAEb,aAAa,EACd,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,qBAAa,SAAU,YAAW,aAAa;IAC7C,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,OAAO,CAAmB;gBAEtB,KAAK,EAAE,QAAQ,GAAG,MAAM,EAAE,OAAO,GAAE,gBAAqB;IAQpE,OAAO,CAAC,cAAc;IAKtB;;OAEG;WACW,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IA2B9C,IAAI,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,UAAU;IA+N1C,OAAO,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAsBpE"}
1
+ {"version":3,"file":"csv.d.ts","sourceRoot":"","sources":["../../src/readers/csv.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,KAAK,EAEV,UAAU,EACV,kBAAkB,EAClB,aAAa,EAEb,aAAa,EACd,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,qBAAa,SAAU,YAAW,aAAa;IAC7C,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,OAAO,CAAmB;gBAEtB,KAAK,EAAE,QAAQ,GAAG,MAAM,EAAE,OAAO,GAAE,gBAAqB;IAQpE,OAAO,CAAC,cAAc;IAKtB;;OAEG;WACW,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IA2B9C,IAAI,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,UAAU;IAqP1C,OAAO,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAsBpE"}
@@ -86,42 +86,51 @@ export class CSVReader {
86
86
  }
87
87
  const activeDelimiter = delimiter ?? ",";
88
88
  const delimLen = activeDelimiter.length;
89
+ const isSingleCharDelim = delimLen === 1;
90
+ const delimCode = activeDelimiter.charCodeAt(0);
91
+ let fieldStart = cursor;
89
92
  while (cursor < buffer.length) {
90
- const char = buffer[cursor];
91
93
  if (inQuotes) {
92
- if (char === '"') {
94
+ const charCode = buffer.charCodeAt(cursor);
95
+ if (charCode === 34 /* " */) {
93
96
  if (cursor + 1 < buffer.length) {
94
- if (buffer[cursor + 1] === '"') {
95
- currentField += '"';
97
+ if (buffer.charCodeAt(cursor + 1) === 34) {
98
+ // Escaped double quote ("")
99
+ currentField += buffer.slice(fieldStart, cursor) + '"';
96
100
  cursor += 2;
97
101
  byteOffset += 2;
102
+ fieldStart = cursor;
98
103
  continue;
99
104
  }
100
105
  else {
106
+ // Closing quote
107
+ currentField += buffer.slice(fieldStart, cursor);
101
108
  inQuotes = false;
102
109
  cursor++;
103
110
  byteOffset++;
111
+ fieldStart = cursor;
104
112
  continue;
105
113
  }
106
114
  }
107
115
  else {
108
- // Reached end of current chunk buffer inside quotes; wait for next chunk
116
+ // Reached end of current buffer inside quotes; wait for next chunk
109
117
  break;
110
118
  }
111
119
  }
112
120
  else {
113
- currentField += char;
114
121
  cursor++;
115
122
  byteOffset++;
116
123
  continue;
117
124
  }
118
125
  }
119
126
  else {
120
- if (char === '"') {
121
- if (currentField.length === 0) {
127
+ const charCode = buffer.charCodeAt(cursor);
128
+ if (charCode === 34 /* " */) {
129
+ if (cursor === fieldStart && currentField.length === 0) {
122
130
  inQuotes = true;
123
131
  cursor++;
124
132
  byteOffset++;
133
+ fieldStart = cursor;
125
134
  continue;
126
135
  }
127
136
  else {
@@ -133,27 +142,35 @@ export class CSVReader {
133
142
  });
134
143
  }
135
144
  }
136
- // If remaining buffer is shorter than delimiter, wait for next chunk
137
- if (buffer.length - cursor < delimLen) {
138
- break;
139
- }
140
145
  // Check for delimiter
141
- if (buffer.startsWith(activeDelimiter, cursor)) {
142
- currentRowFields.push(currentField);
146
+ const isDelim = isSingleCharDelim
147
+ ? charCode === delimCode
148
+ : (buffer.length - cursor >= delimLen && buffer.startsWith(activeDelimiter, cursor));
149
+ if (isDelim) {
150
+ const fieldPart = buffer.slice(fieldStart, cursor);
151
+ const val = currentField.length > 0 ? currentField + fieldPart : fieldPart;
152
+ currentRowFields.push(val);
143
153
  currentField = "";
144
154
  cursor += delimLen;
145
155
  byteOffset += delimLen;
156
+ fieldStart = cursor;
146
157
  continue;
147
158
  }
159
+ // If remaining buffer is shorter than multi-char delimiter, wait for next chunk
160
+ if (!isSingleCharDelim && buffer.length - cursor < delimLen) {
161
+ break;
162
+ }
148
163
  // Check for CRLF / LF newline
149
- if (char === "\r" || char === "\n") {
150
- if (char === "\r" && cursor + 1 >= buffer.length) {
164
+ if (charCode === 13 /* \r */ || charCode === 10 /* \n */) {
165
+ if (charCode === 13 && cursor + 1 >= buffer.length) {
151
166
  // Wait for next chunk to check for \n
152
167
  break;
153
168
  }
154
- currentRowFields.push(currentField);
169
+ const fieldPart = buffer.slice(fieldStart, cursor);
170
+ const val = currentField.length > 0 ? currentField + fieldPart : fieldPart;
171
+ currentRowFields.push(val);
155
172
  currentField = "";
156
- if (char === "\r" && cursor + 1 < buffer.length && buffer[cursor + 1] === "\n") {
173
+ if (charCode === 13 && cursor + 1 < buffer.length && buffer.charCodeAt(cursor + 1) === 10) {
157
174
  cursor += 2;
158
175
  byteOffset += 2;
159
176
  }
@@ -161,6 +178,7 @@ export class CSVReader {
161
178
  cursor++;
162
179
  byteOffset++;
163
180
  }
181
+ fieldStart = cursor;
164
182
  // Skip entirely empty row if it's trailing whitespace
165
183
  if (currentRowFields.length === 1 &&
166
184
  currentRowFields[0]?.trim() === "" &&
@@ -196,12 +214,14 @@ export class CSVReader {
196
214
  }
197
215
  continue;
198
216
  }
199
- currentField += char;
200
217
  cursor++;
201
218
  byteOffset++;
202
219
  }
203
220
  }
204
221
  // Compact processed buffer to keep memory bounded
222
+ if (fieldStart < cursor) {
223
+ currentField += buffer.slice(fieldStart, cursor);
224
+ }
205
225
  buffer = buffer.slice(cursor);
206
226
  cursor = 0;
207
227
  }