rowpipe 1.0.0 → 1.1.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 (106) hide show
  1. package/README.md +25 -32
  2. package/dist/cli/index.js +4 -4
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/core/types.d.ts +2 -0
  5. package/dist/core/types.d.ts.map +1 -1
  6. package/dist/index.d.ts +2 -2
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +2 -2
  9. package/dist/index.js.map +1 -1
  10. package/dist/readers/csv.d.ts.map +1 -1
  11. package/dist/readers/csv.js +28 -16
  12. package/dist/readers/csv.js.map +1 -1
  13. package/dist/readers/index.d.ts +1 -0
  14. package/dist/readers/index.d.ts.map +1 -1
  15. package/dist/readers/index.js +29 -3
  16. package/dist/readers/index.js.map +1 -1
  17. package/dist/readers/json.d.ts.map +1 -1
  18. package/dist/readers/json.js +6 -8
  19. package/dist/readers/json.js.map +1 -1
  20. package/dist/readers/jsonl.d.ts.map +1 -1
  21. package/dist/readers/jsonl.js +5 -7
  22. package/dist/readers/jsonl.js.map +1 -1
  23. package/dist/readers/parquet.d.ts +17 -0
  24. package/dist/readers/parquet.d.ts.map +1 -0
  25. package/dist/readers/parquet.js +146 -0
  26. package/dist/readers/parquet.js.map +1 -0
  27. package/dist/utils/compression.d.ts +30 -6
  28. package/dist/utils/compression.d.ts.map +1 -1
  29. package/dist/utils/compression.js +95 -18
  30. package/dist/utils/compression.js.map +1 -1
  31. package/dist/writers/csv.d.ts.map +1 -1
  32. package/dist/writers/csv.js +9 -11
  33. package/dist/writers/csv.js.map +1 -1
  34. package/dist/writers/index.d.ts +2 -0
  35. package/dist/writers/index.d.ts.map +1 -1
  36. package/dist/writers/index.js +49 -4
  37. package/dist/writers/index.js.map +1 -1
  38. package/dist/writers/json.d.ts +1 -1
  39. package/dist/writers/json.d.ts.map +1 -1
  40. package/dist/writers/json.js +9 -11
  41. package/dist/writers/json.js.map +1 -1
  42. package/dist/writers/jsonl.d.ts +1 -1
  43. package/dist/writers/jsonl.d.ts.map +1 -1
  44. package/dist/writers/jsonl.js +9 -11
  45. package/dist/writers/jsonl.js.map +1 -1
  46. package/dist/writers/markdown.d.ts +21 -0
  47. package/dist/writers/markdown.d.ts.map +1 -0
  48. package/dist/writers/markdown.js +82 -0
  49. package/dist/writers/markdown.js.map +1 -0
  50. package/dist/writers/parquet.d.ts +19 -0
  51. package/dist/writers/parquet.d.ts.map +1 -0
  52. package/dist/writers/parquet.js +129 -0
  53. package/dist/writers/parquet.js.map +1 -0
  54. package/package.json +13 -2
  55. package/skills/rowpipe/SKILL.md +181 -0
  56. package/benchmarks/memory-bench.ts +0 -109
  57. package/src/analytics/reduce.ts +0 -388
  58. package/src/analytics/schema-inference.ts +0 -217
  59. package/src/analytics/semantic-types.ts +0 -36
  60. package/src/analytics/stats.ts +0 -383
  61. package/src/analytics/validator.ts +0 -134
  62. package/src/cli/commands/cast.ts +0 -60
  63. package/src/cli/commands/convert.ts +0 -128
  64. package/src/cli/commands/filter.ts +0 -58
  65. package/src/cli/commands/inspect.ts +0 -193
  66. package/src/cli/commands/map.ts +0 -66
  67. package/src/cli/commands/reduce.ts +0 -74
  68. package/src/cli/commands/rename.ts +0 -59
  69. package/src/cli/commands/sample.ts +0 -61
  70. package/src/cli/commands/schema.ts +0 -86
  71. package/src/cli/commands/select.ts +0 -59
  72. package/src/cli/commands/stats.ts +0 -100
  73. package/src/cli/commands/validate.ts +0 -123
  74. package/src/cli/index.ts +0 -285
  75. package/src/core/batch.ts +0 -81
  76. package/src/core/errors.ts +0 -81
  77. package/src/core/pipeline.ts +0 -150
  78. package/src/core/types.ts +0 -110
  79. package/src/index.ts +0 -52
  80. package/src/readers/csv.ts +0 -302
  81. package/src/readers/index.ts +0 -88
  82. package/src/readers/json.ts +0 -256
  83. package/src/readers/jsonl.ts +0 -126
  84. package/src/readers/xlsx.ts +0 -182
  85. package/src/transforms/cast.ts +0 -212
  86. package/src/transforms/expression.ts +0 -1114
  87. package/src/transforms/filter.ts +0 -38
  88. package/src/transforms/map.ts +0 -99
  89. package/src/transforms/rename.ts +0 -47
  90. package/src/transforms/sample.ts +0 -57
  91. package/src/transforms/select.ts +0 -64
  92. package/src/utils/compression.ts +0 -43
  93. package/src/utils/formatting.ts +0 -75
  94. package/src/utils/progress.ts +0 -37
  95. package/src/writers/csv.ts +0 -106
  96. package/src/writers/index.ts +0 -87
  97. package/src/writers/json.ts +0 -52
  98. package/src/writers/jsonl.ts +0 -49
  99. package/src/writers/xlsx.ts +0 -87
  100. package/tests/analytics.test.ts +0 -119
  101. package/tests/cli-integration.test.ts +0 -187
  102. package/tests/map-reduce.test.ts +0 -223
  103. package/tests/readers-writers.test.ts +0 -189
  104. package/tests/transforms.test.ts +0 -199
  105. package/tsconfig.json +0 -21
  106. package/vitest.config.ts +0 -9
