orchid-orm 1.38.0 → 1.38.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/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Query, SelectableFromShape, CreateMethodsNames, CreateData, CreateBelongsToData, AddQueryDefaults, RelationConfigBase, SetQueryReturnsOne, SetQueryReturnsOneOptional, UpdateData, WhereArg, JoinQueryMethod, DeleteMethodsNames, Db, IsolationLevel, TransactionOptions, Adapter, FromArg, FromResult, AdapterOptions, DbSharedOptions, RelationsBase, ShapeColumnPrimaryKeys, ShapeUniqueColumns, TableDataItemsUniqueColumns, TableDataItemsUniqueColumnTuples, UniqueConstraints, TableDataItemsUniqueConstraints, ComputedColumnsFromOptions, MapTableScopesOption, TableDataItem, ComputedOptionsFactory, QueryData, TableDataFn, DbTableOptionScopes, RawSQL, DynamicRawSQL, DefaultSchemaConfig, DefaultColumnTypes, QueryBeforeHook, QueryAfterHook, AfterHook, WhereResult, MergeQuery } from 'pqb';
1
+ import { Query, TableData, SelectableFromShape, CreateMethodsNames, CreateData, CreateBelongsToData, AddQueryDefaults, RelationConfigBase, SetQueryReturnsOne, SetQueryReturnsOneOptional, UpdateData, WhereArg, JoinQueryMethod, DeleteMethodsNames, Db, IsolationLevel, TransactionOptions, Adapter, FromArg, FromResult, AdapterOptions, DbSharedOptions, RelationsBase, ShapeColumnPrimaryKeys, ShapeUniqueColumns, TableDataItemsUniqueColumns, TableDataItemsUniqueColumnTuples, UniqueConstraints, TableDataItemsUniqueConstraints, ComputedColumnsFromOptions, MapTableScopesOption, TableDataItem, ComputedOptionsFactory, QueryData, TableDataFn, DbTableOptionScopes, RawSQL, DynamicRawSQL, DefaultSchemaConfig, DefaultColumnTypes, QueryBeforeHook, QueryAfterHook, AfterHook, WhereResult, MergeQuery } from 'pqb';
2
2
  export * from 'pqb';
3
3
  import { ColumnsShapeBase, EmptyObject, MaybeArray, RecordUnknown, ShallowSimplify, ColumnShapeOutput, DefaultSelectColumns, ColumnShapeInput, ColumnShapeInputPartial, IsQuery, CoreQueryScopes, ColumnSchemaConfig, StaticSQLArgs, QueryColumn, DynamicSQLArg, QueryColumns, QueryReturnType } from 'orchid-core';
4
4
  export * from 'orchid-core';
@@ -10,6 +10,7 @@ interface RelationCommonOptions<Related extends TableClass = TableClass, Scope e
10
10
  interface RelationRefsOptions<Column extends PropertyKey = string, Ref extends PropertyKey = string> {
11
11
  columns: Column[];
12
12
  references: Ref[];
13
+ foreignKey?: boolean | TableData.References.Options;
13
14
  }
14
15
  interface RelationThroughOptions<Through extends PropertyKey = string, Source extends PropertyKey = string> {
15
16
  through: Through;
@@ -294,10 +295,12 @@ interface HasAndBelongsToManyOptions<Columns extends ColumnsShapeBase = ColumnsS
294
295
  required?: boolean;
295
296
  columns: (keyof Columns)[];
296
297
  references: string[];
298
+ foreignKey?: boolean | TableData.References.Options;
297
299
  through: {
298
300
  table: string;
299
301
  columns: string[];
300
302
  references: (keyof InstanceType<Related>['columns']['shape'])[];
303
+ foreignKey?: boolean | TableData.References.Options;
301
304
  };
302
305
  }
