@toiroakr/lines-db 0.9.2 → 0.10.1
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/CHANGELOG.md +20 -0
- package/bin/cli.mjs +7172 -125
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +3 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +17 -27
- package/src/cli.ts +112 -111
- package/tsdown.config.ts +9 -5
- package/dist/index.cjs +0 -1463
- package/dist/index.d.cts +0 -604
- package/dist/index.d.cts.map +0 -1
package/package.json
CHANGED
|
@@ -1,28 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toiroakr/lines-db",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "A database implementation that treats JSONL files as tables using SQLite",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "./dist/index.cjs",
|
|
7
|
-
"module": "./dist/index.mjs",
|
|
8
6
|
"types": "./dist/index.d.mts",
|
|
9
7
|
"bin": {
|
|
10
8
|
"lines-db": "./bin/cli.mjs"
|
|
11
9
|
},
|
|
12
10
|
"exports": {
|
|
13
11
|
".": {
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
"default": "./dist/index.mjs"
|
|
17
|
-
},
|
|
18
|
-
"require": {
|
|
19
|
-
"types": "./dist/index.d.cts",
|
|
20
|
-
"default": "./dist/index.cjs"
|
|
21
|
-
}
|
|
12
|
+
"types": "./dist/index.d.mts",
|
|
13
|
+
"default": "./dist/index.mjs"
|
|
22
14
|
}
|
|
23
15
|
},
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=22.12.0"
|
|
18
|
+
},
|
|
24
19
|
"scripts": {
|
|
25
20
|
"build": "tsdown",
|
|
21
|
+
"publint": "publint",
|
|
26
22
|
"typecheck": "tsc --noEmit",
|
|
27
23
|
"test": "vitest run"
|
|
28
24
|
},
|
|
@@ -36,31 +32,25 @@
|
|
|
36
32
|
"license": "MIT",
|
|
37
33
|
"repository": {
|
|
38
34
|
"type": "git",
|
|
39
|
-
"url": "https://github.com/toiroakr/lines-db.git"
|
|
35
|
+
"url": "git+https://github.com/toiroakr/lines-db.git"
|
|
40
36
|
},
|
|
41
37
|
"bugs": {
|
|
42
38
|
"url": "https://github.com/toiroakr/lines-db/issues"
|
|
43
39
|
},
|
|
44
40
|
"homepage": "https://github.com/toiroakr/lines-db#readme",
|
|
45
41
|
"devDependencies": {
|
|
46
|
-
"@types/node": "24.
|
|
47
|
-
"
|
|
48
|
-
"
|
|
42
|
+
"@types/node": "24.13.2",
|
|
43
|
+
"politty": "0.11.0",
|
|
44
|
+
"publint": "0.3.21",
|
|
45
|
+
"tsdown": "0.22.3",
|
|
46
|
+
"type-fest": "5.7.0",
|
|
49
47
|
"typescript": "6.0.3",
|
|
50
|
-
"valibot": "1.
|
|
51
|
-
"vitest": "4.1.
|
|
52
|
-
|
|
53
|
-
"peerDependencies": {
|
|
54
|
-
"valibot": ">=1.0.0"
|
|
55
|
-
},
|
|
56
|
-
"peerDependenciesMeta": {
|
|
57
|
-
"valibot": {
|
|
58
|
-
"optional": true
|
|
59
|
-
}
|
|
48
|
+
"valibot": "1.4.2",
|
|
49
|
+
"vitest": "4.1.9",
|
|
50
|
+
"zod": "4.4.3"
|
|
60
51
|
},
|
|
61
52
|
"dependencies": {
|
|
62
53
|
"@standard-schema/spec": "^1.0.0",
|
|
63
|
-
"
|
|
64
|
-
"tsx": "^4.19.2"
|
|
54
|
+
"amaro": "^1.1.10"
|
|
65
55
|
}
|
|
66
56
|
}
|
package/src/cli.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
// Register
|
|
3
|
+
// Register amaro for TypeScript schema file support
|
|
4
4
|
import { register } from 'node:module';
|
|
5
|
-
register('
|
|
5
|
+
register('amaro/transform', import.meta.url);
|
|
6
6
|
|
|
7
7
|
import { TypeGenerator } from './type-generator.js';
|
|
8
8
|
import { LinesDB } from './database.js';
|
|
9
9
|
import { ErrorFormatter } from './error-formatter.js';
|
|
10
10
|
import type { ValidationError, JsonObject } from './types.js';
|
|
11
|
-
import {
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
import { arg, defineCommand, runMain } from 'politty';
|
|
12
13
|
import { styleText } from 'node:util';
|
|
13
14
|
import { writeFile, stat, readdir } from 'node:fs/promises';
|
|
14
15
|
import { basename, dirname } from 'node:path';
|
|
@@ -45,51 +46,59 @@ function runInSandbox<T>(expression: string, context: Record<string, unknown> =
|
|
|
45
46
|
return runInNewContext(expression, sandbox, { timeout: 1000 }) as T;
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
49
|
+
const generateCommand = defineCommand({
|
|
50
|
+
name: 'generate',
|
|
51
|
+
description: 'Generate TypeScript type definitions from schema files',
|
|
52
|
+
args: z.object({
|
|
53
|
+
dataDir: arg(z.string(), {
|
|
54
|
+
positional: true,
|
|
55
|
+
description: 'Directory containing JSONL and schema files',
|
|
56
|
+
}),
|
|
57
|
+
output: arg(z.string().optional(), {
|
|
58
|
+
alias: 'o',
|
|
59
|
+
description: 'Output file path (default: db.ts in dataDir)',
|
|
60
|
+
}),
|
|
61
|
+
}),
|
|
62
|
+
run: async (args) => {
|
|
59
63
|
try {
|
|
60
|
-
const generator = new TypeGenerator({ dataDir, output:
|
|
64
|
+
const generator = new TypeGenerator({ dataDir: args.dataDir, output: args.output });
|
|
61
65
|
await generator.generate();
|
|
62
66
|
console.log('Type generation completed successfully!');
|
|
63
67
|
} catch (error) {
|
|
64
68
|
console.error('Error:', error instanceof Error ? error.message : String(error));
|
|
65
69
|
process.exit(1);
|
|
66
70
|
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
.
|
|
74
|
-
|
|
75
|
-
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const validateCommand = defineCommand({
|
|
75
|
+
name: 'validate',
|
|
76
|
+
description: 'Validate JSONL file(s) against schema',
|
|
77
|
+
args: z.object({
|
|
78
|
+
path: arg(z.string(), {
|
|
79
|
+
positional: true,
|
|
80
|
+
description: 'File or directory path to validate',
|
|
81
|
+
}),
|
|
82
|
+
verbose: arg(z.boolean().default(false), {
|
|
83
|
+
alias: 'v',
|
|
84
|
+
description: 'Show verbose error output',
|
|
85
|
+
}),
|
|
86
|
+
}),
|
|
87
|
+
run: async (args) => {
|
|
76
88
|
try {
|
|
77
|
-
|
|
78
|
-
const stats = await stat(path);
|
|
89
|
+
const stats = await stat(args.path);
|
|
79
90
|
let dataDir: string;
|
|
80
91
|
let tableName: string | undefined;
|
|
81
92
|
|
|
82
93
|
if (stats.isDirectory()) {
|
|
83
|
-
dataDir = path;
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
tableName = basename(path, '.jsonl');
|
|
94
|
+
dataDir = args.path;
|
|
95
|
+
} else if (stats.isFile() && args.path.endsWith('.jsonl')) {
|
|
96
|
+
dataDir = dirname(args.path);
|
|
97
|
+
tableName = basename(args.path, '.jsonl');
|
|
88
98
|
} else {
|
|
89
|
-
throw new Error(`Invalid path: ${path}. Must be a directory or .jsonl file.`);
|
|
99
|
+
throw new Error(`Invalid path: ${args.path}. Must be a directory or .jsonl file.`);
|
|
90
100
|
}
|
|
91
101
|
|
|
92
|
-
// Use LinesDB.initialize() with detailed validation
|
|
93
102
|
const db = LinesDB.create({ dataDir });
|
|
94
103
|
let result;
|
|
95
104
|
try {
|
|
@@ -98,21 +107,17 @@ program
|
|
|
98
107
|
await db.close();
|
|
99
108
|
}
|
|
100
109
|
|
|
101
|
-
// Directory validation: display per-table results
|
|
102
110
|
if (!tableName) {
|
|
103
|
-
const formatter = new ErrorFormatter({ verbose:
|
|
111
|
+
const formatter = new ErrorFormatter({ verbose: args.verbose });
|
|
104
112
|
|
|
105
113
|
for (const tableResult of result.tableResults) {
|
|
106
114
|
if (tableResult.valid && tableResult.warnings.length === 0) {
|
|
107
|
-
// Success
|
|
108
115
|
console.log(styleText('green', `✓ ${tableResult.tableName} (${tableResult.rowCount} records)`));
|
|
109
116
|
} else if (tableResult.valid && tableResult.warnings.length > 0) {
|
|
110
|
-
// Warnings
|
|
111
117
|
for (const warning of tableResult.warnings) {
|
|
112
118
|
console.warn(styleText('yellow', `⚠ ${warning}`));
|
|
113
119
|
}
|
|
114
120
|
} else {
|
|
115
|
-
// Errors
|
|
116
121
|
const fileErrors = tableResult.errors;
|
|
117
122
|
console.error(formatter.formatErrorHeader(fileErrors.length, fileErrors[0]?.file));
|
|
118
123
|
console.error('');
|
|
@@ -159,7 +164,6 @@ program
|
|
|
159
164
|
process.exit(1);
|
|
160
165
|
}
|
|
161
166
|
} else {
|
|
162
|
-
// Single file validation: existing behavior
|
|
163
167
|
if (result.warnings.length > 0) {
|
|
164
168
|
for (const warning of result.warnings) {
|
|
165
169
|
console.warn(styleText('yellow', `⚠ ${warning}`));
|
|
@@ -171,7 +175,7 @@ program
|
|
|
171
175
|
console.log(styleText('green', '✓ All records are valid'));
|
|
172
176
|
process.exit(0);
|
|
173
177
|
} else {
|
|
174
|
-
const formatter = new ErrorFormatter({ verbose:
|
|
178
|
+
const formatter = new ErrorFormatter({ verbose: args.verbose });
|
|
175
179
|
|
|
176
180
|
for (const [, fileErrors] of result.errors.reduce((map, error) => {
|
|
177
181
|
const errors = map.get(error.file) || [];
|
|
@@ -222,46 +226,76 @@ program
|
|
|
222
226
|
console.error('Error:', error instanceof Error ? error.message : String(error));
|
|
223
227
|
process.exit(1);
|
|
224
228
|
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
.
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
229
|
+
},
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
const migrateCommand = defineCommand({
|
|
233
|
+
name: 'migrate',
|
|
234
|
+
description: 'Migrate data with transformation function',
|
|
235
|
+
args: z.object({
|
|
236
|
+
path: arg(z.string(), {
|
|
237
|
+
positional: true,
|
|
238
|
+
description: 'File or directory path to migrate',
|
|
239
|
+
}),
|
|
240
|
+
transform: arg(z.string(), {
|
|
241
|
+
positional: true,
|
|
242
|
+
description: 'Transform function (e.g., "(row) => ({ ...row, age: row.age + 1 })")',
|
|
243
|
+
}),
|
|
244
|
+
filter: arg(z.string().optional(), {
|
|
245
|
+
alias: 'f',
|
|
246
|
+
description: 'Filter expression',
|
|
247
|
+
}),
|
|
248
|
+
errorOutput: arg(z.string().optional(), {
|
|
249
|
+
alias: 'e',
|
|
250
|
+
description: 'Output file path for transformed data when migration fails',
|
|
251
|
+
}),
|
|
252
|
+
verbose: arg(z.boolean().default(false), {
|
|
253
|
+
alias: 'v',
|
|
254
|
+
description: 'Show verbose error output',
|
|
255
|
+
}),
|
|
256
|
+
}),
|
|
257
|
+
run: async (args) => {
|
|
258
|
+
try {
|
|
259
|
+
const stats = await stat(args.path);
|
|
260
|
+
|
|
261
|
+
if (stats.isDirectory()) {
|
|
262
|
+
await migrateDirectory(args.path, args.transform, {
|
|
263
|
+
filter: args.filter,
|
|
264
|
+
errorOutput: args.errorOutput,
|
|
265
|
+
verbose: args.verbose,
|
|
266
|
+
});
|
|
267
|
+
} else if (stats.isFile() && args.path.endsWith('.jsonl')) {
|
|
268
|
+
await migrateFile(args.path, args.transform, {
|
|
269
|
+
filter: args.filter,
|
|
270
|
+
errorOutput: args.errorOutput,
|
|
271
|
+
verbose: args.verbose,
|
|
272
|
+
});
|
|
273
|
+
} else {
|
|
274
|
+
console.error(`Error: Invalid path: ${args.path}. Must be a directory or .jsonl file.`);
|
|
261
275
|
process.exit(1);
|
|
262
276
|
}
|
|
263
|
-
}
|
|
264
|
-
|
|
277
|
+
} catch (error) {
|
|
278
|
+
if (error instanceof Error && 'code' in error && (error as NodeJS.ErrnoException).code === 'ENOENT') {
|
|
279
|
+
console.error(`Error: Path not found: ${args.path}`);
|
|
280
|
+
} else {
|
|
281
|
+
console.error(`Error: ${String(error)}`);
|
|
282
|
+
}
|
|
283
|
+
process.exit(1);
|
|
284
|
+
}
|
|
285
|
+
},
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
const program = defineCommand({
|
|
289
|
+
name: '@toiroakr/lines-db',
|
|
290
|
+
description: 'Database utilities for JSONL files',
|
|
291
|
+
subCommands: {
|
|
292
|
+
generate: generateCommand,
|
|
293
|
+
validate: validateCommand,
|
|
294
|
+
migrate: migrateCommand,
|
|
295
|
+
},
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
runMain(program, { version: '1.0.0' });
|
|
265
299
|
|
|
266
300
|
/**
|
|
267
301
|
* Migrate all JSONL files in a directory
|
|
@@ -271,7 +305,6 @@ async function migrateDirectory(
|
|
|
271
305
|
transformStr: string,
|
|
272
306
|
options: { filter?: string; errorOutput?: string; verbose: boolean },
|
|
273
307
|
) {
|
|
274
|
-
// Find all JSONL files in directory
|
|
275
308
|
const entries = await readdir(dirPath, { withFileTypes: true });
|
|
276
309
|
const jsonlFiles = entries
|
|
277
310
|
.filter((entry) => entry.isFile() && entry.name.endsWith('.jsonl'))
|
|
@@ -284,18 +317,15 @@ async function migrateDirectory(
|
|
|
284
317
|
|
|
285
318
|
console.log(`Found ${jsonlFiles.length} JSONL file(s) in directory`);
|
|
286
319
|
|
|
287
|
-
// Initialize database
|
|
288
320
|
const db = LinesDB.create({ dataDir: dirPath });
|
|
289
321
|
const initResult = await db.initialize({ detailedValidate: true });
|
|
290
322
|
|
|
291
|
-
// Display warnings if any
|
|
292
323
|
if (initResult.warnings.length > 0) {
|
|
293
324
|
for (const warning of initResult.warnings) {
|
|
294
325
|
console.warn(styleText('yellow', `⚠ ${warning}`));
|
|
295
326
|
}
|
|
296
327
|
}
|
|
297
328
|
|
|
298
|
-
// Check for initialization errors
|
|
299
329
|
if (!initResult.valid) {
|
|
300
330
|
console.error(`Error: Failed to initialize database due to validation errors:`);
|
|
301
331
|
const formatter = new ErrorFormatter({ verbose: options.verbose });
|
|
@@ -324,7 +354,6 @@ async function migrateDirectory(
|
|
|
324
354
|
console.log(`Loaded ${tableNames.length} table(s): ${tableNames.join(', ')}\n`);
|
|
325
355
|
|
|
326
356
|
try {
|
|
327
|
-
// Parse transform function
|
|
328
357
|
const transform = runInSandbox<unknown>(`(${transformStr})`);
|
|
329
358
|
|
|
330
359
|
if (typeof transform !== 'function') {
|
|
@@ -333,7 +362,6 @@ async function migrateDirectory(
|
|
|
333
362
|
process.exit(1);
|
|
334
363
|
}
|
|
335
364
|
|
|
336
|
-
// Parse filter if provided
|
|
337
365
|
let filter: unknown = undefined;
|
|
338
366
|
if (options.filter) {
|
|
339
367
|
try {
|
|
@@ -346,12 +374,10 @@ async function migrateDirectory(
|
|
|
346
374
|
let totalRowsMigrated = 0;
|
|
347
375
|
let hasErrors = false;
|
|
348
376
|
|
|
349
|
-
// Process each table
|
|
350
377
|
for (const tableName of tableNames) {
|
|
351
378
|
try {
|
|
352
379
|
console.log(`Processing table '${tableName}'...`);
|
|
353
380
|
|
|
354
|
-
// Get rows to migrate
|
|
355
381
|
const rowsToMigrate = filter ? db.find(tableName, filter as Parameters<typeof db.find>[1]) : db.find(tableName);
|
|
356
382
|
|
|
357
383
|
if (rowsToMigrate.length === 0) {
|
|
@@ -361,10 +387,8 @@ async function migrateDirectory(
|
|
|
361
387
|
|
|
362
388
|
console.log(` Found ${rowsToMigrate.length} row(s) to migrate`);
|
|
363
389
|
|
|
364
|
-
// Apply transformation
|
|
365
390
|
const transformedRows = rowsToMigrate.map((row) => transform(row as JsonObject));
|
|
366
391
|
|
|
367
|
-
// Perform the migration in a transaction
|
|
368
392
|
await db.transaction(async () => {
|
|
369
393
|
db.batchUpdate(tableName, transformedRows as Parameters<typeof db.batchUpdate>[1], {
|
|
370
394
|
validate: true,
|
|
@@ -440,7 +464,6 @@ async function migrateFile(
|
|
|
440
464
|
transformStr: string,
|
|
441
465
|
options: { filter?: string; errorOutput?: string; verbose: boolean },
|
|
442
466
|
) {
|
|
443
|
-
// Extract table name from file path
|
|
444
467
|
const fileName = filePath.split('/').pop() || '';
|
|
445
468
|
const tableName = fileName.replace('.jsonl', '');
|
|
446
469
|
|
|
@@ -449,11 +472,9 @@ async function migrateFile(
|
|
|
449
472
|
process.exit(1);
|
|
450
473
|
}
|
|
451
474
|
|
|
452
|
-
// Get directory from file path
|
|
453
475
|
const lastSlashIndex = filePath.lastIndexOf('/');
|
|
454
476
|
const dataDir = lastSlashIndex > 0 ? filePath.substring(0, lastSlashIndex) : '.';
|
|
455
477
|
|
|
456
|
-
// Parse transform function first (before initialization)
|
|
457
478
|
let transform: (row: JsonObject) => JsonObject;
|
|
458
479
|
try {
|
|
459
480
|
const parsedTransform = runInSandbox<unknown>(`(${transformStr})`);
|
|
@@ -468,18 +489,15 @@ async function migrateFile(
|
|
|
468
489
|
process.exit(1);
|
|
469
490
|
}
|
|
470
491
|
|
|
471
|
-
// Initialize database with transform applied
|
|
472
492
|
const db = LinesDB.create({ dataDir });
|
|
473
493
|
const initResult = await db.initialize({ tableName, transform, detailedValidate: true });
|
|
474
494
|
|
|
475
|
-
// Display warnings if any
|
|
476
495
|
if (initResult.warnings.length > 0) {
|
|
477
496
|
for (const warning of initResult.warnings) {
|
|
478
497
|
console.warn(styleText('yellow', `⚠ ${warning}`));
|
|
479
498
|
}
|
|
480
499
|
}
|
|
481
500
|
|
|
482
|
-
// Check for initialization errors
|
|
483
501
|
if (!initResult.valid) {
|
|
484
502
|
console.error(`Error: Failed to initialize database due to validation errors:`);
|
|
485
503
|
const formatter = new ErrorFormatter({ verbose: options.verbose });
|
|
@@ -499,21 +517,16 @@ async function migrateFile(
|
|
|
499
517
|
}
|
|
500
518
|
|
|
501
519
|
try {
|
|
502
|
-
// Parse filter if provided
|
|
503
520
|
let filter: unknown = undefined;
|
|
504
521
|
if (options.filter) {
|
|
505
522
|
try {
|
|
506
|
-
// Try JSON parse first
|
|
507
523
|
filter = JSON.parse(options.filter);
|
|
508
524
|
} catch {
|
|
509
|
-
// Fall back to eval for JavaScript expressions
|
|
510
525
|
filter = runInSandbox(`(${options.filter})`);
|
|
511
526
|
}
|
|
512
527
|
}
|
|
513
528
|
|
|
514
|
-
// If filter is provided, we need to apply transform only to matching rows
|
|
515
529
|
if (filter) {
|
|
516
|
-
// Get rows to migrate
|
|
517
530
|
let rowsToMigrate;
|
|
518
531
|
try {
|
|
519
532
|
rowsToMigrate = db.find(tableName, filter as Parameters<typeof db.find>[1]);
|
|
@@ -534,10 +547,8 @@ async function migrateFile(
|
|
|
534
547
|
process.exit(0);
|
|
535
548
|
}
|
|
536
549
|
|
|
537
|
-
// Apply transformation
|
|
538
550
|
const transformedRows = rowsToMigrate.map((row) => transform(row as JsonObject));
|
|
539
551
|
|
|
540
|
-
// Perform the migration in a transaction
|
|
541
552
|
try {
|
|
542
553
|
await db.transaction(async () => {
|
|
543
554
|
db.batchUpdate(tableName, transformedRows as Parameters<typeof db.batchUpdate>[1], {
|
|
@@ -553,7 +564,6 @@ async function migrateFile(
|
|
|
553
564
|
} catch (error) {
|
|
554
565
|
await db.close();
|
|
555
566
|
|
|
556
|
-
// Write transformed data to error output file if --errorOutput is specified
|
|
557
567
|
if (options.errorOutput) {
|
|
558
568
|
try {
|
|
559
569
|
const jsonlContent = transformedRows.map((row) => JSON.stringify(row)).join('\n');
|
|
@@ -577,7 +587,6 @@ async function migrateFile(
|
|
|
577
587
|
const formatter = new ErrorFormatter({ verbose: options.verbose });
|
|
578
588
|
console.error(formatter.formatMigrationFailureHeader());
|
|
579
589
|
|
|
580
|
-
// Display detailed error information
|
|
581
590
|
if (error instanceof Error && error.name === 'ValidationError') {
|
|
582
591
|
const validationError = error as ValidationError & {
|
|
583
592
|
validationErrors?: Array<{
|
|
@@ -588,7 +597,6 @@ async function migrateFile(
|
|
|
588
597
|
}>;
|
|
589
598
|
};
|
|
590
599
|
|
|
591
|
-
// Display all validation errors
|
|
592
600
|
if (validationError.validationErrors) {
|
|
593
601
|
console.error(
|
|
594
602
|
`\nFound ${validationError.validationErrors.length} validation error(s) in transformed data:\n`,
|
|
@@ -605,7 +613,6 @@ async function migrateFile(
|
|
|
605
613
|
const formatted = formatter.formatValidationErrors(errorInfos);
|
|
606
614
|
console.error(formatted);
|
|
607
615
|
} else {
|
|
608
|
-
// Fallback for single validation error (backward compatibility)
|
|
609
616
|
console.error('\nValidation error:\n');
|
|
610
617
|
const errorInfo = {
|
|
611
618
|
file: filePath,
|
|
@@ -618,12 +625,10 @@ async function migrateFile(
|
|
|
618
625
|
} else if (error instanceof Error) {
|
|
619
626
|
console.error(`\n ${error.message}`);
|
|
620
627
|
|
|
621
|
-
// Output stack trace for debugging
|
|
622
628
|
if (options.verbose && error.stack) {
|
|
623
629
|
console.error(`\nStack trace:\n${error.stack}`);
|
|
624
630
|
}
|
|
625
631
|
|
|
626
|
-
// Check if it's a SQLite constraint error
|
|
627
632
|
if (
|
|
628
633
|
error.message.includes('UNIQUE constraint failed') ||
|
|
629
634
|
error.message.includes('FOREIGN KEY constraint failed') ||
|
|
@@ -641,8 +646,6 @@ async function migrateFile(
|
|
|
641
646
|
process.exit(1);
|
|
642
647
|
}
|
|
643
648
|
} else {
|
|
644
|
-
// No filter - all rows have been transformed during initialization
|
|
645
|
-
// Just sync to write back to JSONL file
|
|
646
649
|
try {
|
|
647
650
|
const allRows = db.find(tableName);
|
|
648
651
|
console.log(`Migrated ${allRows.length} row(s) in table '${tableName}'`);
|
|
@@ -665,5 +668,3 @@ async function migrateFile(
|
|
|
665
668
|
throw error;
|
|
666
669
|
}
|
|
667
670
|
}
|
|
668
|
-
|
|
669
|
-
program.parse();
|
package/tsdown.config.ts
CHANGED
|
@@ -1,24 +1,28 @@
|
|
|
1
1
|
import { defineConfig } from 'tsdown';
|
|
2
2
|
|
|
3
3
|
export default defineConfig([
|
|
4
|
-
// CLI build (ESM only)
|
|
4
|
+
// CLI build (ESM only, fully bundled)
|
|
5
5
|
{
|
|
6
6
|
entry: ['src/cli.ts'],
|
|
7
7
|
format: ['esm'],
|
|
8
8
|
platform: 'node',
|
|
9
|
-
target: '
|
|
9
|
+
target: 'node22',
|
|
10
10
|
clean: true,
|
|
11
11
|
shims: true,
|
|
12
12
|
outDir: 'bin',
|
|
13
13
|
dts: false,
|
|
14
14
|
treeshake: true,
|
|
15
|
+
deps: {
|
|
16
|
+
alwaysBundle: ['zod', 'politty'],
|
|
17
|
+
onlyBundle: false,
|
|
18
|
+
},
|
|
15
19
|
},
|
|
16
|
-
// Library build (ESM
|
|
20
|
+
// Library build (ESM only)
|
|
17
21
|
{
|
|
18
22
|
entry: ['src/index.ts'],
|
|
19
|
-
format: ['esm'
|
|
23
|
+
format: ['esm'],
|
|
20
24
|
platform: 'node',
|
|
21
|
-
target: '
|
|
25
|
+
target: 'node22',
|
|
22
26
|
outDir: 'dist',
|
|
23
27
|
dts: true,
|
|
24
28
|
treeshake: true,
|