@toiroakr/lines-db 0.3.0 → 0.4.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/CHANGELOG.md +8 -0
- package/bin/cli.js +144 -134
- package/dist/index.cjs +66 -56
- package/dist/index.d.cts +11 -10
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +11 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +66 -56
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/database.ts +32 -15
- package/src/schema.ts +6 -6
- package/src/types.ts +2 -2
- package/src/validator.ts +70 -72
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @toiroakr/lines-db
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- a662484: - Allow flexible schema export methods (support loading from `schema` or `default` exports)
|
|
8
|
+
- Enhance constraint validation by loading data into an actual database (catches unique, primary key, and foreign key violations)
|
|
9
|
+
- Add fallback logic to automatically use `id` column as primary key when it exists and no primary key is explicitly defined
|
|
10
|
+
|
|
3
11
|
## 0.3.0
|
|
4
12
|
|
|
5
13
|
### Minor Changes
|
package/bin/cli.js
CHANGED
|
@@ -248,133 +248,6 @@ var SchemaLoader = class {
|
|
|
248
248
|
}
|
|
249
249
|
};
|
|
250
250
|
|
|
251
|
-
//#endregion
|
|
252
|
-
//#region src/validator.ts
|
|
253
|
-
var Validator = class {
|
|
254
|
-
path;
|
|
255
|
-
projectRoot;
|
|
256
|
-
constructor(options) {
|
|
257
|
-
this.path = options.path;
|
|
258
|
-
this.projectRoot = options.projectRoot || process.cwd();
|
|
259
|
-
}
|
|
260
|
-
/**
|
|
261
|
-
* Validate JSONL file(s)
|
|
262
|
-
*/
|
|
263
|
-
async validate() {
|
|
264
|
-
const fullPath = this.path.startsWith("/") ? this.path : join(this.projectRoot, this.path);
|
|
265
|
-
const stats = await stat(fullPath);
|
|
266
|
-
if (stats.isDirectory()) return this.validateDirectory(fullPath);
|
|
267
|
-
else if (stats.isFile() && fullPath.endsWith(".jsonl")) return this.validateFile(fullPath);
|
|
268
|
-
else throw new Error(`Invalid path: ${this.path}. Must be a directory or .jsonl file.`);
|
|
269
|
-
}
|
|
270
|
-
/**
|
|
271
|
-
* Validate all JSONL files in a directory
|
|
272
|
-
*/
|
|
273
|
-
async validateDirectory(dirPath) {
|
|
274
|
-
const jsonlFiles = (await readdir(dirPath, { withFileTypes: true })).filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl")).map((entry) => join(dirPath, entry.name));
|
|
275
|
-
if (jsonlFiles.length === 0) throw new Error(`No JSONL files found in directory: ${dirPath}`);
|
|
276
|
-
const allErrors = [];
|
|
277
|
-
const allWarnings = [];
|
|
278
|
-
const filesWithSchema = [];
|
|
279
|
-
for (const file of jsonlFiles) if (await SchemaLoader.hasSchema(file)) filesWithSchema.push(file);
|
|
280
|
-
else {
|
|
281
|
-
const tableName = basename(file, ".jsonl");
|
|
282
|
-
allWarnings.push(`Skipping validation for '${tableName}': schema file not found`);
|
|
283
|
-
}
|
|
284
|
-
for (const file of filesWithSchema) {
|
|
285
|
-
const result = await this.validateFile(file);
|
|
286
|
-
allErrors.push(...result.errors);
|
|
287
|
-
allWarnings.push(...result.warnings);
|
|
288
|
-
}
|
|
289
|
-
if (filesWithSchema.length > 0) {
|
|
290
|
-
const fkErrors = await this.validateForeignKeys(dirPath, filesWithSchema);
|
|
291
|
-
allErrors.push(...fkErrors);
|
|
292
|
-
}
|
|
293
|
-
return {
|
|
294
|
-
valid: allErrors.length === 0,
|
|
295
|
-
errors: allErrors,
|
|
296
|
-
warnings: allWarnings
|
|
297
|
-
};
|
|
298
|
-
}
|
|
299
|
-
/**
|
|
300
|
-
* Validate foreign key constraints across all tables
|
|
301
|
-
*/
|
|
302
|
-
async validateForeignKeys(dirPath, jsonlFiles) {
|
|
303
|
-
const errors = [];
|
|
304
|
-
const tableData = /* @__PURE__ */ new Map();
|
|
305
|
-
const tableSchemas = /* @__PURE__ */ new Map();
|
|
306
|
-
for (const file of jsonlFiles) {
|
|
307
|
-
const tableName = basename(file, ".jsonl");
|
|
308
|
-
const data = await JsonlReader.read(file);
|
|
309
|
-
const schema = await SchemaLoader.loadSchema(file);
|
|
310
|
-
tableData.set(tableName, data);
|
|
311
|
-
tableSchemas.set(tableName, schema);
|
|
312
|
-
}
|
|
313
|
-
for (const file of jsonlFiles) {
|
|
314
|
-
const tableName = basename(file, ".jsonl");
|
|
315
|
-
const schema = tableSchemas.get(tableName);
|
|
316
|
-
const data = tableData.get(tableName);
|
|
317
|
-
if (!schema || !data || !schema.foreignKeys) continue;
|
|
318
|
-
for (const fk of schema.foreignKeys) {
|
|
319
|
-
const referencedTable = fk.references.table;
|
|
320
|
-
const referencedData = tableData.get(referencedTable);
|
|
321
|
-
if (!referencedData) continue;
|
|
322
|
-
const referencedValues = /* @__PURE__ */ new Set();
|
|
323
|
-
for (const refRow of referencedData) {
|
|
324
|
-
const keyValues = fk.references.columns.map((col) => refRow[col]);
|
|
325
|
-
const compositeKey = JSON.stringify(keyValues);
|
|
326
|
-
referencedValues.add(compositeKey);
|
|
327
|
-
}
|
|
328
|
-
for (let i = 0; i < data.length; i++) {
|
|
329
|
-
const row = data[i];
|
|
330
|
-
const foreignKeyValues = fk.columns.map((col) => row[col]);
|
|
331
|
-
const compositeKey = JSON.stringify(foreignKeyValues);
|
|
332
|
-
if (!referencedValues.has(compositeKey)) errors.push({
|
|
333
|
-
file,
|
|
334
|
-
tableName,
|
|
335
|
-
rowIndex: i,
|
|
336
|
-
issues: [],
|
|
337
|
-
type: "foreignKey",
|
|
338
|
-
foreignKeyError: {
|
|
339
|
-
column: fk.columns.join(", "),
|
|
340
|
-
value: foreignKeyValues.length === 1 ? foreignKeyValues[0] : foreignKeyValues,
|
|
341
|
-
referencedTable,
|
|
342
|
-
referencedColumn: fk.references.columns.join(", ")
|
|
343
|
-
}
|
|
344
|
-
});
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
return errors;
|
|
349
|
-
}
|
|
350
|
-
/**
|
|
351
|
-
* Validate a single JSONL file
|
|
352
|
-
*/
|
|
353
|
-
async validateFile(filePath) {
|
|
354
|
-
const tableName = basename(filePath, ".jsonl");
|
|
355
|
-
const data = await JsonlReader.read(filePath);
|
|
356
|
-
const schema = await SchemaLoader.loadSchema(filePath);
|
|
357
|
-
const errors = [];
|
|
358
|
-
for (let i = 0; i < data.length; i++) {
|
|
359
|
-
const row = data[i];
|
|
360
|
-
const result = schema["~standard"].validate(row);
|
|
361
|
-
if (result instanceof Promise) throw new Error("Asynchronous validation is not supported.");
|
|
362
|
-
if (result.issues && result.issues.length > 0) errors.push({
|
|
363
|
-
file: filePath,
|
|
364
|
-
tableName,
|
|
365
|
-
rowIndex: i,
|
|
366
|
-
issues: result.issues,
|
|
367
|
-
type: "schema"
|
|
368
|
-
});
|
|
369
|
-
}
|
|
370
|
-
return {
|
|
371
|
-
valid: errors.length === 0,
|
|
372
|
-
errors,
|
|
373
|
-
warnings: []
|
|
374
|
-
};
|
|
375
|
-
}
|
|
376
|
-
};
|
|
377
|
-
|
|
378
251
|
//#endregion
|
|
379
252
|
//#region src/runtime.ts
|
|
380
253
|
function detectRuntime() {
|
|
@@ -529,7 +402,8 @@ var LinesDB = class LinesDB {
|
|
|
529
402
|
let foreignKeys;
|
|
530
403
|
try {
|
|
531
404
|
const { pathToFileURL: pathToFileURL$1 } = await import("node:url");
|
|
532
|
-
|
|
405
|
+
const schemaModule = await import(`${pathToFileURL$1(tableConfig.jsonlPath.replace(".jsonl", ".schema.ts")).href}?t=${Date.now()}`);
|
|
406
|
+
foreignKeys = (schemaModule.schema || schemaModule.default)?.foreignKeys || schemaModule.foreignKeys;
|
|
533
407
|
} catch {}
|
|
534
408
|
if (foreignKeys && foreignKeys.length > 0) for (const fk of foreignKeys) {
|
|
535
409
|
const referencedTable = fk.references.table;
|
|
@@ -556,9 +430,13 @@ var LinesDB = class LinesDB {
|
|
|
556
430
|
if (!config.validationSchema) try {
|
|
557
431
|
const { pathToFileURL: pathToFileURL$1 } = await import("node:url");
|
|
558
432
|
const schemaModule = await import(`${pathToFileURL$1(config.jsonlPath.replace(".jsonl", ".schema.ts")).href}?t=${Date.now()}`);
|
|
559
|
-
|
|
560
|
-
if (
|
|
561
|
-
if (schemaModule.
|
|
433
|
+
const schemaExport = schemaModule.schema || schemaModule.default;
|
|
434
|
+
if (schemaExport?.primaryKey) schemaMetadata.primaryKey = schemaExport.primaryKey;
|
|
435
|
+
else if (schemaModule.primaryKey) schemaMetadata.primaryKey = schemaModule.primaryKey;
|
|
436
|
+
if (schemaExport?.foreignKeys) schemaMetadata.foreignKeys = schemaExport.foreignKeys;
|
|
437
|
+
else if (schemaModule.foreignKeys) schemaMetadata.foreignKeys = schemaModule.foreignKeys;
|
|
438
|
+
if (schemaExport?.indexes) schemaMetadata.indexes = schemaExport.indexes;
|
|
439
|
+
else if (schemaModule.indexes) schemaMetadata.indexes = schemaModule.indexes;
|
|
562
440
|
} catch (_error) {}
|
|
563
441
|
this.validationSchemas.set(tableName, validationSchema);
|
|
564
442
|
const validationErrors = [];
|
|
@@ -594,9 +472,12 @@ var LinesDB = class LinesDB {
|
|
|
594
472
|
const primaryKey = biSchema?.primaryKey || schemaMetadata.primaryKey;
|
|
595
473
|
const foreignKeys = biSchema?.foreignKeys || schemaMetadata.foreignKeys;
|
|
596
474
|
const indexes = biSchema?.indexes || schemaMetadata.indexes;
|
|
597
|
-
if (primaryKey && !schema.columns.some((col) => col.primaryKey))
|
|
598
|
-
const col = schema.columns.find((c) => c.name ===
|
|
475
|
+
if (primaryKey && !schema.columns.some((col) => col.primaryKey)) {
|
|
476
|
+
const col = schema.columns.find((c) => c.name === primaryKey);
|
|
599
477
|
if (col) col.primaryKey = true;
|
|
478
|
+
} else if (!primaryKey && !schema.columns.some((col) => col.primaryKey)) {
|
|
479
|
+
const idColumn = schema.columns.find((c) => c.name === "id");
|
|
480
|
+
if (idColumn) idColumn.primaryKey = true;
|
|
600
481
|
}
|
|
601
482
|
if (foreignKeys) schema.foreignKeys = foreignKeys;
|
|
602
483
|
if (indexes) schema.indexes = indexes;
|
|
@@ -620,7 +501,7 @@ var LinesDB = class LinesDB {
|
|
|
620
501
|
});
|
|
621
502
|
const foreignKeyDefs = [];
|
|
622
503
|
if (schema.foreignKeys && schema.foreignKeys.length > 0) for (const fk of schema.foreignKeys) {
|
|
623
|
-
const fkParts = [`FOREIGN KEY (${
|
|
504
|
+
const fkParts = [`FOREIGN KEY (${this.quoteIdentifier(fk.column)})`, `REFERENCES ${this.quoteTableName(fk.references.table)}(${this.quoteIdentifier(fk.references.column)})`];
|
|
624
505
|
if (fk.onDelete) fkParts.push(`ON DELETE ${fk.onDelete}`);
|
|
625
506
|
if (fk.onUpdate) fkParts.push(`ON UPDATE ${fk.onUpdate}`);
|
|
626
507
|
foreignKeyDefs.push(fkParts.join(" "));
|
|
@@ -1111,6 +992,135 @@ var LinesDB = class LinesDB {
|
|
|
1111
992
|
}
|
|
1112
993
|
};
|
|
1113
994
|
|
|
995
|
+
//#endregion
|
|
996
|
+
//#region src/validator.ts
|
|
997
|
+
var Validator = class {
|
|
998
|
+
path;
|
|
999
|
+
projectRoot;
|
|
1000
|
+
constructor(options) {
|
|
1001
|
+
this.path = options.path;
|
|
1002
|
+
this.projectRoot = options.projectRoot || process.cwd();
|
|
1003
|
+
}
|
|
1004
|
+
/**
|
|
1005
|
+
* Validate JSONL file(s)
|
|
1006
|
+
*/
|
|
1007
|
+
async validate() {
|
|
1008
|
+
const fullPath = this.path.startsWith("/") ? this.path : join(this.projectRoot, this.path);
|
|
1009
|
+
const stats = await stat(fullPath);
|
|
1010
|
+
if (stats.isDirectory()) return this.validateDirectory(fullPath);
|
|
1011
|
+
else if (stats.isFile() && fullPath.endsWith(".jsonl")) return this.validateFile(fullPath);
|
|
1012
|
+
else throw new Error(`Invalid path: ${this.path}. Must be a directory or .jsonl file.`);
|
|
1013
|
+
}
|
|
1014
|
+
/**
|
|
1015
|
+
* Validate all JSONL files in a directory
|
|
1016
|
+
*/
|
|
1017
|
+
async validateDirectory(dirPath) {
|
|
1018
|
+
const jsonlFiles = (await readdir(dirPath, { withFileTypes: true })).filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl")).map((entry) => join(dirPath, entry.name));
|
|
1019
|
+
if (jsonlFiles.length === 0) throw new Error(`No JSONL files found in directory: ${dirPath}`);
|
|
1020
|
+
const allErrors = [];
|
|
1021
|
+
const allWarnings = [];
|
|
1022
|
+
const filesWithSchema = [];
|
|
1023
|
+
for (const file of jsonlFiles) if (await SchemaLoader.hasSchema(file)) filesWithSchema.push(file);
|
|
1024
|
+
else {
|
|
1025
|
+
const tableName = basename(file, ".jsonl");
|
|
1026
|
+
allWarnings.push(`Skipping validation for '${tableName}': schema file not found`);
|
|
1027
|
+
}
|
|
1028
|
+
for (const file of filesWithSchema) {
|
|
1029
|
+
const result = await this.validateFile(file);
|
|
1030
|
+
allErrors.push(...result.errors);
|
|
1031
|
+
allWarnings.push(...result.warnings);
|
|
1032
|
+
}
|
|
1033
|
+
if (filesWithSchema.length > 0 && allErrors.length === 0) {
|
|
1034
|
+
const dbErrors = await this.validateWithDatabase(dirPath, filesWithSchema);
|
|
1035
|
+
allErrors.push(...dbErrors);
|
|
1036
|
+
}
|
|
1037
|
+
return {
|
|
1038
|
+
valid: allErrors.length === 0,
|
|
1039
|
+
errors: allErrors,
|
|
1040
|
+
warnings: allWarnings
|
|
1041
|
+
};
|
|
1042
|
+
}
|
|
1043
|
+
/**
|
|
1044
|
+
* Validate by loading data into an actual database
|
|
1045
|
+
* This catches constraint violations (unique, primary key, foreign key, etc.)
|
|
1046
|
+
*/
|
|
1047
|
+
async validateWithDatabase(dirPath, jsonlFiles) {
|
|
1048
|
+
const errors = [];
|
|
1049
|
+
const warnMessages = [];
|
|
1050
|
+
const originalWarn = console.warn;
|
|
1051
|
+
console.warn = (...args) => {
|
|
1052
|
+
const message = args.map((arg) => String(arg)).join(" ");
|
|
1053
|
+
warnMessages.push(message);
|
|
1054
|
+
originalWarn(...args);
|
|
1055
|
+
};
|
|
1056
|
+
try {
|
|
1057
|
+
const db = LinesDB.create({ dataDir: dirPath });
|
|
1058
|
+
await db.initialize();
|
|
1059
|
+
await db.close();
|
|
1060
|
+
for (const message of warnMessages) if (message.includes("Failed to load table")) {
|
|
1061
|
+
const tableNameMatch = message.match(/Failed to load table '([^']+)'/);
|
|
1062
|
+
const tableName = tableNameMatch ? tableNameMatch[1] : "unknown";
|
|
1063
|
+
const file = jsonlFiles.find((f) => basename(f, ".jsonl") === tableName);
|
|
1064
|
+
errors.push({
|
|
1065
|
+
file: file || `${dirPath}/${tableName}.jsonl`,
|
|
1066
|
+
tableName,
|
|
1067
|
+
rowIndex: 0,
|
|
1068
|
+
issues: [{
|
|
1069
|
+
message: message.replace(/^Warning:\s*/, ""),
|
|
1070
|
+
path: []
|
|
1071
|
+
}],
|
|
1072
|
+
type: "schema"
|
|
1073
|
+
});
|
|
1074
|
+
}
|
|
1075
|
+
} catch (error) {
|
|
1076
|
+
errors.push({
|
|
1077
|
+
file: dirPath,
|
|
1078
|
+
tableName: "database",
|
|
1079
|
+
rowIndex: 0,
|
|
1080
|
+
issues: [{
|
|
1081
|
+
message: `Database initialization failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
1082
|
+
path: []
|
|
1083
|
+
}],
|
|
1084
|
+
type: "schema"
|
|
1085
|
+
});
|
|
1086
|
+
} finally {
|
|
1087
|
+
console.warn = originalWarn;
|
|
1088
|
+
}
|
|
1089
|
+
return errors;
|
|
1090
|
+
}
|
|
1091
|
+
/**
|
|
1092
|
+
* Validate a single JSONL file
|
|
1093
|
+
*/
|
|
1094
|
+
async validateFile(filePath) {
|
|
1095
|
+
const tableName = basename(filePath, ".jsonl");
|
|
1096
|
+
const data = await JsonlReader.read(filePath);
|
|
1097
|
+
const schema = await SchemaLoader.loadSchema(filePath);
|
|
1098
|
+
const errors = [];
|
|
1099
|
+
for (let i = 0; i < data.length; i++) {
|
|
1100
|
+
const row = data[i];
|
|
1101
|
+
const result = schema["~standard"].validate(row);
|
|
1102
|
+
if (result instanceof Promise) throw new Error("Asynchronous validation is not supported.");
|
|
1103
|
+
if (result.issues && result.issues.length > 0) errors.push({
|
|
1104
|
+
file: filePath,
|
|
1105
|
+
tableName,
|
|
1106
|
+
rowIndex: i,
|
|
1107
|
+
issues: result.issues,
|
|
1108
|
+
type: "schema"
|
|
1109
|
+
});
|
|
1110
|
+
}
|
|
1111
|
+
if (errors.length === 0) {
|
|
1112
|
+
const dirPath = dirname(filePath);
|
|
1113
|
+
const dbErrors = await this.validateWithDatabase(dirPath, [filePath]);
|
|
1114
|
+
errors.push(...dbErrors);
|
|
1115
|
+
}
|
|
1116
|
+
return {
|
|
1117
|
+
valid: errors.length === 0,
|
|
1118
|
+
errors,
|
|
1119
|
+
warnings: []
|
|
1120
|
+
};
|
|
1121
|
+
}
|
|
1122
|
+
};
|
|
1123
|
+
|
|
1114
1124
|
//#endregion
|
|
1115
1125
|
//#region src/error-formatter.ts
|
|
1116
1126
|
var ErrorFormatter = class {
|
package/dist/index.cjs
CHANGED
|
@@ -282,9 +282,9 @@ var DirectoryScanner = class {
|
|
|
282
282
|
* const schema = defineSchema(
|
|
283
283
|
* v.object({ id: v.number(), customerId: v.number() }),
|
|
284
284
|
* {
|
|
285
|
-
* primaryKey:
|
|
285
|
+
* primaryKey: 'id',
|
|
286
286
|
* foreignKeys: [
|
|
287
|
-
* {
|
|
287
|
+
* { column: 'customerId', references: { table: 'users', column: 'id' } }
|
|
288
288
|
* ]
|
|
289
289
|
* }
|
|
290
290
|
* );
|
|
@@ -358,7 +358,8 @@ var LinesDB = class LinesDB {
|
|
|
358
358
|
let foreignKeys;
|
|
359
359
|
try {
|
|
360
360
|
const { pathToFileURL: pathToFileURL$1 } = await import("node:url");
|
|
361
|
-
|
|
361
|
+
const schemaModule = await import(`${pathToFileURL$1(tableConfig.jsonlPath.replace(".jsonl", ".schema.ts")).href}?t=${Date.now()}`);
|
|
362
|
+
foreignKeys = (schemaModule.schema || schemaModule.default)?.foreignKeys || schemaModule.foreignKeys;
|
|
362
363
|
} catch {}
|
|
363
364
|
if (foreignKeys && foreignKeys.length > 0) for (const fk of foreignKeys) {
|
|
364
365
|
const referencedTable = fk.references.table;
|
|
@@ -385,9 +386,13 @@ var LinesDB = class LinesDB {
|
|
|
385
386
|
if (!config.validationSchema) try {
|
|
386
387
|
const { pathToFileURL: pathToFileURL$1 } = await import("node:url");
|
|
387
388
|
const schemaModule = await import(`${pathToFileURL$1(config.jsonlPath.replace(".jsonl", ".schema.ts")).href}?t=${Date.now()}`);
|
|
388
|
-
|
|
389
|
-
if (
|
|
390
|
-
if (schemaModule.
|
|
389
|
+
const schemaExport = schemaModule.schema || schemaModule.default;
|
|
390
|
+
if (schemaExport?.primaryKey) schemaMetadata.primaryKey = schemaExport.primaryKey;
|
|
391
|
+
else if (schemaModule.primaryKey) schemaMetadata.primaryKey = schemaModule.primaryKey;
|
|
392
|
+
if (schemaExport?.foreignKeys) schemaMetadata.foreignKeys = schemaExport.foreignKeys;
|
|
393
|
+
else if (schemaModule.foreignKeys) schemaMetadata.foreignKeys = schemaModule.foreignKeys;
|
|
394
|
+
if (schemaExport?.indexes) schemaMetadata.indexes = schemaExport.indexes;
|
|
395
|
+
else if (schemaModule.indexes) schemaMetadata.indexes = schemaModule.indexes;
|
|
391
396
|
} catch (_error) {}
|
|
392
397
|
this.validationSchemas.set(tableName, validationSchema);
|
|
393
398
|
const validationErrors = [];
|
|
@@ -423,9 +428,12 @@ var LinesDB = class LinesDB {
|
|
|
423
428
|
const primaryKey = biSchema?.primaryKey || schemaMetadata.primaryKey;
|
|
424
429
|
const foreignKeys = biSchema?.foreignKeys || schemaMetadata.foreignKeys;
|
|
425
430
|
const indexes = biSchema?.indexes || schemaMetadata.indexes;
|
|
426
|
-
if (primaryKey && !schema.columns.some((col) => col.primaryKey))
|
|
427
|
-
const col = schema.columns.find((c) => c.name ===
|
|
431
|
+
if (primaryKey && !schema.columns.some((col) => col.primaryKey)) {
|
|
432
|
+
const col = schema.columns.find((c) => c.name === primaryKey);
|
|
428
433
|
if (col) col.primaryKey = true;
|
|
434
|
+
} else if (!primaryKey && !schema.columns.some((col) => col.primaryKey)) {
|
|
435
|
+
const idColumn = schema.columns.find((c) => c.name === "id");
|
|
436
|
+
if (idColumn) idColumn.primaryKey = true;
|
|
429
437
|
}
|
|
430
438
|
if (foreignKeys) schema.foreignKeys = foreignKeys;
|
|
431
439
|
if (indexes) schema.indexes = indexes;
|
|
@@ -449,7 +457,7 @@ var LinesDB = class LinesDB {
|
|
|
449
457
|
});
|
|
450
458
|
const foreignKeyDefs = [];
|
|
451
459
|
if (schema.foreignKeys && schema.foreignKeys.length > 0) for (const fk of schema.foreignKeys) {
|
|
452
|
-
const fkParts = [`FOREIGN KEY (${
|
|
460
|
+
const fkParts = [`FOREIGN KEY (${this.quoteIdentifier(fk.column)})`, `REFERENCES ${this.quoteTableName(fk.references.table)}(${this.quoteIdentifier(fk.references.column)})`];
|
|
453
461
|
if (fk.onDelete) fkParts.push(`ON DELETE ${fk.onDelete}`);
|
|
454
462
|
if (fk.onUpdate) fkParts.push(`ON UPDATE ${fk.onUpdate}`);
|
|
455
463
|
foreignKeyDefs.push(fkParts.join(" "));
|
|
@@ -1087,9 +1095,9 @@ var Validator = class {
|
|
|
1087
1095
|
allErrors.push(...result.errors);
|
|
1088
1096
|
allWarnings.push(...result.warnings);
|
|
1089
1097
|
}
|
|
1090
|
-
if (filesWithSchema.length > 0) {
|
|
1091
|
-
const
|
|
1092
|
-
allErrors.push(...
|
|
1098
|
+
if (filesWithSchema.length > 0 && allErrors.length === 0) {
|
|
1099
|
+
const dbErrors = await this.validateWithDatabase(dirPath, filesWithSchema);
|
|
1100
|
+
allErrors.push(...dbErrors);
|
|
1093
1101
|
}
|
|
1094
1102
|
return {
|
|
1095
1103
|
valid: allErrors.length === 0,
|
|
@@ -1098,53 +1106,50 @@ var Validator = class {
|
|
|
1098
1106
|
};
|
|
1099
1107
|
}
|
|
1100
1108
|
/**
|
|
1101
|
-
* Validate
|
|
1109
|
+
* Validate by loading data into an actual database
|
|
1110
|
+
* This catches constraint violations (unique, primary key, foreign key, etc.)
|
|
1102
1111
|
*/
|
|
1103
|
-
async
|
|
1112
|
+
async validateWithDatabase(dirPath, jsonlFiles) {
|
|
1104
1113
|
const errors = [];
|
|
1105
|
-
const
|
|
1106
|
-
const
|
|
1107
|
-
|
|
1108
|
-
const
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
const
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
const row = data[i];
|
|
1131
|
-
const foreignKeyValues = fk.columns.map((col) => row[col]);
|
|
1132
|
-
const compositeKey = JSON.stringify(foreignKeyValues);
|
|
1133
|
-
if (!referencedValues.has(compositeKey)) errors.push({
|
|
1134
|
-
file,
|
|
1135
|
-
tableName,
|
|
1136
|
-
rowIndex: i,
|
|
1137
|
-
issues: [],
|
|
1138
|
-
type: "foreignKey",
|
|
1139
|
-
foreignKeyError: {
|
|
1140
|
-
column: fk.columns.join(", "),
|
|
1141
|
-
value: foreignKeyValues.length === 1 ? foreignKeyValues[0] : foreignKeyValues,
|
|
1142
|
-
referencedTable,
|
|
1143
|
-
referencedColumn: fk.references.columns.join(", ")
|
|
1144
|
-
}
|
|
1145
|
-
});
|
|
1146
|
-
}
|
|
1114
|
+
const warnMessages = [];
|
|
1115
|
+
const originalWarn = console.warn;
|
|
1116
|
+
console.warn = (...args) => {
|
|
1117
|
+
const message = args.map((arg) => String(arg)).join(" ");
|
|
1118
|
+
warnMessages.push(message);
|
|
1119
|
+
originalWarn(...args);
|
|
1120
|
+
};
|
|
1121
|
+
try {
|
|
1122
|
+
const db = LinesDB.create({ dataDir: dirPath });
|
|
1123
|
+
await db.initialize();
|
|
1124
|
+
await db.close();
|
|
1125
|
+
for (const message of warnMessages) if (message.includes("Failed to load table")) {
|
|
1126
|
+
const tableNameMatch = message.match(/Failed to load table '([^']+)'/);
|
|
1127
|
+
const tableName = tableNameMatch ? tableNameMatch[1] : "unknown";
|
|
1128
|
+
const file = jsonlFiles.find((f) => (0, node_path.basename)(f, ".jsonl") === tableName);
|
|
1129
|
+
errors.push({
|
|
1130
|
+
file: file || `${dirPath}/${tableName}.jsonl`,
|
|
1131
|
+
tableName,
|
|
1132
|
+
rowIndex: 0,
|
|
1133
|
+
issues: [{
|
|
1134
|
+
message: message.replace(/^Warning:\s*/, ""),
|
|
1135
|
+
path: []
|
|
1136
|
+
}],
|
|
1137
|
+
type: "schema"
|
|
1138
|
+
});
|
|
1147
1139
|
}
|
|
1140
|
+
} catch (error) {
|
|
1141
|
+
errors.push({
|
|
1142
|
+
file: dirPath,
|
|
1143
|
+
tableName: "database",
|
|
1144
|
+
rowIndex: 0,
|
|
1145
|
+
issues: [{
|
|
1146
|
+
message: `Database initialization failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
1147
|
+
path: []
|
|
1148
|
+
}],
|
|
1149
|
+
type: "schema"
|
|
1150
|
+
});
|
|
1151
|
+
} finally {
|
|
1152
|
+
console.warn = originalWarn;
|
|
1148
1153
|
}
|
|
1149
1154
|
return errors;
|
|
1150
1155
|
}
|
|
@@ -1168,6 +1173,11 @@ var Validator = class {
|
|
|
1168
1173
|
type: "schema"
|
|
1169
1174
|
});
|
|
1170
1175
|
}
|
|
1176
|
+
if (errors.length === 0) {
|
|
1177
|
+
const dirPath = (0, node_path.dirname)(filePath);
|
|
1178
|
+
const dbErrors = await this.validateWithDatabase(dirPath, [filePath]);
|
|
1179
|
+
errors.push(...dbErrors);
|
|
1180
|
+
}
|
|
1171
1181
|
return {
|
|
1172
1182
|
valid: errors.length === 0,
|
|
1173
1183
|
errors,
|
package/dist/index.d.cts
CHANGED
|
@@ -30,10 +30,10 @@ type StandardSchemaIssue = StandardSchemaV1.Issue;
|
|
|
30
30
|
type InferInput<T$1> = T$1 extends StandardSchemaV1<infer I, unknown> ? I : never;
|
|
31
31
|
type InferOutput<T$1> = T$1 extends StandardSchemaV1<unknown, infer O> ? O : never;
|
|
32
32
|
interface ForeignKeyDefinition {
|
|
33
|
-
|
|
33
|
+
column: string;
|
|
34
34
|
references: {
|
|
35
35
|
table: string;
|
|
36
|
-
|
|
36
|
+
column: string;
|
|
37
37
|
};
|
|
38
38
|
onDelete?: 'CASCADE' | 'SET NULL' | 'RESTRICT' | 'NO ACTION';
|
|
39
39
|
onUpdate?: 'CASCADE' | 'SET NULL' | 'RESTRICT' | 'NO ACTION';
|
|
@@ -328,9 +328,9 @@ declare class DirectoryScanner {
|
|
|
328
328
|
*/
|
|
329
329
|
interface SchemaOptions {
|
|
330
330
|
/**
|
|
331
|
-
* Primary key
|
|
331
|
+
* Primary key column
|
|
332
332
|
*/
|
|
333
|
-
primaryKey?: string
|
|
333
|
+
primaryKey?: string;
|
|
334
334
|
/**
|
|
335
335
|
* Foreign key constraints
|
|
336
336
|
*/
|
|
@@ -356,9 +356,9 @@ interface BiDirectionalSchema<Input extends Table = Table, Output extends Table
|
|
|
356
356
|
*/
|
|
357
357
|
backward?: (output: Output) => Input;
|
|
358
358
|
/**
|
|
359
|
-
* Primary key
|
|
359
|
+
* Primary key column
|
|
360
360
|
*/
|
|
361
|
-
primaryKey?: string
|
|
361
|
+
primaryKey?: string;
|
|
362
362
|
/**
|
|
363
363
|
* Foreign key constraints
|
|
364
364
|
*/
|
|
@@ -393,9 +393,9 @@ interface BiDirectionalSchema<Input extends Table = Table, Output extends Table
|
|
|
393
393
|
* const schema = defineSchema(
|
|
394
394
|
* v.object({ id: v.number(), customerId: v.number() }),
|
|
395
395
|
* {
|
|
396
|
-
* primaryKey:
|
|
396
|
+
* primaryKey: 'id',
|
|
397
397
|
* foreignKeys: [
|
|
398
|
-
* {
|
|
398
|
+
* { column: 'customerId', references: { table: 'users', column: 'id' } }
|
|
399
399
|
* ]
|
|
400
400
|
* }
|
|
401
401
|
* );
|
|
@@ -469,9 +469,10 @@ declare class Validator {
|
|
|
469
469
|
*/
|
|
470
470
|
private validateDirectory;
|
|
471
471
|
/**
|
|
472
|
-
* Validate
|
|
472
|
+
* Validate by loading data into an actual database
|
|
473
|
+
* This catches constraint violations (unique, primary key, foreign key, etc.)
|
|
473
474
|
*/
|
|
474
|
-
private
|
|
475
|
+
private validateWithDatabase;
|
|
475
476
|
/**
|
|
476
477
|
* Validate a single JSONL file
|
|
477
478
|
*/
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/sqlite-adapter.ts","../src/types.ts","../src/database.ts","../src/jsonl-reader.ts","../src/jsonl-writer.ts","../src/schema-loader.ts","../src/directory-scanner.ts","../src/schema.ts","../src/type-generator.ts","../src/validator.ts","../src/jsonl-migration.ts","../src/runtime.ts"],"sourcesContent":[],"mappings":";;;;;;;AASA;AAMA;;UANiB,cAAA;wBACO;ECPZ,IAAA,CAAA,GAAK,EAAA,MAAA,CAAA,
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/sqlite-adapter.ts","../src/types.ts","../src/database.ts","../src/jsonl-reader.ts","../src/jsonl-writer.ts","../src/schema-loader.ts","../src/directory-scanner.ts","../src/schema.ts","../src/type-generator.ts","../src/validator.ts","../src/jsonl-migration.ts","../src/runtime.ts"],"sourcesContent":[],"mappings":"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"}
|