orchid-orm 1.76.5 → 1.77.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/dist/bun.d.ts +7 -18
- package/dist/bun.js +3 -2
- package/dist/bun.js.map +1 -1
- package/dist/bun.mjs +3 -2
- package/dist/bun.mjs.map +1 -1
- package/dist/index.d.ts +884 -158
- package/dist/index.js +636 -44
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +637 -46
- package/dist/index.mjs.map +1 -1
- package/dist/migrations/bun.js.map +1 -1
- package/dist/migrations/bun.mjs.map +1 -1
- package/dist/migrations/index.d.ts +2 -1
- package/dist/migrations/index.js +284 -121
- package/dist/migrations/index.js.map +1 -1
- package/dist/migrations/index.mjs +285 -121
- package/dist/migrations/index.mjs.map +1 -1
- package/dist/migrations/node-postgres.js.map +1 -1
- package/dist/migrations/node-postgres.mjs.map +1 -1
- package/dist/migrations/postgres-js.js.map +1 -1
- package/dist/migrations/postgres-js.mjs.map +1 -1
- package/dist/node-postgres.d.ts +7 -17
- package/dist/node-postgres.js +3 -2
- package/dist/node-postgres.js.map +1 -1
- package/dist/node-postgres.mjs +3 -2
- package/dist/node-postgres.mjs.map +1 -1
- package/dist/postgres-js.d.ts +7 -15
- package/dist/postgres-js.js +3 -2
- package/dist/postgres-js.js.map +1 -1
- package/dist/postgres-js.mjs +3 -2
- package/dist/postgres-js.mjs.map +1 -1
- package/package.json +4 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bun.js","names":[],"sources":["../../src/migrations/adapters/bun.ts"],"sourcesContent":["import { patchRakeDb } from 'orchid-orm/migrations';\nexport * from '../patch-rake-db-types';\nexport * from 'rake-db/bun';\n\npatchRakeDb();\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"bun.js","names":["patchRakeDb"],"sources":["../../src/migrations/adapters/bun.ts"],"sourcesContent":["import { patchRakeDb } from 'orchid-orm/migrations';\nexport * from '../patch-rake-db-types';\nexport * from 'rake-db/bun';\n\npatchRakeDb();\n"],"mappings":"CAIAA,kCAAAA,CAAAA,CAAAA,YAAAA,CAAY"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bun.mjs","names":[],"sources":["../../src/migrations/adapters/bun.ts"],"sourcesContent":["import { patchRakeDb } from 'orchid-orm/migrations';\nexport * from '../patch-rake-db-types';\nexport * from 'rake-db/bun';\n\npatchRakeDb();\n"],"mappings":";;AAIA,
|
|
1
|
+
{"version":3,"file":"bun.mjs","names":[],"sources":["../../src/migrations/adapters/bun.ts"],"sourcesContent":["import { patchRakeDb } from 'orchid-orm/migrations';\nexport * from '../patch-rake-db-types';\nexport * from 'rake-db/bun';\n\npatchRakeDb();\n"],"mappings":";;AAIA,YAAY"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ColumnSchemaConfig } from "pqb/internal";
|
|
2
2
|
export * from "rake-db";
|
|
3
|
+
declare const patchRakeDb$1: () => void;
|
|
3
4
|
declare module 'rake-db' {
|
|
4
5
|
interface RakeDbConfig {
|
|
5
6
|
dbPath?: string;
|
|
@@ -12,5 +13,5 @@ declare module 'rake-db' {
|
|
|
12
13
|
generateTableTo?(tableName: string): string;
|
|
13
14
|
}
|
|
14
15
|
}
|
|
15
|
-
declare const patchRakeDb:
|
|
16
|
+
declare const patchRakeDb: typeof patchRakeDb$1;
|
|
16
17
|
export { patchRakeDb };
|
package/dist/migrations/index.js
CHANGED
|
@@ -15,7 +15,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
15
|
}
|
|
16
16
|
return to;
|
|
17
17
|
};
|
|
18
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
19
19
|
value: mod,
|
|
20
20
|
enumerable: true
|
|
21
21
|
}) : target, mod));
|
|
@@ -26,8 +26,6 @@ node_path = __toESM(node_path);
|
|
|
26
26
|
let node_url = require("node:url");
|
|
27
27
|
let node_fs_promises = require("node:fs/promises");
|
|
28
28
|
node_fs_promises = __toESM(node_fs_promises);
|
|
29
|
-
let typescript = require("typescript");
|
|
30
|
-
typescript = __toESM(typescript);
|
|
31
29
|
const viewDataToSql = (viewData, viewName) => {
|
|
32
30
|
return (0, pqb_internal.sqlToRawSql)(viewDataToQuerySql(viewData, viewName));
|
|
33
31
|
};
|
|
@@ -351,8 +349,9 @@ const compareColumns = async (adapter, domainsMap, ast, currentSchema, compareSq
|
|
|
351
349
|
if (!typeCasts.get(dbBaseType)?.has(codeBaseType)) {
|
|
352
350
|
if (!(dbColumn instanceof pqb_internal.EnumColumn) || !(codeColumn instanceof pqb_internal.EnumColumn) || !(0, pqb_internal.deepCompare)(dbColumn.options, codeColumn.options)) {
|
|
353
351
|
if (verifying) throw new AbortSignal();
|
|
352
|
+
const tableName = (0, rake_db.concatSchemaAndName)(changeTableData.changeTableAst);
|
|
354
353
|
if (await (0, rake_db.promptSelect)({
|
|
355
|
-
message: `Cannot cast type of ${
|
|
354
|
+
message: `Cannot cast type of ${tableName}'s column ${key} from ${dbType} to ${codeType}`,
|
|
356
355
|
options: [`${pqb_internal.colors.yellowBold(`-/+`)} recreate the column, existing data will be ${pqb_internal.colors.red("lost")}`, `write migration manually`]
|
|
357
356
|
})) throw new AbortSignal();
|
|
358
357
|
dbColumn.data.name = codeColumn.data.name;
|
|
@@ -432,7 +431,7 @@ JOIN pg_type AS t ON t.oid = casttarget`);
|
|
|
432
431
|
for (const [source, target] of rows) {
|
|
433
432
|
const set = directTypeCasts.get(source);
|
|
434
433
|
if (set) set.add(target);
|
|
435
|
-
else directTypeCasts.set(source, new Set([target]));
|
|
434
|
+
else directTypeCasts.set(source, /* @__PURE__ */ new Set([target]));
|
|
436
435
|
}
|
|
437
436
|
typeCasts = /* @__PURE__ */ new Map();
|
|
438
437
|
for (const [type, directSet] of directTypeCasts.entries()) {
|
|
@@ -563,7 +562,8 @@ const makeComparableDomain = (currentSchema, schemaName, name, column) => {
|
|
|
563
562
|
inner = inner.data.item;
|
|
564
563
|
arrayDims++;
|
|
565
564
|
}
|
|
566
|
-
const
|
|
565
|
+
const fullType = getColumnDbType(inner, currentSchema);
|
|
566
|
+
const [typeSchema = "pg_catalog", type] = (0, rake_db.getSchemaAndTableFromName)(currentSchema, fullType);
|
|
567
567
|
return {
|
|
568
568
|
schemaName,
|
|
569
569
|
name,
|
|
@@ -802,7 +802,7 @@ const processPrimaryKey = (config, changeTableData) => {
|
|
|
802
802
|
};
|
|
803
803
|
const changePrimaryKey = (config, columnsPrimaryKey, { codeTable, dbTableData: { primaryKey: dbPrimaryKey }, changeTableAst: { shape, add, drop }, changingColumns }) => {
|
|
804
804
|
const tablePrimaryKey = codeTable.internal.tableData.primaryKey;
|
|
805
|
-
const primaryKey = [
|
|
805
|
+
const primaryKey = [.../* @__PURE__ */ new Set([...columnsPrimaryKey, ...(config.snakeCase ? tablePrimaryKey?.columns.map((key) => ({
|
|
806
806
|
key,
|
|
807
807
|
name: (0, pqb_internal.toSnakeCase)(key)
|
|
808
808
|
})) : tablePrimaryKey?.columns.map((key) => ({
|
|
@@ -1302,7 +1302,7 @@ const collectCodeFkeys = (config, { codeTable, changeTableAst: { shape } }, curr
|
|
|
1302
1302
|
};
|
|
1303
1303
|
const fnOrTableToString = (fnOrTable) => {
|
|
1304
1304
|
if (typeof fnOrTable !== "string") {
|
|
1305
|
-
const { schema, table, nameInDb } =
|
|
1305
|
+
const { schema, table, nameInDb } = (0, pqb_internal.getForeignKeyTableInstance)(fnOrTable());
|
|
1306
1306
|
const name = nameInDb || table;
|
|
1307
1307
|
if (!name) throw new Error("Referenced table is missing table property");
|
|
1308
1308
|
fnOrTable = (0, rake_db.concatSchemaAndName)({
|
|
@@ -2210,7 +2210,7 @@ const processDefaultPrivileges = (ast, dbStructure, { internal: { roles } }) =>
|
|
|
2210
2210
|
const codeObj = codePrivilege.objectConfigs.find((o) => o.object === objectType);
|
|
2211
2211
|
const dbPrivs = dbObj?.privilegeConfigs ?? [];
|
|
2212
2212
|
const codePrivs = codeObj?.privilegeConfigs ?? [];
|
|
2213
|
-
const
|
|
2213
|
+
const collapsedDbPrivilege = {
|
|
2214
2214
|
owner: dbPrivilege.owner,
|
|
2215
2215
|
grantee: dbPrivilege.grantee,
|
|
2216
2216
|
schema: dbPrivilege.schema,
|
|
@@ -2218,7 +2218,8 @@ const processDefaultPrivileges = (ast, dbStructure, { internal: { roles } }) =>
|
|
|
2218
2218
|
object: objectType,
|
|
2219
2219
|
privilegeConfigs: dbPrivs
|
|
2220
2220
|
}]
|
|
2221
|
-
}
|
|
2221
|
+
};
|
|
2222
|
+
const collapsedDbPrivs = collapsePrivilegesToAll(collapsedDbPrivilege, objectTypeToAllPrivileges).objectConfigs[0]?.privilegeConfigs ?? [];
|
|
2222
2223
|
const toGrant = codePrivs.filter((cp) => !collapsedDbPrivs.some((dp) => privilegeConfigsMatch(cp, dp, objectType, objectTypeToAllPrivileges)));
|
|
2223
2224
|
const toRevoke = dbPrivs.filter((dp) => !codePrivs.some((cp) => privilegeConfigsMatch(cp, dp, objectType, objectTypeToAllPrivileges)));
|
|
2224
2225
|
if (toGrant.length) {
|
|
@@ -2642,9 +2643,7 @@ const dbViewOptionsToAst = (view) => {
|
|
|
2642
2643
|
case "security_barrier":
|
|
2643
2644
|
options.securityBarrier = value === "true";
|
|
2644
2645
|
break;
|
|
2645
|
-
case "security_invoker":
|
|
2646
|
-
options.securityInvoker = value === "true";
|
|
2647
|
-
break;
|
|
2646
|
+
case "security_invoker": options.securityInvoker = value === "true";
|
|
2648
2647
|
}
|
|
2649
2648
|
}
|
|
2650
2649
|
return options;
|
|
@@ -3069,10 +3068,11 @@ const report = (ast, config, currentSchema) => {
|
|
|
3069
3068
|
break;
|
|
3070
3069
|
}
|
|
3071
3070
|
case "policy": {
|
|
3072
|
-
const
|
|
3071
|
+
const table = dbItemName({
|
|
3073
3072
|
schema: a.schema,
|
|
3074
3073
|
name: a.table
|
|
3075
|
-
}, currentSchema)
|
|
3074
|
+
}, currentSchema);
|
|
3075
|
+
const summary = formatPolicySummary(a, table);
|
|
3076
3076
|
const message = a.action === "create" ? `${green("+ create policy")} ${a.name}: ${summary}` : `${red("- drop policy")} ${a.name}: ${summary}`;
|
|
3077
3077
|
code.push(message);
|
|
3078
3078
|
break;
|
|
@@ -3159,7 +3159,7 @@ const formatPolicyChangeDefinition = (policy) => {
|
|
|
3159
3159
|
var AbortSignal = class extends Error {};
|
|
3160
3160
|
const generate = async (adapters, config, args, afterPull) => {
|
|
3161
3161
|
let { dbPath } = config;
|
|
3162
|
-
if (!dbPath || !
|
|
3162
|
+
if (!dbPath || !(0, rake_db.getTableFactoryConfig)(config)) throw invalidConfig(config);
|
|
3163
3163
|
if (!adapters.length) throw new Error(`Database options must not be empty`);
|
|
3164
3164
|
if (!dbPath.endsWith(".ts")) dbPath += ".ts";
|
|
3165
3165
|
let migrationName = args[0] ?? "generated";
|
|
@@ -3229,7 +3229,7 @@ const generate = async (adapters, config, args, afterPull) => {
|
|
|
3229
3229
|
if (up) for (const adapter of adapters) await (0, rake_db.migrateAndClose)(adapter, config);
|
|
3230
3230
|
else if (!afterPull) await closeAdapters(adapters);
|
|
3231
3231
|
};
|
|
3232
|
-
const invalidConfig = (config) => /* @__PURE__ */ new Error(`\`${config.dbPath ? "baseTable" : "dbPath"}\` setting must be set in the migrations config for the generator to work`);
|
|
3232
|
+
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`);
|
|
3233
3233
|
const getDbFromConfig = async (config, dbPath) => {
|
|
3234
3234
|
const db = (await config.import((0, node_url.pathToFileURL)(node_path.default.resolve(config.basePath, dbPath)).toString()))[config.dbExportedAs ?? "db"];
|
|
3235
3235
|
if (!db?.$qb) throw new Error(`Unable to import OrchidORM instance as ${config.dbExportedAs ?? "db"} from ${config.dbPath}`);
|
|
@@ -3507,95 +3507,128 @@ const processHasAndBelongsToManyColumn = (column, habtmTables, codeItems) => {
|
|
|
3507
3507
|
const closeAdapters = (adapters) => {
|
|
3508
3508
|
return Promise.all(adapters.map((x) => x.close()));
|
|
3509
3509
|
};
|
|
3510
|
-
const
|
|
3510
|
+
const getTableInfos = (asts, config) => {
|
|
3511
3511
|
const generateTableTo = config.generateTableTo ?? ((name) => `./tables/${name}.table.ts`);
|
|
3512
3512
|
const tableInfos = {};
|
|
3513
|
-
const fkeys = {};
|
|
3514
3513
|
for (const ast of asts) if (ast.type === "table") {
|
|
3515
3514
|
const tableKey = (0, pqb_internal.toCamelCase)(ast.name);
|
|
3516
3515
|
const dbTableName = ast.schema ? `${ast.schema}.${ast.name}` : ast.name;
|
|
3517
3516
|
let tablePath = node_path.default.resolve(config.basePath, generateTableTo(tableKey));
|
|
3518
3517
|
if (!tablePath.endsWith(".ts")) tablePath += ".ts";
|
|
3519
3518
|
const name = (0, pqb_internal.toPascalCase)(ast.name);
|
|
3520
|
-
|
|
3519
|
+
tableInfos[dbTableName] = {
|
|
3521
3520
|
dbTableName,
|
|
3522
3521
|
key: tableKey,
|
|
3523
3522
|
path: tablePath,
|
|
3524
3523
|
name,
|
|
3525
3524
|
className: `${name}Table`
|
|
3526
3525
|
};
|
|
3527
|
-
tableInfos[dbTableName] = info;
|
|
3528
|
-
if (ast.constraints) for (const { references } of ast.constraints) {
|
|
3529
|
-
if (!references) continue;
|
|
3530
|
-
(fkeys[references.fnOrTable] ??= []).push({
|
|
3531
|
-
table: info,
|
|
3532
|
-
references
|
|
3533
|
-
});
|
|
3534
|
-
}
|
|
3535
3526
|
}
|
|
3536
|
-
return
|
|
3537
|
-
tableInfos,
|
|
3538
|
-
fkeys
|
|
3539
|
-
};
|
|
3527
|
+
return tableInfos;
|
|
3540
3528
|
};
|
|
3541
|
-
const appCodeGenTable = (tableInfos,
|
|
3529
|
+
const appCodeGenTable = (tableInfos, ast, tableFactorySource, currentSchema) => {
|
|
3542
3530
|
const tableInfo = tableInfos[ast.schema ? `${ast.schema}.${ast.name}` : ast.name];
|
|
3543
|
-
const
|
|
3544
|
-
|
|
3545
|
-
|
|
3531
|
+
const content = appCodeGenDefineTable(tableInfo, ast, tableFactorySource, currentSchema);
|
|
3532
|
+
return {
|
|
3533
|
+
...tableInfo,
|
|
3534
|
+
content
|
|
3546
3535
|
};
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
if (ast.comment) props.push(`comment = ${(0, pqb_internal.singleQuote)(ast.comment)};`);
|
|
3551
|
-
if (ast.noPrimaryKey === "ignore") props.push("noPrimaryKey = true;");
|
|
3536
|
+
};
|
|
3537
|
+
const appCodeGenDefineTable = (tableInfo, ast, tableFactorySource, currentSchema) => {
|
|
3538
|
+
const tableOptions = getDefineTableOptions(tableInfo, ast);
|
|
3552
3539
|
const hasTableData = Boolean(ast.primaryKey || ast.indexes?.length || ast.excludes?.length || ast.constraints?.length);
|
|
3553
|
-
const
|
|
3540
|
+
const ctx = {
|
|
3554
3541
|
t: "t",
|
|
3542
|
+
sql: "sql",
|
|
3555
3543
|
table: ast.name,
|
|
3556
3544
|
currentSchema
|
|
3557
|
-
}, ast.shape);
|
|
3558
|
-
props.push(`columns = this.setColumns(${hasTableData ? "\n " : ""}(t) => ({`, hasTableData ? [shapeCode] : shapeCode, hasTableData ? " })," : "}));");
|
|
3559
|
-
if (hasTableData) props.push((0, pqb_internal.pushTableDataCode)([], ast), ");");
|
|
3560
|
-
const relations = [];
|
|
3561
|
-
const belongsTo = fkeys[ast.schema ? `${ast.schema}.${ast.name}` : ast.name];
|
|
3562
|
-
if (belongsTo) for (const { table, references } of belongsTo) {
|
|
3563
|
-
imports[(0, pqb_internal.getImportPath)(tableInfo.path, table.path)] = table.className;
|
|
3564
|
-
relations.push(`${table.key}: this.belongsTo(() => ${table.className}, {`, [`columns: [${references.foreignColumns.map(pqb_internal.singleQuote).join(", ")}],`, `references: [${references.columns.map(pqb_internal.singleQuote).join(", ")}],`], "}),");
|
|
3565
|
-
}
|
|
3566
|
-
if (ast.constraints) for (const { references } of ast.constraints) {
|
|
3567
|
-
if (!references) continue;
|
|
3568
|
-
const table = tableInfos[references.fnOrTable];
|
|
3569
|
-
imports[(0, pqb_internal.getImportPath)(tableInfo.path, table.path)] = table.className;
|
|
3570
|
-
relations.push(`${table.key}: this.hasMany(() => ${table.className}, {`, [`columns: [${references.columns.map(pqb_internal.singleQuote).join(", ")}],`, `references: [${references.foreignColumns.map(pqb_internal.singleQuote).join(", ")}],`], "}),");
|
|
3571
|
-
}
|
|
3572
|
-
if (relations.length) props.push("", "relations = {", relations, "};");
|
|
3573
|
-
const importsCode = importsToCode(imports);
|
|
3574
|
-
const { name, className } = tableInfo;
|
|
3575
|
-
const code = [
|
|
3576
|
-
`export type ${name} = Selectable<${className}>;
|
|
3577
|
-
export type ${name}New = Insertable<${className}>;
|
|
3578
|
-
export type ${name}Update = Updatable<${className}>;
|
|
3579
|
-
|
|
3580
|
-
export class ${className} extends ${baseTableExportedAs} {`,
|
|
3581
|
-
props,
|
|
3582
|
-
"}\n"
|
|
3583
|
-
];
|
|
3584
|
-
return {
|
|
3585
|
-
...tableInfo,
|
|
3586
|
-
content: importsCode + "\n\n" + (0, pqb_internal.codeToString)(code, "", " ")
|
|
3587
3545
|
};
|
|
3546
|
+
const shapeCode = (0, pqb_internal.columnsShapeToCode)(ctx, ast.shape);
|
|
3547
|
+
const { name, className } = tableInfo;
|
|
3548
|
+
const code = [`export type ${name} = Selectable<typeof ${className}>;
|
|
3549
|
+
export type ${name}New = Insertable<typeof ${className}>;
|
|
3550
|
+
export type ${name}Update = Updatable<typeof ${className}>;
|
|
3551
|
+
`];
|
|
3552
|
+
if (tableOptions.length) code.push(`export const ${className} = ${tableFactorySource.exportedAs}(`, [
|
|
3553
|
+
`${(0, pqb_internal.singleQuote)(tableInfo.key)},`,
|
|
3554
|
+
...tableOptions,
|
|
3555
|
+
"(t) => ({",
|
|
3556
|
+
shapeCode,
|
|
3557
|
+
"}),"
|
|
3558
|
+
], `)${hasTableData ? "" : ";"}`);
|
|
3559
|
+
else if (hasTableData && getTableDataItemsCount(ast) === 1) code.push(`export const ${className} = ${tableFactorySource.exportedAs}(`, [
|
|
3560
|
+
`${(0, pqb_internal.singleQuote)(tableInfo.key)},`,
|
|
3561
|
+
"(t) => ({",
|
|
3562
|
+
shapeCode,
|
|
3563
|
+
"}),"
|
|
3564
|
+
], ")");
|
|
3565
|
+
else code.push(`export const ${className} = ${tableFactorySource.exportedAs}(${(0, pqb_internal.singleQuote)(tableInfo.key)}, (t) => ({`, shapeCode, `}))${hasTableData ? "" : ";"}`);
|
|
3566
|
+
if (hasTableData) {
|
|
3567
|
+
let tableDataCode = getTableDataChainCode(ast, ctx);
|
|
3568
|
+
if (ast.constraints?.some(({ check }) => check)) tableDataCode = addTrailingSemicolon(tableDataCode);
|
|
3569
|
+
code.push(tableDataCode, ";");
|
|
3570
|
+
}
|
|
3571
|
+
return importsToCode({
|
|
3572
|
+
"orchid-orm": "Selectable, Insertable, Updatable",
|
|
3573
|
+
[(0, pqb_internal.getImportPath)(tableInfo.path, tableFactorySource.path)]: ctx.isSqlUsed ? `${tableFactorySource.exportedAs}, sql` : tableFactorySource.exportedAs
|
|
3574
|
+
}) + "\n\n" + formatColumnSqlChains((0, pqb_internal.codeToString)(code, "", " ")) + "\n";
|
|
3575
|
+
};
|
|
3576
|
+
const getDefineTableOptions = (tableInfo, ast) => {
|
|
3577
|
+
const options = [];
|
|
3578
|
+
if (ast.schema) options.push(`schema: ${(0, pqb_internal.singleQuote)(ast.schema)},`);
|
|
3579
|
+
if (tableInfo.key !== ast.name) options.push(`nameInDb: ${(0, pqb_internal.singleQuote)(ast.name)},`);
|
|
3580
|
+
if (ast.comment) options.push(`comment: ${(0, pqb_internal.singleQuote)(ast.comment)},`);
|
|
3581
|
+
if (ast.noPrimaryKey === "ignore") options.push("noPrimaryKey: true,");
|
|
3582
|
+
return options.length ? [
|
|
3583
|
+
"{",
|
|
3584
|
+
options,
|
|
3585
|
+
"},"
|
|
3586
|
+
] : [];
|
|
3587
|
+
};
|
|
3588
|
+
const getTableDataChainCode = (ast, ctx) => {
|
|
3589
|
+
const code = [];
|
|
3590
|
+
if (ast.primaryKey) code.push((0, pqb_internal.primaryKeyInnerToCode)(ast.primaryKey, ""));
|
|
3591
|
+
if (ast.indexes) for (const index of ast.indexes) code.push(...removeTrailingComma((0, pqb_internal.indexToCode)(index, "")));
|
|
3592
|
+
if (ast.excludes) for (const exclude of ast.excludes) code.push(...removeTrailingComma((0, pqb_internal.excludeToCode)(exclude, "")));
|
|
3593
|
+
if (ast.constraints) for (const constraint of ast.constraints) code.push(...removeTrailingComma((0, pqb_internal.constraintToCode)(constraint, "", true, "", ctx)));
|
|
3594
|
+
return code;
|
|
3595
|
+
};
|
|
3596
|
+
const getTableDataItemsCount = (ast) => {
|
|
3597
|
+
return (ast.primaryKey ? 1 : 0) + (ast.indexes?.length ?? 0) + (ast.excludes?.length ?? 0) + (ast.constraints?.length ?? 0);
|
|
3598
|
+
};
|
|
3599
|
+
const removeTrailingComma = (code) => {
|
|
3600
|
+
if (typeof code === "string") return removeComma(code);
|
|
3601
|
+
const copy = [...code];
|
|
3602
|
+
const lastIndex = copy.length - 1;
|
|
3603
|
+
const last = copy[lastIndex];
|
|
3604
|
+
if (last !== void 0) copy[lastIndex] = removeTrailingComma(last);
|
|
3605
|
+
return copy;
|
|
3606
|
+
};
|
|
3607
|
+
const removeComma = (code) => code.endsWith(",") ? code.slice(0, -1) : code;
|
|
3608
|
+
const formatColumnSqlChains = (code) => {
|
|
3609
|
+
return code.replace(/^(\s+\S+: )t((?:\.\w+\([^{}\n]*\))+)\.index\(\{\n((?:\s+[^\n]*\n)*?)(\s+)\}\)(\.check\(sql[^\n]*)$/gm, (line, prefix, chain, options, _closeIndent, check) => {
|
|
3610
|
+
const methodIndent = `${" ".repeat(line.match(/^\s*/)?.[0].length ?? 0)} `;
|
|
3611
|
+
const optionIndent = `${methodIndent} `;
|
|
3612
|
+
const optionLines = options.split("\n").filter(Boolean).map((line) => `${optionIndent}${line.trimStart()}`).join("\n");
|
|
3613
|
+
return `${prefix}t${chain.replace(/\./g, `\n${methodIndent}.`)}\n${methodIndent}.index({\n${optionLines}\n${methodIndent}})\n${methodIndent}${check}`;
|
|
3614
|
+
});
|
|
3615
|
+
};
|
|
3616
|
+
const addTrailingSemicolon = (code) => {
|
|
3617
|
+
if (typeof code === "string") return `${code};`;
|
|
3618
|
+
const copy = [...code];
|
|
3619
|
+
const lastIndex = copy.length - 1;
|
|
3620
|
+
const last = copy[lastIndex];
|
|
3621
|
+
if (last !== void 0) copy[lastIndex] = addTrailingSemicolon(last);
|
|
3622
|
+
return copy;
|
|
3588
3623
|
};
|
|
3589
3624
|
function importsToCode(imports) {
|
|
3590
3625
|
return Object.entries(imports).map(([from, name]) => `import { ${name} } from '${from}';`).join("\n");
|
|
3591
3626
|
}
|
|
3592
|
-
const { createSourceFile, ScriptTarget, SyntaxKind } = typescript.default;
|
|
3593
3627
|
const appCodeGenUpdateDbFile = async (dbPath, tables, extensions, domains, currentSchema) => {
|
|
3594
3628
|
const content = await node_fs_promises.default.readFile(dbPath, "utf-8");
|
|
3595
|
-
const
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
const { config, tablesList } = getOrchidOrmArgs(importName, statements);
|
|
3629
|
+
const importInfo = getOrchidOrmImport(content);
|
|
3630
|
+
if (!importInfo) throw new Error(`Main file does not contain import of orchid-orm`);
|
|
3631
|
+
const { config, tablesList } = getOrchidOrmArgs(content, importInfo.importName);
|
|
3599
3632
|
const changes = [];
|
|
3600
3633
|
let replacedConfig;
|
|
3601
3634
|
if (extensions.length || domains.length) {
|
|
@@ -3611,32 +3644,18 @@ const appCodeGenUpdateDbFile = async (dbPath, tables, extensions, domains, curre
|
|
|
3611
3644
|
}, ast.baseType.data.name ?? "")},`).join("\n ")}\n },`;
|
|
3612
3645
|
replacedConfig = code + "\n}";
|
|
3613
3646
|
}
|
|
3614
|
-
const tablesChanges = makeTablesListChanges(content,
|
|
3647
|
+
const tablesChanges = makeTablesListChanges(content, importInfo.lastImportEnd, tablesList, tables, dbPath);
|
|
3615
3648
|
if (tablesChanges) addChange(content, changes, tablesChanges.imports.pos, tablesChanges.imports.text);
|
|
3616
3649
|
if (replacedConfig) replaceContent(content, changes, config.pos, config.end, replacedConfig);
|
|
3617
3650
|
if (tablesChanges) addChange(content, changes, tablesChanges.tablesList.pos, tablesChanges.tablesList.text);
|
|
3618
3651
|
return applyChanges(content, changes);
|
|
3619
3652
|
};
|
|
3620
|
-
const
|
|
3621
|
-
return createSourceFile("file.ts", content, ScriptTarget.Latest, true).statements;
|
|
3622
|
-
};
|
|
3623
|
-
const getOrchidOrmImportName = (statements) => {
|
|
3624
|
-
for (const node of statements) {
|
|
3625
|
-
if (node.kind !== SyntaxKind.ImportDeclaration) continue;
|
|
3626
|
-
const imp = node;
|
|
3627
|
-
if (imp.moduleSpecifier.getText().slice(1, -1) !== "orchid-orm") continue;
|
|
3628
|
-
if (!imp.importClause) continue;
|
|
3629
|
-
const elements = imp.importClause.namedBindings?.elements;
|
|
3630
|
-
if (!elements);
|
|
3631
|
-
for (const element of elements) if (element.name.escapedText === "orchidORM" || element.propertyName && "escapedText" in element.propertyName && element.propertyName.escapedText === "orchidORM") return element.name.escapedText.toString();
|
|
3632
|
-
}
|
|
3633
|
-
};
|
|
3634
|
-
const makeTablesListChanges = (content, statements, object, tables, dbPath) => {
|
|
3653
|
+
const makeTablesListChanges = (content, importPos, object, tables, dbPath) => {
|
|
3635
3654
|
const spaces = getTablesListSpaces(content, object);
|
|
3636
3655
|
let imports = "";
|
|
3637
3656
|
let tablesList = "";
|
|
3638
|
-
const prependComma = object.
|
|
3639
|
-
const tablesListNewLine = content.slice(object.
|
|
3657
|
+
const prependComma = object.hasProperties && !object.hasTrailingComma;
|
|
3658
|
+
const tablesListNewLine = content.slice(object.propertiesEnd, object.end).includes("\n");
|
|
3640
3659
|
const tablesArr = Object.values(tables);
|
|
3641
3660
|
for (let i = 0; i < tablesArr.length; i++) {
|
|
3642
3661
|
const { path, className, key } = tablesArr[i];
|
|
@@ -3646,15 +3665,13 @@ const makeTablesListChanges = (content, statements, object, tables, dbPath) => {
|
|
|
3646
3665
|
if (i === tablesArr.length - 1 && !tablesListNewLine) tablesList += `\n${spaces}`;
|
|
3647
3666
|
}
|
|
3648
3667
|
if (!imports.length) return;
|
|
3649
|
-
let importPos = 0;
|
|
3650
|
-
for (const node of statements) if (node.kind === SyntaxKind.ImportDeclaration) importPos = node.end;
|
|
3651
3668
|
return {
|
|
3652
3669
|
imports: {
|
|
3653
3670
|
pos: importPos,
|
|
3654
3671
|
text: imports
|
|
3655
3672
|
},
|
|
3656
3673
|
tablesList: {
|
|
3657
|
-
pos: object.
|
|
3674
|
+
pos: object.propertiesEnd,
|
|
3658
3675
|
text: tablesList
|
|
3659
3676
|
}
|
|
3660
3677
|
};
|
|
@@ -3663,24 +3680,165 @@ const getTablesListSpaces = (content, object) => {
|
|
|
3663
3680
|
const lines = content.slice(0, object.end).split("\n");
|
|
3664
3681
|
return lines[lines.length - 1].match(/^\s+/)?.[0] || "";
|
|
3665
3682
|
};
|
|
3666
|
-
const getOrchidOrmArgs = (
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3683
|
+
const getOrchidOrmArgs = (content, importName) => {
|
|
3684
|
+
const call = findCall(content, importName);
|
|
3685
|
+
if (!call) throw new Error("List of tables is not found in main file");
|
|
3686
|
+
const closeParen = findClosingBracket(content, call.openParen);
|
|
3687
|
+
if (closeParen === -1) throw new Error("List of tables is not found in main file");
|
|
3688
|
+
const firstComma = findTopLevelComma(content, call.openParen + 1, closeParen);
|
|
3689
|
+
if (firstComma === -1) throw new Error("Invalid number of arguments when initializing orchid orm");
|
|
3690
|
+
if (findTopLevelComma(content, firstComma + 1, closeParen) !== -1) throw new Error("Invalid number of arguments when initializing orchid orm");
|
|
3691
|
+
const config = makeTrimmedRange(content, call.openParen + 1, firstComma);
|
|
3692
|
+
const tablesList = getObjectRange(content, firstComma + 1, closeParen);
|
|
3693
|
+
if (!tablesList) throw new Error("Second argument of orchidORM must be an object literal");
|
|
3694
|
+
return {
|
|
3695
|
+
config,
|
|
3696
|
+
tablesList
|
|
3697
|
+
};
|
|
3698
|
+
};
|
|
3699
|
+
const getOrchidOrmImport = (content) => {
|
|
3700
|
+
let lastImportEnd = 0;
|
|
3701
|
+
let importName;
|
|
3702
|
+
const importRegex = /(^|\n)\s*import\s+([\s\S]*?)\s+from\s+['"]([^'"]+)['"]\s*;?/g;
|
|
3703
|
+
let match;
|
|
3704
|
+
while (match = importRegex.exec(content)) {
|
|
3705
|
+
lastImportEnd = importRegex.lastIndex;
|
|
3706
|
+
if (match[3] !== "orchid-orm") continue;
|
|
3707
|
+
const named = match[2].match(/\{([\s\S]*)\}/);
|
|
3708
|
+
if (!named) continue;
|
|
3709
|
+
for (const part of named[1].split(",")) {
|
|
3710
|
+
const item = part.trim();
|
|
3711
|
+
const alias = item.match(/^orchidORM\s+as\s+([A-Za-z_$][\w$]*)$/);
|
|
3712
|
+
if (alias) {
|
|
3713
|
+
importName = alias[1];
|
|
3714
|
+
continue;
|
|
3715
|
+
}
|
|
3716
|
+
if (item === "orchidORM") importName = "orchidORM";
|
|
3680
3717
|
}
|
|
3681
3718
|
}
|
|
3719
|
+
if (!importName) return;
|
|
3720
|
+
return {
|
|
3721
|
+
importName,
|
|
3722
|
+
lastImportEnd
|
|
3723
|
+
};
|
|
3724
|
+
};
|
|
3725
|
+
const findCall = (content, importName) => {
|
|
3726
|
+
let index = 0;
|
|
3727
|
+
while (index < content.length) {
|
|
3728
|
+
const found = content.indexOf(importName, index);
|
|
3729
|
+
if (found === -1) return;
|
|
3730
|
+
const before = content[found - 1];
|
|
3731
|
+
const after = content[found + importName.length];
|
|
3732
|
+
if ((!before || !isIdentifierChar(before)) && (!after || !isIdentifierChar(after))) {
|
|
3733
|
+
const openParen = skipWhitespace(content, found + importName.length);
|
|
3734
|
+
if (content[openParen] === "(") return { openParen };
|
|
3735
|
+
}
|
|
3736
|
+
index = found + importName.length;
|
|
3737
|
+
}
|
|
3682
3738
|
throw new Error("List of tables is not found in main file");
|
|
3683
3739
|
};
|
|
3740
|
+
const getObjectRange = (content, from, to) => {
|
|
3741
|
+
const pos = skipWhitespace(content, from);
|
|
3742
|
+
if (content[pos] !== "{") return;
|
|
3743
|
+
const end = findClosingBracket(content, pos);
|
|
3744
|
+
if (end === -1 || skipWhitespace(content, end + 1) < to) return;
|
|
3745
|
+
const lastBodyChar = findLastNonWhitespace(content, pos + 1, end);
|
|
3746
|
+
const hasProperties = lastBodyChar !== -1;
|
|
3747
|
+
const hasTrailingComma = hasProperties && content[lastBodyChar] === ",";
|
|
3748
|
+
const propertiesEnd = hasProperties ? lastBodyChar + 1 : pos + 1;
|
|
3749
|
+
return {
|
|
3750
|
+
pos,
|
|
3751
|
+
end: end + 1,
|
|
3752
|
+
propertiesEnd,
|
|
3753
|
+
hasProperties,
|
|
3754
|
+
hasTrailingComma
|
|
3755
|
+
};
|
|
3756
|
+
};
|
|
3757
|
+
const makeTrimmedRange = (content, from, to) => {
|
|
3758
|
+
return {
|
|
3759
|
+
pos: skipWhitespace(content, from),
|
|
3760
|
+
end: trimWhitespaceEnd(content, from, to)
|
|
3761
|
+
};
|
|
3762
|
+
};
|
|
3763
|
+
const findTopLevelComma = (content, from, to) => {
|
|
3764
|
+
let depth = 0;
|
|
3765
|
+
for (let i = from; i < to; i++) {
|
|
3766
|
+
const skipped = skipCodeFragment(content, i);
|
|
3767
|
+
if (skipped !== i) {
|
|
3768
|
+
i = skipped - 1;
|
|
3769
|
+
continue;
|
|
3770
|
+
}
|
|
3771
|
+
const char = content[i];
|
|
3772
|
+
if (char === "(" || char === "{" || char === "[") depth++;
|
|
3773
|
+
else if (char === ")" || char === "}" || char === "]") depth--;
|
|
3774
|
+
else if (char === "," && depth === 0) return i;
|
|
3775
|
+
}
|
|
3776
|
+
return -1;
|
|
3777
|
+
};
|
|
3778
|
+
const findClosingBracket = (content, open) => {
|
|
3779
|
+
const close = getClosingBracket(content[open]);
|
|
3780
|
+
if (!close) return -1;
|
|
3781
|
+
let depth = 1;
|
|
3782
|
+
for (let i = open + 1; i < content.length; i++) {
|
|
3783
|
+
const skipped = skipCodeFragment(content, i);
|
|
3784
|
+
if (skipped !== i) {
|
|
3785
|
+
i = skipped - 1;
|
|
3786
|
+
continue;
|
|
3787
|
+
}
|
|
3788
|
+
const char = content[i];
|
|
3789
|
+
if (char === content[open]) depth++;
|
|
3790
|
+
else if (char === close) {
|
|
3791
|
+
depth--;
|
|
3792
|
+
if (depth === 0) return i;
|
|
3793
|
+
}
|
|
3794
|
+
}
|
|
3795
|
+
return -1;
|
|
3796
|
+
};
|
|
3797
|
+
const getClosingBracket = (char) => {
|
|
3798
|
+
if (char === "(") return ")";
|
|
3799
|
+
if (char === "{") return "}";
|
|
3800
|
+
if (char === "[") return "]";
|
|
3801
|
+
};
|
|
3802
|
+
const skipCodeFragment = (content, i) => {
|
|
3803
|
+
const char = content[i];
|
|
3804
|
+
if (char === "'" || char === "\"" || char === "`") return skipQuoted(content, i, char);
|
|
3805
|
+
if (char === "/" && content[i + 1] === "/") {
|
|
3806
|
+
const nextLine = content.indexOf("\n", i + 2);
|
|
3807
|
+
return nextLine === -1 ? content.length : nextLine + 1;
|
|
3808
|
+
}
|
|
3809
|
+
if (char === "/" && content[i + 1] === "*") {
|
|
3810
|
+
const end = content.indexOf("*/", i + 2);
|
|
3811
|
+
return end === -1 ? content.length : end + 2;
|
|
3812
|
+
}
|
|
3813
|
+
return i;
|
|
3814
|
+
};
|
|
3815
|
+
const skipQuoted = (content, i, quote) => {
|
|
3816
|
+
for (let j = i + 1; j < content.length; j++) {
|
|
3817
|
+
if (content[j] === "\\") {
|
|
3818
|
+
j++;
|
|
3819
|
+
continue;
|
|
3820
|
+
}
|
|
3821
|
+
if (content[j] === quote) return j + 1;
|
|
3822
|
+
}
|
|
3823
|
+
return content.length;
|
|
3824
|
+
};
|
|
3825
|
+
const skipWhitespace = (content, from) => {
|
|
3826
|
+
let i = from;
|
|
3827
|
+
while (/\s/.test(content[i])) i++;
|
|
3828
|
+
return i;
|
|
3829
|
+
};
|
|
3830
|
+
const trimWhitespaceEnd = (content, from, to) => {
|
|
3831
|
+
let i = to;
|
|
3832
|
+
while (i > from && /\s/.test(content[i - 1])) i--;
|
|
3833
|
+
return i;
|
|
3834
|
+
};
|
|
3835
|
+
const findLastNonWhitespace = (content, from, to) => {
|
|
3836
|
+
for (let i = to - 1; i >= from; i--) if (!/\s/.test(content[i])) return i;
|
|
3837
|
+
return -1;
|
|
3838
|
+
};
|
|
3839
|
+
const isIdentifierChar = (char) => {
|
|
3840
|
+
return /[A-Za-z0-9_$]/.test(char);
|
|
3841
|
+
};
|
|
3684
3842
|
const addChange = (content, changes, at, text, end = at) => {
|
|
3685
3843
|
if (changes.length === 0) changes.push([0, at], text, [end, content.length]);
|
|
3686
3844
|
else {
|
|
@@ -3696,14 +3854,21 @@ const applyChanges = (content, changes) => {
|
|
|
3696
3854
|
return changes.length ? changes.map((item) => typeof item === "string" ? item : content.slice(item[0], item[1])).join("") : content;
|
|
3697
3855
|
};
|
|
3698
3856
|
const pull = async (adapters, config) => {
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3857
|
+
const { defineTable } = config;
|
|
3858
|
+
if (!config.dbPath || !defineTable) throw new Error(`\`${config.dbPath ? "defineTable" : "dbPath"}\` setting must be set in the migrations config for pull command`);
|
|
3859
|
+
if (!defineTable.types) throw new Error("defineTable is missing types");
|
|
3860
|
+
if (!defineTable.exportAs) throw new Error("defineTable is missing exportAs");
|
|
3861
|
+
if (typeof defineTable.getFilePath !== "function") throw new Error("defineTable is missing getFilePath");
|
|
3862
|
+
const tableFactorySource = {
|
|
3863
|
+
path: defineTable.getFilePath(),
|
|
3864
|
+
exportedAs: defineTable.exportAs
|
|
3865
|
+
};
|
|
3702
3866
|
const [adapter] = adapters;
|
|
3703
3867
|
const adapterSchema = adapter.getSchema();
|
|
3704
3868
|
const currentSchema = (typeof adapterSchema === "function" ? adapterSchema() : adapterSchema) ?? "public";
|
|
3705
|
-
const
|
|
3706
|
-
const
|
|
3869
|
+
const ctx = (0, rake_db.makeStructureToAstCtx)(config, currentSchema);
|
|
3870
|
+
const asts = await (0, rake_db.structureToAst)(ctx, adapter, config);
|
|
3871
|
+
const tableInfos = getTableInfos(asts, config);
|
|
3707
3872
|
const exclusiveWriteOptions = { flag: "wx" };
|
|
3708
3873
|
const pendingFileWrites = [];
|
|
3709
3874
|
const tables = {};
|
|
@@ -3712,7 +3877,7 @@ const pull = async (adapters, config) => {
|
|
|
3712
3877
|
let firstTable;
|
|
3713
3878
|
for (const ast of asts) switch (ast.type) {
|
|
3714
3879
|
case "table": {
|
|
3715
|
-
const table = appCodeGenTable(tableInfos,
|
|
3880
|
+
const table = appCodeGenTable(tableInfos, ast, tableFactorySource, currentSchema);
|
|
3716
3881
|
tables[table.key] = table;
|
|
3717
3882
|
if (!firstTable) firstTable = table;
|
|
3718
3883
|
pendingFileWrites.push([
|
|
@@ -3728,9 +3893,7 @@ const pull = async (adapters, config) => {
|
|
|
3728
3893
|
version: ast.version
|
|
3729
3894
|
});
|
|
3730
3895
|
break;
|
|
3731
|
-
case "domain":
|
|
3732
|
-
domains.push(ast);
|
|
3733
|
-
break;
|
|
3896
|
+
case "domain": domains.push(ast);
|
|
3734
3897
|
}
|
|
3735
3898
|
if (!firstTable && !extensions.length && !domains.length) {
|
|
3736
3899
|
await adapter.close();
|