orchid-orm 1.76.5 → 1.77.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/dist/bun.d.ts +4 -4
- package/dist/bun.js.map +1 -1
- package/dist/bun.mjs.map +1 -1
- package/dist/index.d.ts +871 -133
- package/dist/index.js +611 -32
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +612 -34
- package/dist/index.mjs.map +1 -1
- package/dist/migrations/index.js +104 -63
- package/dist/migrations/index.js.map +1 -1
- package/dist/migrations/index.mjs +106 -65
- package/dist/migrations/index.mjs.map +1 -1
- package/dist/node-postgres.d.ts +4 -4
- package/dist/node-postgres.js.map +1 -1
- package/dist/node-postgres.mjs.map +1 -1
- package/dist/postgres-js.d.ts +4 -4
- package/dist/postgres-js.js.map +1 -1
- package/dist/postgres-js.mjs.map +1 -1
- package/package.json +4 -4
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { astToMigration, concatSchemaAndName, createMigrationInterface, dbColumnToAst, encodeColumnDefault, getConstraintName, getDbStructureTableData, getDbTableColumnsChecks, getDbVersion, getExcludeName, getIndexName, getMigrationsSchemaAndTable, getSchemaAndTableFromName, instantiateDbColumn, introspectDbSchema, makeDomainsMap, makeFileVersion, makeStructureToAstCtx, migrate, migrateAndClose, promptSelect, rakeDbCommands, saveMigratedVersion, structureToAst, tableToAst, writeMigrationFile } from "rake-db";
|
|
2
|
-
import { ArrayColumn, DomainColumn, EnumColumn, RawSql, UnknownColumn, VirtualColumn, addCode, codeToString, colors, columnsShapeToCode, deepCompare, emptyArray, emptyObject, exhaustive, getColumnBaseType, getDriverErrorCode, getFreeSetAlias, getImportPath, getQuerySchema, getSupportedDefaultPrivileges, pathToLog, pluralize,
|
|
1
|
+
import { astToMigration, concatSchemaAndName, createMigrationInterface, dbColumnToAst, encodeColumnDefault, getConstraintName, getDbStructureTableData, getDbTableColumnsChecks, getDbVersion, getExcludeName, getIndexName, getMigrationsSchemaAndTable, getSchemaAndTableFromName, getTableFactoryConfig, instantiateDbColumn, introspectDbSchema, makeDomainsMap, makeFileVersion, makeStructureToAstCtx, migrate, migrateAndClose, promptSelect, rakeDbCommands, saveMigratedVersion, structureToAst, tableToAst, writeMigrationFile } from "rake-db";
|
|
2
|
+
import { ArrayColumn, DomainColumn, EnumColumn, RawSql, UnknownColumn, VirtualColumn, addCode, codeToString, colors, columnsShapeToCode, constraintToCode, deepCompare, emptyArray, emptyObject, excludeToCode, exhaustive, getColumnBaseType, getDriverErrorCode, getForeignKeyTableInstance, getFreeSetAlias, getImportPath, getQuerySchema, getSupportedDefaultPrivileges, indexToCode, pathToLog, pluralize, primaryKeyInnerToCode, queryToSql, quoteObjectKey, raw, rawSqlToSql, singleQuote, sqlToRawSql, toArray, toCamelCase, toPascalCase, toSnakeCase } from "pqb/internal";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
5
5
|
import fs from "node:fs/promises";
|
|
@@ -1279,7 +1279,7 @@ const collectCodeFkeys = (config, { codeTable, changeTableAst: { shape } }, curr
|
|
|
1279
1279
|
};
|
|
1280
1280
|
const fnOrTableToString = (fnOrTable) => {
|
|
1281
1281
|
if (typeof fnOrTable !== "string") {
|
|
1282
|
-
const { schema, table, nameInDb } =
|
|
1282
|
+
const { schema, table, nameInDb } = getForeignKeyTableInstance(fnOrTable());
|
|
1283
1283
|
const name = nameInDb || table;
|
|
1284
1284
|
if (!name) throw new Error("Referenced table is missing table property");
|
|
1285
1285
|
fnOrTable = concatSchemaAndName({
|
|
@@ -3136,7 +3136,7 @@ const formatPolicyChangeDefinition = (policy) => {
|
|
|
3136
3136
|
var AbortSignal = class extends Error {};
|
|
3137
3137
|
const generate = async (adapters, config, args, afterPull) => {
|
|
3138
3138
|
let { dbPath } = config;
|
|
3139
|
-
if (!dbPath || !config
|
|
3139
|
+
if (!dbPath || !getTableFactoryConfig(config)) throw invalidConfig(config);
|
|
3140
3140
|
if (!adapters.length) throw new Error(`Database options must not be empty`);
|
|
3141
3141
|
if (!dbPath.endsWith(".ts")) dbPath += ".ts";
|
|
3142
3142
|
let migrationName = args[0] ?? "generated";
|
|
@@ -3206,7 +3206,7 @@ const generate = async (adapters, config, args, afterPull) => {
|
|
|
3206
3206
|
if (up) for (const adapter of adapters) await migrateAndClose(adapter, config);
|
|
3207
3207
|
else if (!afterPull) await closeAdapters(adapters);
|
|
3208
3208
|
};
|
|
3209
|
-
const invalidConfig = (config) => /* @__PURE__ */ new Error(`\`${config.dbPath ? "baseTable" : "dbPath"}\` setting must be set in the migrations config for the generator to work`);
|
|
3209
|
+
const invalidConfig = (config) => /* @__PURE__ */ new Error(`\`${config.dbPath ? "baseTable` or `defineTable" : "dbPath"}\` setting must be set in the migrations config for the generator to work`);
|
|
3210
3210
|
const getDbFromConfig = async (config, dbPath) => {
|
|
3211
3211
|
const db = (await config.import(pathToFileURL(path.resolve(config.basePath, dbPath)).toString()))[config.dbExportedAs ?? "db"];
|
|
3212
3212
|
if (!db?.$qb) throw new Error(`Unable to import OrchidORM instance as ${config.dbExportedAs ?? "db"} from ${config.dbPath}`);
|
|
@@ -3484,84 +3484,119 @@ const processHasAndBelongsToManyColumn = (column, habtmTables, codeItems) => {
|
|
|
3484
3484
|
const closeAdapters = (adapters) => {
|
|
3485
3485
|
return Promise.all(adapters.map((x) => x.close()));
|
|
3486
3486
|
};
|
|
3487
|
-
const
|
|
3487
|
+
const getTableInfos = (asts, config) => {
|
|
3488
3488
|
const generateTableTo = config.generateTableTo ?? ((name) => `./tables/${name}.table.ts`);
|
|
3489
3489
|
const tableInfos = {};
|
|
3490
|
-
const fkeys = {};
|
|
3491
3490
|
for (const ast of asts) if (ast.type === "table") {
|
|
3492
3491
|
const tableKey = toCamelCase(ast.name);
|
|
3493
3492
|
const dbTableName = ast.schema ? `${ast.schema}.${ast.name}` : ast.name;
|
|
3494
3493
|
let tablePath = path.resolve(config.basePath, generateTableTo(tableKey));
|
|
3495
3494
|
if (!tablePath.endsWith(".ts")) tablePath += ".ts";
|
|
3496
3495
|
const name = toPascalCase(ast.name);
|
|
3497
|
-
|
|
3496
|
+
tableInfos[dbTableName] = {
|
|
3498
3497
|
dbTableName,
|
|
3499
3498
|
key: tableKey,
|
|
3500
3499
|
path: tablePath,
|
|
3501
3500
|
name,
|
|
3502
3501
|
className: `${name}Table`
|
|
3503
3502
|
};
|
|
3504
|
-
tableInfos[dbTableName] = info;
|
|
3505
|
-
if (ast.constraints) for (const { references } of ast.constraints) {
|
|
3506
|
-
if (!references) continue;
|
|
3507
|
-
(fkeys[references.fnOrTable] ??= []).push({
|
|
3508
|
-
table: info,
|
|
3509
|
-
references
|
|
3510
|
-
});
|
|
3511
|
-
}
|
|
3512
3503
|
}
|
|
3513
|
-
return
|
|
3514
|
-
tableInfos,
|
|
3515
|
-
fkeys
|
|
3516
|
-
};
|
|
3504
|
+
return tableInfos;
|
|
3517
3505
|
};
|
|
3518
|
-
const appCodeGenTable = (tableInfos,
|
|
3506
|
+
const appCodeGenTable = (tableInfos, ast, tableFactorySource, currentSchema) => {
|
|
3519
3507
|
const tableInfo = tableInfos[ast.schema ? `${ast.schema}.${ast.name}` : ast.name];
|
|
3520
|
-
const
|
|
3521
|
-
|
|
3522
|
-
|
|
3508
|
+
const content = appCodeGenDefineTable(tableInfo, ast, tableFactorySource, currentSchema);
|
|
3509
|
+
return {
|
|
3510
|
+
...tableInfo,
|
|
3511
|
+
content
|
|
3523
3512
|
};
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
if (ast.comment) props.push(`comment = ${singleQuote(ast.comment)};`);
|
|
3528
|
-
if (ast.noPrimaryKey === "ignore") props.push("noPrimaryKey = true;");
|
|
3513
|
+
};
|
|
3514
|
+
const appCodeGenDefineTable = (tableInfo, ast, tableFactorySource, currentSchema) => {
|
|
3515
|
+
const tableOptions = getDefineTableOptions(tableInfo, ast);
|
|
3529
3516
|
const hasTableData = Boolean(ast.primaryKey || ast.indexes?.length || ast.excludes?.length || ast.constraints?.length);
|
|
3530
|
-
const
|
|
3517
|
+
const ctx = {
|
|
3531
3518
|
t: "t",
|
|
3519
|
+
sql: "sql",
|
|
3532
3520
|
table: ast.name,
|
|
3533
3521
|
currentSchema
|
|
3534
|
-
}, ast.shape);
|
|
3535
|
-
props.push(`columns = this.setColumns(${hasTableData ? "\n " : ""}(t) => ({`, hasTableData ? [shapeCode] : shapeCode, hasTableData ? " })," : "}));");
|
|
3536
|
-
if (hasTableData) props.push(pushTableDataCode([], ast), ");");
|
|
3537
|
-
const relations = [];
|
|
3538
|
-
const belongsTo = fkeys[ast.schema ? `${ast.schema}.${ast.name}` : ast.name];
|
|
3539
|
-
if (belongsTo) for (const { table, references } of belongsTo) {
|
|
3540
|
-
imports[getImportPath(tableInfo.path, table.path)] = table.className;
|
|
3541
|
-
relations.push(`${table.key}: this.belongsTo(() => ${table.className}, {`, [`columns: [${references.foreignColumns.map(singleQuote).join(", ")}],`, `references: [${references.columns.map(singleQuote).join(", ")}],`], "}),");
|
|
3542
|
-
}
|
|
3543
|
-
if (ast.constraints) for (const { references } of ast.constraints) {
|
|
3544
|
-
if (!references) continue;
|
|
3545
|
-
const table = tableInfos[references.fnOrTable];
|
|
3546
|
-
imports[getImportPath(tableInfo.path, table.path)] = table.className;
|
|
3547
|
-
relations.push(`${table.key}: this.hasMany(() => ${table.className}, {`, [`columns: [${references.columns.map(singleQuote).join(", ")}],`, `references: [${references.foreignColumns.map(singleQuote).join(", ")}],`], "}),");
|
|
3548
|
-
}
|
|
3549
|
-
if (relations.length) props.push("", "relations = {", relations, "};");
|
|
3550
|
-
const importsCode = importsToCode(imports);
|
|
3551
|
-
const { name, className } = tableInfo;
|
|
3552
|
-
const code = [
|
|
3553
|
-
`export type ${name} = Selectable<${className}>;
|
|
3554
|
-
export type ${name}New = Insertable<${className}>;
|
|
3555
|
-
export type ${name}Update = Updatable<${className}>;
|
|
3556
|
-
|
|
3557
|
-
export class ${className} extends ${baseTableExportedAs} {`,
|
|
3558
|
-
props,
|
|
3559
|
-
"}\n"
|
|
3560
|
-
];
|
|
3561
|
-
return {
|
|
3562
|
-
...tableInfo,
|
|
3563
|
-
content: importsCode + "\n\n" + codeToString(code, "", " ")
|
|
3564
3522
|
};
|
|
3523
|
+
const shapeCode = columnsShapeToCode(ctx, ast.shape);
|
|
3524
|
+
const { name, className } = tableInfo;
|
|
3525
|
+
const code = [`export type ${name} = Selectable<typeof ${className}>;
|
|
3526
|
+
export type ${name}New = Insertable<typeof ${className}>;
|
|
3527
|
+
export type ${name}Update = Updatable<typeof ${className}>;
|
|
3528
|
+
`];
|
|
3529
|
+
if (tableOptions.length) code.push(`export const ${className} = ${tableFactorySource.exportedAs}(`, [
|
|
3530
|
+
`${singleQuote(tableInfo.key)},`,
|
|
3531
|
+
...tableOptions,
|
|
3532
|
+
"(t) => ({",
|
|
3533
|
+
shapeCode,
|
|
3534
|
+
"}),"
|
|
3535
|
+
], `)${hasTableData ? "" : ";"}`);
|
|
3536
|
+
else if (hasTableData && getTableDataItemsCount(ast) === 1) code.push(`export const ${className} = ${tableFactorySource.exportedAs}(`, [
|
|
3537
|
+
`${singleQuote(tableInfo.key)},`,
|
|
3538
|
+
"(t) => ({",
|
|
3539
|
+
shapeCode,
|
|
3540
|
+
"}),"
|
|
3541
|
+
], ")");
|
|
3542
|
+
else code.push(`export const ${className} = ${tableFactorySource.exportedAs}(${singleQuote(tableInfo.key)}, (t) => ({`, shapeCode, `}))${hasTableData ? "" : ";"}`);
|
|
3543
|
+
if (hasTableData) {
|
|
3544
|
+
let tableDataCode = getTableDataChainCode(ast, ctx);
|
|
3545
|
+
if (ast.constraints?.some(({ check }) => check)) tableDataCode = addTrailingSemicolon(tableDataCode);
|
|
3546
|
+
code.push(tableDataCode, ";");
|
|
3547
|
+
}
|
|
3548
|
+
return importsToCode({
|
|
3549
|
+
"orchid-orm": "Selectable, Insertable, Updatable",
|
|
3550
|
+
[getImportPath(tableInfo.path, tableFactorySource.path)]: ctx.isSqlUsed ? `${tableFactorySource.exportedAs}, sql` : tableFactorySource.exportedAs
|
|
3551
|
+
}) + "\n\n" + formatColumnSqlChains(codeToString(code, "", " ")) + "\n";
|
|
3552
|
+
};
|
|
3553
|
+
const getDefineTableOptions = (tableInfo, ast) => {
|
|
3554
|
+
const options = [];
|
|
3555
|
+
if (ast.schema) options.push(`schema: ${singleQuote(ast.schema)},`);
|
|
3556
|
+
if (tableInfo.key !== ast.name) options.push(`nameInDb: ${singleQuote(ast.name)},`);
|
|
3557
|
+
if (ast.comment) options.push(`comment: ${singleQuote(ast.comment)},`);
|
|
3558
|
+
if (ast.noPrimaryKey === "ignore") options.push("noPrimaryKey: true,");
|
|
3559
|
+
return options.length ? [
|
|
3560
|
+
"{",
|
|
3561
|
+
options,
|
|
3562
|
+
"},"
|
|
3563
|
+
] : [];
|
|
3564
|
+
};
|
|
3565
|
+
const getTableDataChainCode = (ast, ctx) => {
|
|
3566
|
+
const code = [];
|
|
3567
|
+
if (ast.primaryKey) code.push(primaryKeyInnerToCode(ast.primaryKey, ""));
|
|
3568
|
+
if (ast.indexes) for (const index of ast.indexes) code.push(...removeTrailingComma(indexToCode(index, "")));
|
|
3569
|
+
if (ast.excludes) for (const exclude of ast.excludes) code.push(...removeTrailingComma(excludeToCode(exclude, "")));
|
|
3570
|
+
if (ast.constraints) for (const constraint of ast.constraints) code.push(...removeTrailingComma(constraintToCode(constraint, "", true, "", ctx)));
|
|
3571
|
+
return code;
|
|
3572
|
+
};
|
|
3573
|
+
const getTableDataItemsCount = (ast) => {
|
|
3574
|
+
return (ast.primaryKey ? 1 : 0) + (ast.indexes?.length ?? 0) + (ast.excludes?.length ?? 0) + (ast.constraints?.length ?? 0);
|
|
3575
|
+
};
|
|
3576
|
+
const removeTrailingComma = (code) => {
|
|
3577
|
+
if (typeof code === "string") return removeComma(code);
|
|
3578
|
+
const copy = [...code];
|
|
3579
|
+
const lastIndex = copy.length - 1;
|
|
3580
|
+
const last = copy[lastIndex];
|
|
3581
|
+
if (last !== void 0) copy[lastIndex] = removeTrailingComma(last);
|
|
3582
|
+
return copy;
|
|
3583
|
+
};
|
|
3584
|
+
const removeComma = (code) => code.endsWith(",") ? code.slice(0, -1) : code;
|
|
3585
|
+
const formatColumnSqlChains = (code) => {
|
|
3586
|
+
return code.replace(/^(\s+\S+: )t((?:\.\w+\([^{}\n]*\))+)\.index\(\{\n((?:\s+[^\n]*\n)*?)(\s+)\}\)(\.check\(sql[^\n]*)$/gm, (line, prefix, chain, options, _closeIndent, check) => {
|
|
3587
|
+
const methodIndent = `${" ".repeat(line.match(/^\s*/)?.[0].length ?? 0)} `;
|
|
3588
|
+
const optionIndent = `${methodIndent} `;
|
|
3589
|
+
const optionLines = options.split("\n").filter(Boolean).map((line) => `${optionIndent}${line.trimStart()}`).join("\n");
|
|
3590
|
+
return `${prefix}t${chain.replace(/\./g, `\n${methodIndent}.`)}\n${methodIndent}.index({\n${optionLines}\n${methodIndent}})\n${methodIndent}${check}`;
|
|
3591
|
+
});
|
|
3592
|
+
};
|
|
3593
|
+
const addTrailingSemicolon = (code) => {
|
|
3594
|
+
if (typeof code === "string") return `${code};`;
|
|
3595
|
+
const copy = [...code];
|
|
3596
|
+
const lastIndex = copy.length - 1;
|
|
3597
|
+
const last = copy[lastIndex];
|
|
3598
|
+
if (last !== void 0) copy[lastIndex] = addTrailingSemicolon(last);
|
|
3599
|
+
return copy;
|
|
3565
3600
|
};
|
|
3566
3601
|
function importsToCode(imports) {
|
|
3567
3602
|
return Object.entries(imports).map(([from, name]) => `import { ${name} } from '${from}';`).join("\n");
|
|
@@ -3673,14 +3708,20 @@ const applyChanges = (content, changes) => {
|
|
|
3673
3708
|
return changes.length ? changes.map((item) => typeof item === "string" ? item : content.slice(item[0], item[1])).join("") : content;
|
|
3674
3709
|
};
|
|
3675
3710
|
const pull = async (adapters, config) => {
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3711
|
+
const { defineTable } = config;
|
|
3712
|
+
if (!config.dbPath || !defineTable) throw new Error(`\`${config.dbPath ? "defineTable" : "dbPath"}\` setting must be set in the migrations config for pull command`);
|
|
3713
|
+
if (!defineTable.types) throw new Error("defineTable is missing types");
|
|
3714
|
+
if (!defineTable.exportAs) throw new Error("defineTable is missing exportAs");
|
|
3715
|
+
if (typeof defineTable.getFilePath !== "function") throw new Error("defineTable is missing getFilePath");
|
|
3716
|
+
const tableFactorySource = {
|
|
3717
|
+
path: defineTable.getFilePath(),
|
|
3718
|
+
exportedAs: defineTable.exportAs
|
|
3719
|
+
};
|
|
3679
3720
|
const [adapter] = adapters;
|
|
3680
3721
|
const adapterSchema = adapter.getSchema();
|
|
3681
3722
|
const currentSchema = (typeof adapterSchema === "function" ? adapterSchema() : adapterSchema) ?? "public";
|
|
3682
3723
|
const asts = await structureToAst(makeStructureToAstCtx(config, currentSchema), adapter, config);
|
|
3683
|
-
const
|
|
3724
|
+
const tableInfos = getTableInfos(asts, config);
|
|
3684
3725
|
const exclusiveWriteOptions = { flag: "wx" };
|
|
3685
3726
|
const pendingFileWrites = [];
|
|
3686
3727
|
const tables = {};
|
|
@@ -3689,7 +3730,7 @@ const pull = async (adapters, config) => {
|
|
|
3689
3730
|
let firstTable;
|
|
3690
3731
|
for (const ast of asts) switch (ast.type) {
|
|
3691
3732
|
case "table": {
|
|
3692
|
-
const table = appCodeGenTable(tableInfos,
|
|
3733
|
+
const table = appCodeGenTable(tableInfos, ast, tableFactorySource, currentSchema);
|
|
3693
3734
|
tables[table.key] = table;
|
|
3694
3735
|
if (!firstTable) firstTable = table;
|
|
3695
3736
|
pendingFileWrites.push([
|