@toiroakr/lines-db 0.6.1 → 0.7.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 +11 -0
- package/bin/cli.js +72 -25
- package/dist/index.cjs +87 -24
- package/dist/index.d.cts +30 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +30 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +82 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/cli.ts +3 -2
- package/src/database.test.ts +28 -0
- package/src/database.ts +18 -7
- package/src/index.ts +8 -0
- package/src/schema-extensions.test.ts +155 -0
- package/src/schema-extensions.ts +89 -0
- package/src/schema-loader.test.ts +90 -0
- package/src/schema-loader.ts +10 -18
- package/src/type-generator.ts +11 -10
package/dist/index.js
CHANGED
|
@@ -159,6 +159,71 @@ var JsonlWriter = class {
|
|
|
159
159
|
}
|
|
160
160
|
};
|
|
161
161
|
|
|
162
|
+
//#endregion
|
|
163
|
+
//#region src/schema-extensions.ts
|
|
164
|
+
/**
|
|
165
|
+
* Supported schema file extensions, in priority order.
|
|
166
|
+
* The first match wins when discovering schema files.
|
|
167
|
+
*/
|
|
168
|
+
const SCHEMA_EXTENSIONS = [
|
|
169
|
+
".schema.ts",
|
|
170
|
+
".schema.mts",
|
|
171
|
+
".schema.cts"
|
|
172
|
+
];
|
|
173
|
+
/**
|
|
174
|
+
* Map from schema extensions to their JavaScript import counterparts.
|
|
175
|
+
*/
|
|
176
|
+
const SCHEMA_TO_JS_IMPORT_MAP = {
|
|
177
|
+
".schema.ts": ".schema.js",
|
|
178
|
+
".schema.mts": ".schema.mjs",
|
|
179
|
+
".schema.cts": ".schema.cjs"
|
|
180
|
+
};
|
|
181
|
+
/**
|
|
182
|
+
* Try each supported schema extension and return the full path of the first
|
|
183
|
+
* one that exists on disk. Returns undefined if none is found.
|
|
184
|
+
*/
|
|
185
|
+
async function findSchemaFile(dir, tableName) {
|
|
186
|
+
for (const ext of SCHEMA_EXTENSIONS) {
|
|
187
|
+
const candidate = join(dir, `${tableName}${ext}`);
|
|
188
|
+
try {
|
|
189
|
+
await access(candidate);
|
|
190
|
+
return candidate;
|
|
191
|
+
} catch {}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Synchronously find a schema file among directory entries.
|
|
196
|
+
* Returns the full path of the first match, or undefined.
|
|
197
|
+
*/
|
|
198
|
+
function findSchemaFileInEntries(dataDirPath, tableName, entries) {
|
|
199
|
+
for (const ext of SCHEMA_EXTENSIONS) {
|
|
200
|
+
const candidateName = `${tableName}${ext}`;
|
|
201
|
+
if (entries.some((e) => e.isFile() && e.name === candidateName)) return join(dataDirPath, candidateName);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Check if a filename matches any supported schema file pattern.
|
|
206
|
+
*/
|
|
207
|
+
function isSchemaFile(fileName) {
|
|
208
|
+
return SCHEMA_EXTENSIONS.some((ext) => fileName.endsWith(ext));
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Extract table name from a schema filename.
|
|
212
|
+
* e.g., "users.schema.ts" -> "users", "users.schema.mts" -> "users"
|
|
213
|
+
*/
|
|
214
|
+
function extractTableNameFromSchemaFile(fileName) {
|
|
215
|
+
for (const ext of SCHEMA_EXTENSIONS) if (fileName.endsWith(ext)) return fileName.slice(0, -ext.length);
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Rewrite a TypeScript path to its JavaScript counterpart for ESM imports.
|
|
220
|
+
* ".schema.ts" -> ".schema.js", ".schema.mts" -> ".schema.mjs", ".schema.cts" -> ".schema.cjs"
|
|
221
|
+
*/
|
|
222
|
+
function rewriteExtensionForImport(filePath) {
|
|
223
|
+
for (const [tsExt, jsExt] of Object.entries(SCHEMA_TO_JS_IMPORT_MAP)) if (filePath.endsWith(tsExt)) return filePath.slice(0, -tsExt.length) + jsExt;
|
|
224
|
+
return filePath;
|
|
225
|
+
}
|
|
226
|
+
|
|
162
227
|
//#endregion
|
|
163
228
|
//#region src/schema-loader.ts
|
|
164
229
|
var SchemaLoader = class {
|
|
@@ -166,27 +231,17 @@ var SchemaLoader = class {
|
|
|
166
231
|
* Check if a schema file exists for a table
|
|
167
232
|
*/
|
|
168
233
|
static async hasSchema(jsonlPath) {
|
|
169
|
-
|
|
170
|
-
try {
|
|
171
|
-
await access(schemaPath);
|
|
172
|
-
return true;
|
|
173
|
-
} catch {
|
|
174
|
-
return false;
|
|
175
|
-
}
|
|
234
|
+
return await findSchemaFile(dirname(jsonlPath), basename(jsonlPath, ".jsonl")) !== void 0;
|
|
176
235
|
}
|
|
177
236
|
/**
|
|
178
237
|
* Load a validation schema file for a table
|
|
179
|
-
* Requires ${tableName}.schema.ts to exist alongside the JSONL file
|
|
238
|
+
* Requires ${tableName}.schema.{ts,mts,cts} to exist alongside the JSONL file
|
|
180
239
|
*/
|
|
181
240
|
static async loadSchema(jsonlPath) {
|
|
182
241
|
const dir = dirname(jsonlPath);
|
|
183
242
|
const tableName = basename(jsonlPath, ".jsonl");
|
|
184
|
-
const schemaPath =
|
|
185
|
-
|
|
186
|
-
await access(schemaPath);
|
|
187
|
-
} catch (error) {
|
|
188
|
-
throw new Error(`Schema file not found for table '${tableName}'. Expected: ${schemaPath}`, { cause: error instanceof Error ? error : void 0 });
|
|
189
|
-
}
|
|
243
|
+
const schemaPath = await findSchemaFile(dir, tableName);
|
|
244
|
+
if (!schemaPath) throw new Error(`Schema file not found for table '${tableName}'. Expected one of: ${SCHEMA_EXTENSIONS.map((ext) => `${tableName}${ext}`).join(", ")}`);
|
|
190
245
|
try {
|
|
191
246
|
const module = await import(`${pathToFileURL(schemaPath).href}?t=${Date.now()}`);
|
|
192
247
|
const schema = module.default || module.schema;
|
|
@@ -360,8 +415,11 @@ var LinesDB = class LinesDB {
|
|
|
360
415
|
let foreignKeys;
|
|
361
416
|
try {
|
|
362
417
|
const { pathToFileURL: pathToFileURL$1 } = await import("node:url");
|
|
363
|
-
const
|
|
364
|
-
|
|
418
|
+
const schemaPath = await findSchemaFile(dirname(tableConfig.jsonlPath), basename(tableConfig.jsonlPath, ".jsonl"));
|
|
419
|
+
if (schemaPath) {
|
|
420
|
+
const schemaModule = await import(`${pathToFileURL$1(schemaPath).href}?t=${Date.now()}`);
|
|
421
|
+
foreignKeys = (schemaModule.schema || schemaModule.default)?.foreignKeys || schemaModule.foreignKeys;
|
|
422
|
+
}
|
|
365
423
|
} catch {}
|
|
366
424
|
if (foreignKeys && foreignKeys.length > 0) for (const fk of foreignKeys) {
|
|
367
425
|
const referencedTable = fk.references.table;
|
|
@@ -401,7 +459,9 @@ var LinesDB = class LinesDB {
|
|
|
401
459
|
} catch (_error) {}
|
|
402
460
|
if (!config.validationSchema) try {
|
|
403
461
|
const { pathToFileURL: pathToFileURL$1 } = await import("node:url");
|
|
404
|
-
const
|
|
462
|
+
const schemaPath = await findSchemaFile(dirname(config.jsonlPath), basename(config.jsonlPath, ".jsonl"));
|
|
463
|
+
if (!schemaPath) throw new Error("Schema file not found");
|
|
464
|
+
const schemaModule = await import(`${pathToFileURL$1(schemaPath).href}?t=${Date.now()}`);
|
|
405
465
|
const schemaExport = schemaModule.schema || schemaModule.default;
|
|
406
466
|
if (schemaExport?.primaryKey) schemaMetadata.primaryKey = schemaExport.primaryKey;
|
|
407
467
|
else if (schemaModule.primaryKey) schemaMetadata.primaryKey = schemaModule.primaryKey;
|
|
@@ -1089,7 +1149,7 @@ var TypeGenerator = class {
|
|
|
1089
1149
|
this.projectRoot = envProjectRoot !== void 0 ? envProjectRoot : options.projectRoot || process.cwd();
|
|
1090
1150
|
this.dataDir = options.dataDir;
|
|
1091
1151
|
this.dataDirPath = isAbsolute(this.dataDir) ? this.dataDir : join(this.projectRoot, this.dataDir);
|
|
1092
|
-
this.outputFile = join(this.dataDirPath, "db.ts");
|
|
1152
|
+
this.outputFile = options.output ? isAbsolute(options.output) ? options.output : join(this.projectRoot, options.output) : join(this.dataDirPath, "db.ts");
|
|
1093
1153
|
}
|
|
1094
1154
|
/**
|
|
1095
1155
|
* Generate types file from JSONL files and their optional schema files.
|
|
@@ -1112,12 +1172,10 @@ var TypeGenerator = class {
|
|
|
1112
1172
|
const tables = [];
|
|
1113
1173
|
for (const entry of entries) if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
1114
1174
|
const tableName = basename(entry.name, ".jsonl");
|
|
1115
|
-
const
|
|
1116
|
-
const schemaFilePath = join(this.dataDirPath, schemaFileName);
|
|
1117
|
-
const hasSchema = entries.some((e) => e.isFile() && e.name === schemaFileName);
|
|
1175
|
+
const schemaFilePath = findSchemaFileInEntries(this.dataDirPath, tableName, entries);
|
|
1118
1176
|
tables.push({
|
|
1119
1177
|
tableName,
|
|
1120
|
-
schemaFile:
|
|
1178
|
+
schemaFile: schemaFilePath
|
|
1121
1179
|
});
|
|
1122
1180
|
}
|
|
1123
1181
|
return tables;
|
|
@@ -1138,7 +1196,7 @@ var TypeGenerator = class {
|
|
|
1138
1196
|
if (table.schemaFile) {
|
|
1139
1197
|
const schemaIdentifier = this.createSchemaIdentifier(table.tableName, usedAliases);
|
|
1140
1198
|
usedAliases.add(schemaIdentifier);
|
|
1141
|
-
let relativePath = relative(join(this.outputFile, ".."), table.schemaFile).replace(/\\/g, "/")
|
|
1199
|
+
let relativePath = rewriteExtensionForImport(relative(join(this.outputFile, ".."), table.schemaFile).replace(/\\/g, "/"));
|
|
1142
1200
|
if (!relativePath.startsWith(".")) relativePath = "./" + relativePath;
|
|
1143
1201
|
imports.push(`import { schema as ${schemaIdentifier} } from '${relativePath}';`);
|
|
1144
1202
|
tableEntries.push(` ${tableKey}: InferOutput<typeof ${schemaIdentifier}>;`);
|
|
@@ -1214,5 +1272,5 @@ async function ensureTableRowsValid(options) {
|
|
|
1214
1272
|
}
|
|
1215
1273
|
|
|
1216
1274
|
//#endregion
|
|
1217
|
-
export { DirectoryScanner, JsonlReader, JsonlWriter, LinesDB, RUNTIME, SchemaLoader, TypeGenerator, defineSchema, detectRuntime, ensureTableRowsValid, hasBackward };
|
|
1275
|
+
export { DirectoryScanner, JsonlReader, JsonlWriter, LinesDB, RUNTIME, SCHEMA_EXTENSIONS, SchemaLoader, TypeGenerator, defineSchema, detectRuntime, ensureTableRowsValid, extractTableNameFromSchemaFile, findSchemaFile, hasBackward, isSchemaFile, rewriteExtensionForImport };
|
|
1218
1276
|
//# sourceMappingURL=index.js.map
|