package/src/core/batch.ts DELETED
@@ -1,81 +0,0 @@
1
- import type { DataBatch, DataStream, Row } from "./types.js";
2
-
3
- /**
4
- * Packs an AsyncIterable of individual rows into DataBatch chunks with a given batchSize.
5
- */
6
- export async function* rowsToBatches(
7
- rows: AsyncIterable<Row>,
8
- batchSize = 1000
9
- ): AsyncGenerator<DataBatch> {
10
- const effectiveBatchSize = Math.max(1, batchSize);
11
- let currentRows: Row[] = [];
12
- let totalOffset = 0;
13
-
14
- for await (const row of rows) {
15
- currentRows.push(row);
16
- if (currentRows.length >= effectiveBatchSize) {
17
- yield {
18
- rows: currentRows,
19
- offset: totalOffset,
20
- };
21
- totalOffset += currentRows.length;
22
- currentRows = [];
23
- }
24
- }
25
-
26
- if (currentRows.length > 0) {
27
- yield {
28
- rows: currentRows,
29
- offset: totalOffset,
30
- };
31
- }
32
- }
33
-
34
- /**
35
- * Unpacks DataBatches into individual rows.
36
- */
37
- export async function* batchesToRows(stream: DataStream): AsyncGenerator<Row> {
38
- for await (const batch of stream) {
39
- for (const row of batch.rows) {
40
- yield row;
41
- }
42
- }
43
- }
44
-
45
- /**
46
- * Applies a mapping function to each row in batches, maintaining batch structure
47
- * and filtering out null/undefined results.
48
- */
49
- export async function* batchMap(
50
- stream: DataStream,
51
- fn: (row: Row, globalIndex: number) => Row | null | undefined,
52
- targetBatchSize = 1000
53
- ): AsyncGenerator<DataBatch> {
54
- let pendingRows: Row[] = [];
55
- let currentOffset = 0;
56
- let globalIndex = 0;
57
-
58
- for await (const batch of stream) {
59
- for (const row of batch.rows) {
60
- const transformed = fn(row, globalIndex++);
61
- if (transformed !== null && transformed !== undefined) {
62
- pendingRows.push(transformed);
63
- if (pendingRows.length >= targetBatchSize) {
64
- yield {
65
- rows: pendingRows,
66
- offset: currentOffset,
67
- };
68
- currentOffset += pendingRows.length;
69
- pendingRows = [];
70
- }
71
- }
72
- }
73
- }
74
-
75
- if (pendingRows.length > 0) {
76
- yield {
77
- rows: pendingRows,
78
- offset: currentOffset,
79
- };
80
- }
81
- }
@@ -1,81 +0,0 @@
1
- export class RowpipeError extends Error {
2
- public readonly exitCode: number;
3
-
4
- constructor(message: string, exitCode = 1) {
5
- super(message);
6
- this.name = "RowpipeError";
7
- this.exitCode = exitCode;
8
- Object.setPrototypeOf(this, new.target.prototype);
9
- }
10
- }
11
-
12
- export class InvalidArgumentError extends RowpipeError {
13
- constructor(message: string) {
14
- super(message, 2);
15
- this.name = "InvalidArgumentError";
16
- }
17
- }
18
-
19
- export interface ParseErrorContext {
20
- file?: string;
21
- sheet?: string;
22
- row?: number;
23
- column?: string | number;
24
- byteOffset?: number;
25
- line?: number;
26
- cell?: string;
27
- }
28
-
29
- export class ParseError extends RowpipeError {
30
- public readonly context: ParseErrorContext;
31
-
32
- constructor(message: string, context: ParseErrorContext = {}) {
33
- let detailedMsg = `Parse error: ${message}`;
34
- const parts: string[] = [];
35
-
36
- if (context.file) parts.push(`File: ${context.file}`);
37
- if (context.sheet) parts.push(`Sheet: ${context.sheet}`);
38
- if (context.row !== undefined) parts.push(`Row: ${context.row}`);
39
- if (context.column !== undefined) parts.push(`Column: ${context.column}`);
40
- if (context.cell) parts.push(`Cell: ${context.cell}`);
41
- if (context.byteOffset !== undefined) parts.push(`Byte offset: ${context.byteOffset}`);
42
-
43
- if (parts.length > 0) {
44
- detailedMsg += `\n Context: ${parts.join(", ")}`;
45
- }
46
-
47
- super(detailedMsg, 3);
48
- this.name = "ParseError";
49
- this.context = context;
50
- }
51
- }
52
-
53
- export interface ValidationViolation {
54
- column: string;
55
- expected: string;
56
- actual?: string;
57
- count: number;
58
- examples?: unknown[];
59
- }
60
-
61
- export class ValidationError extends RowpipeError {
62
- public readonly violations: ValidationViolation[];
63
- public readonly totalRows: number;
64
- public readonly validRows: number;
65
- public readonly invalidRows: number;
66
-
67
- constructor(
68
- message: string,
69
- violations: ValidationViolation[] = [],
70
- totalRows = 0,
71
- validRows = 0,
72
- invalidRows = 0
73
- ) {
74
- super(message, 4);
75
- this.name = "ValidationError";
76
- this.violations = violations;
77
- this.totalRows = totalRows;
78
- this.validRows = validRows;
79
- this.invalidRows = invalidRows;
80
- }
81
- }
@@ -1,150 +0,0 @@
1
- import type {
2
- Aggregator,
3
- DataBatch,
4
- DataStream,
5
- ProgressCallback,
6
- ReaderOptions,
7
- Row,
8
- TabularReader,
9
- TabularWriter,
10
- TransformFunction,
11
- WriterOptions,
12
- } from "./types.js";
13
- import { batchesToRows } from "./batch.js";
14
-
15
- export class Pipeline {
16
- private stream: DataStream;
17
- private progressCallbacks: ProgressCallback[] = [];
18
-
19
- constructor(source: DataStream | TabularReader, options?: ReaderOptions) {
20
- if ("read" in source && typeof source.read === "function") {
21
- this.stream = source.read(options);
22
- } else {
23
- this.stream = source as DataStream;
24
- }
25
- }
26
-
27
- /**
28
- * Chains a transform function to the pipeline.
29
- */
30
- pipe(transform: TransformFunction): this {
31
- this.stream = transform(this.stream);
32
- return this;
33
- }
34
-
35
- /**
36
- * Adds a progress listener.
37
- */
38
- onProgress(callback: ProgressCallback): this {
39
- this.progressCallbacks.push(callback);
40
- return this;
41
- }
42
-
43
- /**
44
- * Wraps the current stream with a progress tracking generator if callbacks are registered.
45
- */
46
- private getTrackedStream(): DataStream {
47
- if (this.progressCallbacks.length === 0) {
48
- return this.stream;
49
- }
50
-
51
- const callbacks = this.progressCallbacks;
52
- const stream = this.stream;
53
-
54
- return (async function* () {
55
- let rowsProcessed = 0;
56
- const startTime = Date.now();
57
- let lastReport = startTime;
58
-
59
- for await (const batch of stream) {
60
- rowsProcessed += batch.rows.length;
61
- const now = Date.now();
62
-
63
- // Throttle progress notifications to ~100ms intervals
64
- if (now - lastReport >= 100) {
65
- const elapsedSec = (now - startTime) / 1000 || 0.001;
66
- const info = {
67
- rowsProcessed,
68
- elapsedMs: now - startTime,
69
- rowsPerSecond: Math.round(rowsProcessed / elapsedSec),
70
- };
71
- for (const cb of callbacks) {
72
- cb(info);
73
- }
74
- lastReport = now;
75
- }
76
-
77
- yield batch;
78
- }
79
-
80
- // Final progress callback
81
- const finalNow = Date.now();
82
- const finalElapsedSec = (finalNow - startTime) / 1000 || 0.001;
83
- const finalInfo = {
84
- rowsProcessed,
85
- elapsedMs: finalNow - startTime,
86
- rowsPerSecond: Math.round(rowsProcessed / finalElapsedSec),
87
- };
88
- for (const cb of callbacks) {
89
- cb(finalInfo);
90
- }
91
- })();
92
- }
93
-
94
- /**
95
- * Pipes the stream into a TabularWriter.
96
- */
97
- async to(writer: TabularWriter, options?: WriterOptions): Promise<void> {
98
- const tracked = this.getTrackedStream();
99
- await writer.write(tracked, options);
100
- if (writer.close) {
101
- await writer.close();
102
- }
103
- }
104
-
105
- /**
106
- * Consumes the stream using an Aggregator.
107
- */
108
- async reduce<T>(aggregator: Aggregator<T>): Promise<T> {
109
- const tracked = this.getTrackedStream();
110
- for await (const row of batchesToRows(tracked)) {
111
- aggregator.add(row);
112
- }
113
- return aggregator.result();
114
- }
115
-
116
- /**
117
- * Returns an AsyncIterable of DataBatches.
118
- */
119
- batches(): DataStream {
120
- return this.getTrackedStream();
121
- }
122
-
123
- /**
124
- * Returns an AsyncIterable of individual rows.
125
- */
126
- rows(): AsyncIterable<Row> {
127
- return batchesToRows(this.getTrackedStream());
128
- }
129
-
130
- /**
131
- * Collects all rows up to a maximum limit (default 10,000 to prevent unbounded memory).
132
- */
133
- async toArray(maxRows = 10000): Promise<Row[]> {
134
- const results: Row[] = [];
135
- for await (const row of this.rows()) {
136
- results.push(row);
137
- if (results.length >= maxRows) {
138
- break;
139
- }
140
- }
141
- return results;
142
- }
143
- }
144
-
145
- export function createPipeline(
146
- source: DataStream | TabularReader,
147
- options?: ReaderOptions
148
- ): Pipeline {
149
- return new Pipeline(source, options);
150
- }
package/src/core/types.ts DELETED
@@ -1,110 +0,0 @@
1
- import type { Readable, Writable } from "node:stream";
2
-
3
- export type Row = Record<string, unknown>;
4
-
5
- export interface DataBatch {
6
- rows: Row[];
7
- offset: number;
8
- }
9
-
10
- export type DataStream = AsyncIterable<DataBatch>;
11
-
12
- export type ColumnType =
13
- | "string"
14
- | "integer"
15
- | "number"
16
- | "boolean"
17
- | "date"
18
- | "datetime"
19
- | "null"
20
- | "mixed";
21
-
22
- export type SemanticType =
23
- | "email"
24
- | "url"
25
- | "uuid"
26
- | "ipv4"
27
- | "ipv6"
28
- | "country-code"
29
- | "currency"
30
- | "phone";
31
-
32
- export interface ReaderOptions {
33
- batchSize?: number;
34
- header?: boolean;
35
- delimiter?: string;
36
- path?: string;
37
- sheet?: string | number;
38
- maxRows?: number;
39
- filePath?: string;
40
- }
41
-
42
- export interface WriterOptions {
43
- delimiter?: string;
44
- header?: boolean;
45
- sheet?: string;
46
- }
47
-
48
- export interface SheetMetadata {
49
- name: string;
50
- rowCount: number;
51
- columnCount?: number;
52
- columns?: string[];
53
- }
54
-
55
- export interface InspectionMetadata {
56
- format: string;
57
- sizeBytes?: number;
58
- rowCount?: number;
59
- columnCount?: number;
60
- columns?: Array<{
61
- name: string;
62
- type: ColumnType;
63
- nullPercentage: number;
64
- approxUniquePercentage?: number;
65
- }>;
66
- sheetsCount?: number;
67
- sheets?: SheetMetadata[];
68
- }
69
-
70
- export interface TabularReader {
71
- read(options?: ReaderOptions): DataStream;
72
- inspect?(options?: ReaderOptions): Promise<InspectionMetadata>;
73
- close?(): Promise<void>;
74
- }
75
-
76
- export interface TabularWriter {
77
- write(stream: DataStream, options?: WriterOptions): Promise<void>;
78
- close?(): Promise<void>;
79
- }
80
-
81
- export interface FormatAdapter {
82
- name: string;
83
- extensions: string[];
84
- createReader(
85
- input: Readable | string,
86
- options?: ReaderOptions
87
- ): TabularReader;
88
- createWriter(
89
- output: Writable | string,
90
- options?: WriterOptions
91
- ): TabularWriter;
92
- }
93
-
94
- export type TransformFunction = (stream: DataStream) => DataStream;
95
-
96
- export interface Aggregator<T> {
97
- add(row: Row): void;
98
- merge?(other: Aggregator<T>): void;
99
- result(): T;
100
- }
101
-
102
- export interface ProgressCallbackInfo {
103
- rowsProcessed: number;
104
- bytesRead?: number;
105
- elapsedMs: number;
106
- rowsPerSecond: number;
107
- megabytesPerSecond?: number;
108
- }
109
-
110
- export type ProgressCallback = (info: ProgressCallbackInfo) => void;
package/src/index.ts DELETED
@@ -1,52 +0,0 @@
1
- // Core
2
- export * from "./core/types.js";
3
- export * from "./core/errors.js";
4
- export * from "./core/batch.js";
5
- export * from "./core/pipeline.js";
6
-
7
- // Readers
8
- export {
9
- CSVReader,
10
- type CSVReaderOptions,
11
- JSONReader,
12
- type JSONReaderOptions,
13
- JSONLReader,
14
- type JSONLReaderOptions,
15
- XLSXReader,
16
- type XLSXReaderOptions,
17
- createReader,
18
- inferFormatFromPath as inferReaderFormatFromPath,
19
- } from "./readers/index.js";
20
-
21
- // Writers
22
- export {
23
- CSVWriter,
24
- type CSVWriterOptions,
25
- JSONWriter,
26
- JSONLWriter,
27
- XLSXWriter,
28
- type XLSXWriterOptions,
29
- createWriter,
30
- inferFormatFromPath as inferWriterFormatFromPath,
31
- } from "./writers/index.js";
32
-
33
- // Transforms
34
- export * from "./transforms/select.js";
35
- export * from "./transforms/rename.js";
36
- export * from "./transforms/cast.js";
37
- export * from "./transforms/sample.js";
38
- export * from "./transforms/filter.js";
39
- export * from "./transforms/expression.js";
40
- export * from "./transforms/map.js";
41
-
42
- // Analytics
43
- export * from "./analytics/stats.js";
44
- export * from "./analytics/reduce.js";
45
- export * from "./analytics/schema-inference.js";
46
- export * from "./analytics/semantic-types.js";
47
- export * from "./analytics/validator.js";
48
-
49
- // Utilities
50
- export * from "./utils/compression.js";
51
- export * from "./utils/formatting.js";
52
- export * from "./utils/progress.js";