303
306
  type HasAndBelongsToManyParams<T extends RelationConfigSelf, Relation extends HasAndBelongsToMany> = {
@@ -453,6 +456,7 @@ interface ORMTableInput {
453
456
  scopes?: RecordUnknown;
454
457
  readonly softDelete?: true | string;
455
458
  comment?: string;
459
+ autoForeignKeys?: TableData.References.BaseOptions;
456
460
  }
457
461
  type Queryable<T extends ORMTableInput> = ShallowSimplify<{
458
462
  [K in keyof T['columns']['shape']]?: T['columns']['shape'][K]['queryType'];
@@ -679,7 +683,7 @@ interface BaseTableClass<SchemaConfig extends ColumnSchemaConfig, ColumnTypes> {
679
683
  */
680
684
  updateSchema: SchemaConfig['updateSchema'];
681
685
  }
682
- declare function createBaseTable<SchemaConfig extends ColumnSchemaConfig = DefaultSchemaConfig, ColumnTypes = DefaultColumnTypes<SchemaConfig>>({ schemaConfig, columnTypes: columnTypesArg, snakeCase, filePath: filePathArg, nowSQL, exportAs, language, }?: {
686
+ declare function createBaseTable<SchemaConfig extends ColumnSchemaConfig = DefaultSchemaConfig, ColumnTypes = DefaultColumnTypes<SchemaConfig>>({ schemaConfig, columnTypes: columnTypesArg, snakeCase, filePath: filePathArg, nowSQL, exportAs, language, autoForeignKeys, }?: {
683
687
  schemaConfig?: SchemaConfig;
684
688
  columnTypes?: ColumnTypes | ((t: DefaultColumnTypes<SchemaConfig>) => ColumnTypes);
685
689
  snakeCase?: boolean;
@@ -687,6 +691,7 @@ declare function createBaseTable<SchemaConfig extends ColumnSchemaConfig = Defau
687
691
  nowSQL?: string;
688
692
  exportAs?: string;
689
693
  language?: string;
694
+ autoForeignKeys?: boolean | TableData.References.BaseOptions;
690
695
  }): BaseTableClass<SchemaConfig, ColumnTypes>;
691
696
 
692
697
  type QueryMethods<T extends Query> = Record<string, (q: T, ...args: any[]) => any>;
package/dist/index.js CHANGED
@@ -11,7 +11,8 @@ function createBaseTable({
11
11
  filePath: filePathArg,
12
12
  nowSQL,
13
13
  exportAs = "BaseTable",
14
- language
14
+ language,
15
+ autoForeignKeys
15
16
  } = {}) {
16
17
  var _a;
17
18
  const columnTypes = typeof columnTypesArg === "function" ? columnTypesArg(pqb.makeColumnTypes(schemaConfig)) : columnTypesArg || pqb.makeColumnTypes(schemaConfig);
@@ -142,6 +143,7 @@ function createBaseTable({
142
143
  orchidCore.applyMixins(base, [pqb.QueryHooks]);
143
144
  base.prototype.types = columnTypes;
144
145
  base.prototype.snakeCase = snakeCase;
146
+ base.prototype.autoForeignKeys = autoForeignKeys === true ? {} : autoForeignKeys || void 0;
145
147
  return base;
146
148
  }
147
149
 
@@ -252,6 +254,61 @@ const joinQueryChainingHOF = (reverseJoin, joinQuery) => (joiningQuery, baseQuer
252
254
  EXISTS: { q: reverseJoin(query, joiningQuery) }
253
255
  });
254
256
  };
257
+ const addAutoForeignKey = (tableConfig, from, to, primaryKeys, foreignKeys, options) => {
258
+ var _a;
259
+ const toTable = to.table;
260
+ let fkeyOptions = options.foreignKey !== void 0 ? options.foreignKey : tableConfig.autoForeignKeys;
261
+ if (!fkeyOptions) return;
262
+ if (fkeyOptions === true) {
263
+ fkeyOptions = tableConfig.autoForeignKeys || orchidCore.emptyObject;
264
+ }
265
+ if (foreignKeys.length === 1) {
266
+ const column = from.shape[foreignKeys[0]];
267
+ if (column.data.foreignKeys) {
268
+ const pkey = primaryKeys[0];
269
+ for (const fkey of column.data.foreignKeys) {
270
+ let fkeyTable;
271
+ let fkeyColumn = fkey.foreignColumns[0];
272
+ if (typeof fkey.fnOrTable === "string") {
273
+ fkeyTable = fkey.fnOrTable;
274
+ fkeyColumn = getColumnKeyFromDbName(to, fkeyColumn);
275
+ } else {
276
+ fkeyTable = fkey.fnOrTable().instance().table;
277
+ }
278
+ if (toTable === fkeyTable && pkey === fkeyColumn) return;
279
+ }
280
+ }
281
+ }
282
+ const { constraints } = from.internal.tableData;
283
+ if (constraints) {
284
+ const sortedPkeys = [...primaryKeys].sort();
285
+ const sortedFkeys = [...foreignKeys].sort();
286
+ for (const { references: refs } of constraints) {
287
+ if (!refs) continue;
288
+ if (refs.columns.length === sortedFkeys.length && refs.columns.every((column, i) => column === sortedFkeys[i]) && refs.foreignColumns.length === sortedPkeys.length && (typeof refs.fnOrTable === "string" ? refs.fnOrTable === toTable && refs.foreignColumns.every(
289
+ (column, i) => getColumnKeyFromDbName(to, column) === sortedPkeys[i]
290
+ ) : refs.fnOrTable().instance().table === toTable && refs.foreignColumns.every((column, i) => column === sortedPkeys[i])))
291
+ return;
292
+ }
293
+ }
294
+ ((_a = from.internal.tableData).constraints ?? (_a.constraints = [])).push({
295
+ references: {
296
+ columns: foreignKeys,
297
+ fnOrTable: toTable,
298
+ foreignColumns: primaryKeys,
299
+ options: fkeyOptions
300
+ },
301
+ dropMode: fkeyOptions.dropMode
302
+ });
303
+ };
304
+ const getColumnKeyFromDbName = (query, name) => {
305
+ for (const k in query.shape) {
306
+ if (query.shape[k].data.name === name) {
307
+ return k;
308
+ }
309
+ }
310
+ return name;
311
+ };
255
312
 
256
313
  class BelongsToVirtualColumn extends pqb.VirtualColumn {
257
314
  constructor(schema, key, state) {
@@ -304,12 +361,20 @@ class BelongsToVirtualColumn extends pqb.VirtualColumn {
304
361
  this.nestedUpdate(q, set, data, ctx);
305
362
  }
306
363
  }
307
- const makeBelongsToMethod = (relation, relationName, query) => {
364
+ const makeBelongsToMethod = (tableConfig, table, relation, relationName, query) => {
308
365
  const primaryKeys = relation.options.references;
309
366
  const foreignKeys = relation.options.columns;
310
367
  const len = primaryKeys.length;
311
368
  const state = { query, primaryKeys, foreignKeys, len };
312
369
  const makeWhere = relationWhere(len, primaryKeys, foreignKeys);
370
+ addAutoForeignKey(
371
+ tableConfig,
372
+ table,
373
+ query,
374
+ primaryKeys,
375
+ foreignKeys,
376
+ relation.options
377
+ );
313
378
  const join = (baseQuery, joiningQuery, primaryKeys2, foreignKeys2) => {
314
379
  const q = joiningQuery.clone();
315
380
  pqb.setQueryObjectValue(
@@ -577,7 +642,7 @@ class HasOneVirtualColumn extends pqb.VirtualColumn {
577
642
  );
578
643
  }
579
644
  }
580
- const makeHasOneMethod = (table, relation, relationName, query) => {
645
+ const makeHasOneMethod = (tableConfig, table, relation, relationName, query) => {
581
646
  if ("through" in relation.options) {
582
647
  const { through, source } = relation.options;
583
648
  const throughRelation = getThroughRelation(table, through);
@@ -617,6 +682,14 @@ const makeHasOneMethod = (table, relation, relationName, query) => {
617
682
  }
618
683
  const primaryKeys = relation.options.columns;
619
684
  const foreignKeys = relation.options.references;
685
+ addAutoForeignKey(
686
+ tableConfig,
687
+ query,
688
+ table,
689
+ primaryKeys,
690
+ foreignKeys,
691
+ relation.options
692
+ );
620
693
  const state = { query, primaryKeys, foreignKeys };
621
694
  const len = primaryKeys.length;
622
695
  const reversedOn = {};
@@ -827,7 +900,7 @@ class HasManyVirtualColumn extends pqb.VirtualColumn {
827
900
  );
828
901
  }
829
902
  }
830
- const makeHasManyMethod = (table, relation, relationName, query) => {
903
+ const makeHasManyMethod = (tableConfig, table, relation, relationName, query) => {
831
904
  if ("through" in relation.options) {
832
905
  const { through, source } = relation.options;
833
906
  const throughRelation = getThroughRelation(table, through);
@@ -873,6 +946,14 @@ const makeHasManyMethod = (table, relation, relationName, query) => {
873
946
  }
874
947
  const primaryKeys = relation.options.columns;
875
948
  const foreignKeys = relation.options.references;
949
+ addAutoForeignKey(
950
+ tableConfig,
951
+ query,
952
+ table,
953
+ primaryKeys,
954
+ foreignKeys,
955
+ relation.options
956
+ );
876
957
  const state = { query, primaryKeys, foreignKeys };
877
958
  const len = primaryKeys.length;
878
959
  const reversedOn = {};
@@ -1135,7 +1216,7 @@ const removeColumnName = (column) => {
1135
1216
  cloned.data = { ...column.data, name: void 0 };
1136
1217
  return cloned;
1137
1218
  };
1138
- const makeHasAndBelongsToManyMethod = (table, qb, relation, relationName, query) => {
1219
+ const makeHasAndBelongsToManyMethod = (tableConfig, table, qb, relation, relationName, query) => {
1139
1220
  const { options } = relation;
1140
1221
  const primaryKeys = options.columns;
1141
1222
  const foreignKeys = options.references;
@@ -1177,6 +1258,22 @@ const makeHasAndBelongsToManyMethod = (table, qb, relation, relationName, query)
1177
1258
  shape: baseQuery.shape
1178
1259
  };
1179
1260
  const subQuery = Object.create(baseQuery);
1261
+ addAutoForeignKey(
1262
+ tableConfig,
1263
+ subQuery,
1264
+ table,
1265
+ primaryKeys,
1266
+ foreignKeys,
1267
+ relation.options
1268
+ );
1269
+ addAutoForeignKey(
1270
+ tableConfig,
1271
+ subQuery,
1272
+ query,
1273
+ throughPrimaryKeys,
1274
+ throughForeignKeys,
1275
+ relation.options.through
1276
+ );
1180
1277
  const state = {
1181
1278
  relatedTableQuery: query,
1182
1279
  joinTableQuery: subQuery,
@@ -1619,7 +1716,7 @@ const applyRelations = (qb, tables, result) => {
1619
1716
  continue;
1620
1717
  }
1621
1718
  }
1622
- applyRelation(qb, data, delayedRelations);
1719
+ applyRelation(table, qb, data, delayedRelations);
1623
1720
  }
1624
1721
  }
1625
1722
  if (delayedRelations.size) {
@@ -1655,7 +1752,7 @@ const delayRelation = (delayedRelations, table, relationName, data) => {
1655
1752
  tableRelations[relationName] = [data];
1656
1753
  }
1657
1754
  };
1658
- const applyRelation = (qb, { relationName, relation, dbTable, otherDbTable }, delayedRelations) => {
1755
+ const applyRelation = (table, qb, { relationName, relation, dbTable, otherDbTable }, delayedRelations) => {
1659
1756
  const baseQuery = Object.create(otherDbTable);
1660
1757
  baseQuery.baseQuery = baseQuery;
1661
1758
  const query = (relation.options.scope ? relation.options.scope(baseQuery) : baseQuery).as(relationName);
@@ -1668,13 +1765,14 @@ const applyRelation = (qb, { relationName, relation, dbTable, otherDbTable }, de
1668
1765
  const { type } = relation;
1669
1766
  let data;
1670
1767
  if (type === "belongsTo") {
1671
- data = makeBelongsToMethod(relation, relationName, query);
1768
+ data = makeBelongsToMethod(table, dbTable, relation, relationName, query);
1672
1769
  } else if (type === "hasOne") {
1673
- data = makeHasOneMethod(dbTable, relation, relationName, query);
1770
+ data = makeHasOneMethod(table, dbTable, relation, relationName, query);
1674
1771
  } else if (type === "hasMany") {
1675
- data = makeHasManyMethod(dbTable, relation, relationName, query);
1772
+ data = makeHasManyMethod(table, dbTable, relation, relationName, query);
1676
1773
  } else if (type === "hasAndBelongsToMany") {
1677
1774
  data = makeHasAndBelongsToManyMethod(
1775
+ table,
1678
1776
  dbTable,
1679
1777
  qb,
1680
1778
  relation,
@@ -1718,7 +1816,7 @@ const applyRelation = (qb, { relationName, relation, dbTable, otherDbTable }, de
1718
1816
  const tableRelations = delayedRelations.get(dbTable);
1719
1817
  if (!tableRelations) return;
1720
1818
  tableRelations[relationName]?.forEach((data2) => {
1721
- applyRelation(qb, data2, delayedRelations);
1819
+ applyRelation(table, qb, data2, delayedRelations);
1722
1820
  });
1723
1821
  };
1724
1822