rake-db 2.3.10 → 2.3.13

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 CHANGED
@@ -1,5 +1,27 @@
1
1
  # rake-db
2
2
 
3
+ ## 2.3.13
4
+
5
+ ### Patch Changes
6
+
7
+ - ee1961e: Make columnTypes optional in configs
8
+ - Updated dependencies [ee1961e]
9
+ - pqb@0.9.8
10
+
11
+ ## 2.3.12
12
+
13
+ ### Patch Changes
14
+
15
+ - Handle table ordering by foreign key when pulling db
16
+ - Updated dependencies
17
+ - pqb@0.9.7
18
+
19
+ ## 2.3.11
20
+
21
+ ### Patch Changes
22
+
23
+ - Add generating extension to db pull
24
+
3
25
  ## 2.3.10
4
26
 
5
27
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as pqb from 'pqb';
2
- import { EmptyObject, RawExpression, ColumnType, ColumnTypes, raw, ColumnsShape, DbResult, columnTypes, TransactionAdapter, AdapterOptions, TextColumn, MaybeArray, IndexColumnOptions, IndexOptions, ForeignKeyOptions, QueryLogObject, NoPrimaryKeyOption, TableData, SingleColumnIndexOptions, QueryLogOptions } from 'pqb';
2
+ import { EmptyObject, RawExpression, ColumnType, ColumnTypes, raw, ColumnsShape, DbResult, DefaultColumnTypes, TransactionAdapter, AdapterOptions, TextColumn, MaybeArray, IndexColumnOptions, IndexOptions, ForeignKeyOptions, QueryLogObject, NoPrimaryKeyOption, TableData, SingleColumnIndexOptions, QueryLogOptions } from 'pqb';
3
3
 
4
4
  declare function add(item: ColumnType, options?: {
5
5
  dropMode?: DropMode;
@@ -60,7 +60,7 @@ declare type ExtensionOptions = {
60
60
  version?: string;
61
61
  cascade?: boolean;
62
62
  };
63
- declare type Migration = DbResult<typeof columnTypes> & MigrationBase;
63
+ declare type Migration = DbResult<DefaultColumnTypes> & MigrationBase;
64
64
  declare const createMigrationInterface: (tx: TransactionAdapter, up: boolean, options: RakeDbConfig, adapterOptions: AdapterOptions, appCodeUpdaterCache: object) => pqb.Db<string, Record<string, never>, pqb.RelationsBase, {
65
65
  smallint: () => pqb.SmallIntColumn;
66
66
  integer: () => pqb.IntegerColumn;
@@ -105,7 +105,7 @@ declare const createMigrationInterface: (tx: TransactionAdapter, up: boolean, op
105
105
  xml: () => pqb.XMLColumn;
106
106
  json: <Type extends pqb.JSONTypeAny>(schemaOrFn: Type | ((j: {
107
107
  set: <Value extends pqb.JSONTypeAny>(valueType: Value) => pqb.JSONSet<Value>;
108
- tuple: <T_1 extends [] | pqb.JSONTupleItems, Rest extends pqb.JSONTypeAny | null = null>(items: T_1, rest?: Rest) => pqb.JSONTuple<T_1, Rest>;
108
+ tuple: <T_1 extends pqb.JSONTupleItems | [], Rest extends pqb.JSONTypeAny | null = null>(items: T_1, rest?: Rest) => pqb.JSONTuple<T_1, Rest>;
109
109
  union: <T_2 extends [pqb.JSONTypeAny, pqb.JSONTypeAny, ...pqb.JSONTypeAny[]]>(types: T_2) => pqb.JSONUnion<T_2>;
110
110
  any: () => pqb.JSONAny;
111
111
  bigint: () => pqb.JSONBigInt;
@@ -204,7 +204,7 @@ declare const createMigrationInterface: (tx: TransactionAdapter, up: boolean, op
204
204
  xml: () => pqb.XMLColumn;
205
205
  json: <Type extends pqb.JSONTypeAny>(schemaOrFn: Type | ((j: {
206
206
  set: <Value extends pqb.JSONTypeAny>(valueType: Value) => pqb.JSONSet<Value>;
207
- tuple: <T_1 extends [] | pqb.JSONTupleItems, Rest extends pqb.JSONTypeAny | null = null>(items: T_1, rest?: Rest) => pqb.JSONTuple<T_1, Rest>;
207
+ tuple: <T_1 extends pqb.JSONTupleItems | [], Rest extends pqb.JSONTypeAny | null = null>(items: T_1, rest?: Rest) => pqb.JSONTuple<T_1, Rest>;
208
208
  union: <T_2 extends [pqb.JSONTypeAny, pqb.JSONTypeAny, ...pqb.JSONTypeAny[]]>(types: T_2) => pqb.JSONUnion<T_2>;
209
209
  any: () => pqb.JSONAny;
210
210
  bigint: () => pqb.JSONBigInt;
@@ -258,7 +258,105 @@ declare const createMigrationInterface: (tx: TransactionAdapter, up: boolean, op
258
258
  <Table extends pqb.ForeignKeyTableWithColumns, Columns extends [Exclude<keyof InstanceType<Table>["columns"]["shape"], number | symbol>, ...Exclude<keyof InstanceType<Table>["columns"]["shape"], number | symbol>[]]>(columns: string[], fn: () => Table, foreignColumns: Columns, options?: ForeignKeyOptions | undefined): {};
259
259
  <Table_1 extends string, Columns_1 extends [string, ...string[]]>(columns: string[], table: Table_1, foreignColumns: Columns_1, options?: ForeignKeyOptions | undefined): {};
260
260
  };
261
- }) => Shape) | undefined, options?: pqb.DbTableOptions | undefined): pqb.Db<Table_2, Shape, pqb.RelationsBase, pqb.ColumnTypesBase>;
261
+ }) => Shape) | undefined, options?: pqb.DbTableOptions | undefined): pqb.Db<Table_2, Shape, pqb.RelationsBase, {
262
+ smallint: () => pqb.SmallIntColumn;
263
+ integer: () => pqb.IntegerColumn;
264
+ bigint: () => pqb.BigIntColumn;
265
+ numeric: <Precision extends number | undefined = undefined, Scale extends number | undefined = undefined>(precision?: Precision | undefined, scale?: Scale | undefined) => pqb.DecimalColumn<Precision, Scale>;
266
+ decimal: <Precision_1 extends number | undefined = undefined, Scale_1 extends number | undefined = undefined>(precision?: Precision_1 | undefined, scale?: Scale_1 | undefined) => pqb.DecimalColumn<Precision_1, Scale_1>;
267
+ real: () => pqb.RealColumn;
268
+ doublePrecision: () => pqb.DoublePrecisionColumn;
269
+ smallSerial: () => pqb.SmallSerialColumn;
270
+ serial: () => pqb.SerialColumn;
271
+ bigSerial: () => pqb.BigSerialColumn;
272
+ money: () => pqb.MoneyColumn;
273
+ varchar: <Limit extends number | undefined = undefined>(limit?: Limit | undefined) => pqb.VarCharColumn<Limit>;
274
+ char: <Limit_1 extends number | undefined = undefined>(limit?: Limit_1 | undefined) => pqb.CharColumn<Limit_1>;
275
+ text: (min: number, max: number) => TextColumn;
276
+ string: (min: number, max: number) => TextColumn;
277
+ bytea: () => pqb.ByteaColumn;
278
+ date: () => pqb.DateColumn;
279
+ timestamp: <Precision_2 extends number | undefined = undefined>(precision?: Precision_2 | undefined) => pqb.TimestampColumn<Precision_2>;
280
+ timestampWithTimeZone: <Precision_3 extends number | undefined = undefined>(precision?: Precision_3 | undefined) => pqb.TimestampWithTimeZoneColumn<Precision_3>;
281
+ time: <Precision_4 extends number | undefined = undefined>(precision?: Precision_4 | undefined) => pqb.TimeColumn<Precision_4>;
282
+ timeWithTimeZone: <Precision_5 extends number | undefined = undefined>(precision?: Precision_5 | undefined) => pqb.TimeWithTimeZoneColumn<Precision_5>;
283
+ interval: <Fields extends string | undefined = undefined, Precision_6 extends number | undefined = undefined>(fields?: Fields | undefined, precision?: Precision_6 | undefined) => pqb.IntervalColumn<Fields, Precision_6>;
284
+ boolean: () => pqb.BooleanColumn;
285
+ enum: <U extends string, T extends [U, ...U[]]>(dataType: string, type: T) => pqb.EnumColumn<U, T>;
286
+ point: () => pqb.PointColumn;
287
+ line: () => pqb.LineColumn;
288
+ lseg: () => pqb.LsegColumn;
289
+ box: () => pqb.BoxColumn;
290
+ path: () => pqb.PathColumn;
291
+ polygon: () => pqb.PolygonColumn;
292
+ circle: () => pqb.CircleColumn;
293
+ cidr: () => pqb.CidrColumn;
294
+ inet: () => pqb.InetColumn;
295
+ macaddr: () => pqb.MacAddrColumn;
296
+ macaddr8: () => pqb.MacAddr8Column;
297
+ bit: <Length extends number>(length: Length) => pqb.BitColumn<Length>;
298
+ bitVarying: <Length_1 extends number | undefined = undefined>(length?: Length_1 | undefined) => pqb.BitVaryingColumn<Length_1>;
299
+ tsvector: () => pqb.TsVectorColumn;
300
+ tsquery: () => pqb.TsQueryColumn;
301
+ uuid: () => pqb.UUIDColumn;
302
+ xml: () => pqb.XMLColumn;
303
+ json: <Type extends pqb.JSONTypeAny>(schemaOrFn: Type | ((j: {
304
+ set: <Value extends pqb.JSONTypeAny>(valueType: Value) => pqb.JSONSet<Value>;
305
+ tuple: <T_1 extends pqb.JSONTupleItems | [], Rest extends pqb.JSONTypeAny | null = null>(items: T_1, rest?: Rest) => pqb.JSONTuple<T_1, Rest>;
306
+ union: <T_2 extends [pqb.JSONTypeAny, pqb.JSONTypeAny, ...pqb.JSONTypeAny[]]>(types: T_2) => pqb.JSONUnion<T_2>;
307
+ any: () => pqb.JSONAny;
308
+ bigint: () => pqb.JSONBigInt;
309
+ boolean: () => pqb.JSONBoolean;
310
+ date: () => pqb.JSONDate;
311
+ nan: () => pqb.JSONNaN;
312
+ never: () => pqb.JSONNever;
313
+ null: () => pqb.JSONNull;
314
+ number: () => pqb.JSONNumber;
315
+ string: () => pqb.JSONString;
316
+ undefined: () => pqb.JSONUndefined;
317
+ unknown: () => pqb.JSONUnknown;
318
+ void: () => pqb.JSONVoid;
319
+ array: <Type_1 extends pqb.JSONTypeAny>(element: Type_1) => pqb.JSONArray<Type_1, "many">;
320
+ discriminatedUnion: <Discriminator extends string, DiscriminatorValue extends pqb.Primitive, Types extends [pqb.JSONDiscriminatedObject<Discriminator, DiscriminatorValue>, pqb.JSONDiscriminatedObject<Discriminator, DiscriminatorValue>, ...pqb.JSONDiscriminatedObject<Discriminator, DiscriminatorValue>[]]>(discriminator: Discriminator, options: Types) => pqb.JSONDiscriminatedUnion<Discriminator, DiscriminatorValue, Types[number]>;
321
+ enum: <U_1 extends string, T_3 extends [U_1, ...U_1[]]>(options: T_3) => pqb.JSONEnum<U_1, T_3>;
322
+ instanceOf: <T_4 extends new (...args: any[]) => any>(cls: T_4) => pqb.JSONInstanceOf<T_4>;
323
+ intersection: <Left extends pqb.JSONTypeAny, Right extends pqb.JSONTypeAny>(left: Left, right: Right) => pqb.JSONIntersection<Left, Right>;
324
+ lazy: <T_5 extends pqb.JSONTypeAny>(fn: () => T_5) => pqb.JSONLazy<T_5>;
325
+ literal: <T_6 extends pqb.Primitive>(value: T_6) => pqb.JSONLiteral<T_6>;
326
+ map: <Key extends pqb.JSONTypeAny, Value_1 extends pqb.JSONTypeAny>(keyType: Key, valueType: Value_1) => pqb.JSONMap<Key, Value_1>;
327
+ nativeEnum: <T_7 extends pqb.EnumLike>(givenEnum: T_7) => pqb.JSONNativeEnum<T_7>;
328
+ nullable: <T_8 extends pqb.JSONTypeAny>(type: T_8) => pqb.JSONNullable<T_8>;
329
+ nullish: <T_9 extends pqb.JSONTypeAny>(type: T_9) => pqb.JSONNullish<T_9>;
330
+ object: <T_10 extends pqb.JSONObjectShape, UnknownKeys extends pqb.UnknownKeysParam = "strip", Catchall extends pqb.JSONTypeAny = pqb.JSONTypeAny>(shape: T_10) => pqb.JSONObject<T_10, UnknownKeys, Catchall, pqb.JSONTypeAny extends Catchall ? pqb.addQuestionMarks<{ [k_1 in keyof T_10]: T_10[k_1]["type"]; }> extends infer T_11 extends object ? { [k in keyof T_11]: pqb.addQuestionMarks<{ [k_1 in keyof T_10]: T_10[k_1]["type"]; }>[k]; } : never : (pqb.addQuestionMarks<{ [k_1 in keyof T_10]: T_10[k_1]["type"]; }> extends infer T_11 extends object ? { [k in keyof T_11]: pqb.addQuestionMarks<{ [k_1 in keyof T_10]: T_10[k_1]["type"]; }>[k]; } : never) & {
331
+ [k: string]: Catchall["type"];
332
+ } extends infer T_12 extends object ? { [k_2 in keyof T_12]: ((pqb.addQuestionMarks<{ [k_1 in keyof T_10]: T_10[k_1]["type"]; }> extends infer T_11 extends object ? { [k in keyof T_11]: pqb.addQuestionMarks<{ [k_1 in keyof T_10]: T_10[k_1]["type"]; }>[k]; } : never) & {
333
+ [k: string]: Catchall["type"];
334
+ })[k_2]; } : never>;
335
+ optional: <T_13 extends pqb.JSONTypeAny>(type: T_13) => pqb.JSONOptional<T_13>;
336
+ record: typeof pqb.record;
337
+ }) => Type)) => pqb.JSONColumn<Type>;
338
+ jsonText: () => pqb.JSONTextColumn;
339
+ array: <Item extends ColumnType<unknown, pqb.Operators, unknown>>(item: Item) => pqb.ArrayColumn<Item>;
340
+ timestamps: <T_14 extends ColumnType<unknown, pqb.Operators, unknown>>(this: {
341
+ timestamp(): T_14;
342
+ }) => {
343
+ createdAt: T_14 & {
344
+ hasDefault: true;
345
+ };
346
+ updatedAt: T_14 & {
347
+ hasDefault: true;
348
+ };
349
+ };
350
+ primaryKey(columns: string[], options?: {
351
+ name?: string | undefined;
352
+ } | undefined): {};
353
+ index(columns: MaybeArray<string | IndexColumnOptions>, options?: IndexOptions): {};
354
+ unique(columns: MaybeArray<string | IndexColumnOptions>, options?: IndexOptions): {};
355
+ foreignKey: {
356
+ <Table extends pqb.ForeignKeyTableWithColumns, Columns extends [Exclude<keyof InstanceType<Table>["columns"]["shape"], number | symbol>, ...Exclude<keyof InstanceType<Table>["columns"]["shape"], number | symbol>[]]>(columns: string[], fn: () => Table, foreignColumns: Columns, options?: ForeignKeyOptions | undefined): {};
357
+ <Table_1 extends string, Columns_1 extends [string, ...string[]]>(columns: string[], table: Table_1, foreignColumns: Columns_1, options?: ForeignKeyOptions | undefined): {};
358
+ };
359
+ }>;
262
360
  adapter: pqb.Adapter;
263
361
  close: () => Promise<void>;
264
362
  } & MigrationBase & {
@@ -311,7 +409,7 @@ declare class MigrationBase {
311
409
  }
312
410
  declare const runCodeUpdater: (migration: MigrationBase, ast: RakeDbAst) => Promise<void> | undefined;
313
411
 
314
- declare type RakeDbAst = RakeDbAst.Table | RakeDbAst.ChangeTable | RakeDbAst.RenameTable | RakeDbAst.Schema | RakeDbAst.Extension;
412
+ declare type RakeDbAst = RakeDbAst.Table | RakeDbAst.ChangeTable | RakeDbAst.RenameTable | RakeDbAst.Schema | RakeDbAst.Extension | RakeDbAst.ForeignKey;
315
413
  declare namespace RakeDbAst {
316
414
  type Table = {
317
415
  type: 'table';
@@ -387,9 +485,15 @@ declare namespace RakeDbAst {
387
485
  ifExists?: boolean;
388
486
  ifNotExists?: boolean;
389
487
  };
488
+ type ForeignKey = {
489
+ type: 'foreignKey';
490
+ action: 'create';
491
+ tableSchema?: string;
492
+ tableName: string;
493
+ } & TableData.ForeignKey;
390
494
  }
391
495
 
392
- declare type Db = DbResult<typeof columnTypes>;
496
+ declare type Db = DbResult<DefaultColumnTypes>;
393
497
  declare type RakeDbConfig = {
394
498
  migrationsPath: string;
395
499
  migrationsTable: string;
package/dist/index.js CHANGED
@@ -928,7 +928,7 @@ const createMigrationInterface = (tx, up, options, adapterOptions, appCodeUpdate
928
928
  adapter.arrays = (q, types) => {
929
929
  return wrapWithLog(log, q, () => arrays.call(adapter, q, types));
930
930
  };
931
- const db = pqb.createDb({ adapter, columnTypes: pqb.columnTypes });
931
+ const db = pqb.createDb({ adapter });
932
932
  const { prototype: proto } = MigrationBase;
933
933
  for (const key of Object.getOwnPropertyNames(proto)) {
934
934
  db[key] = proto[key];
@@ -1030,10 +1030,10 @@ class MigrationBase {
1030
1030
  return createSchema$1(this, !this.up, schemaName);
1031
1031
  }
1032
1032
  createExtension(name, options = {}) {
1033
- return createExtension(this, this.up, name, options);
1033
+ return createExtension$1(this, this.up, name, options);
1034
1034
  }
1035
1035
  dropExtension(name, options = {}) {
1036
- return createExtension(this, !this.up, name, options);
1036
+ return createExtension$1(this, !this.up, name, options);
1037
1037
  }
1038
1038
  async tableExists(tableName) {
1039
1039
  return queryExists(this, {
@@ -1095,7 +1095,7 @@ const createSchema$1 = async (migration, up, name) => {
1095
1095
  );
1096
1096
  await runCodeUpdater(migration, ast);
1097
1097
  };
1098
- const createExtension = async (migration, up, name, options) => {
1098
+ const createExtension$1 = async (migration, up, name, options) => {
1099
1099
  const ast = __spreadValues$2({
1100
1100
  type: "extension",
1101
1101
  action: up ? "create" : "drop",
@@ -1138,7 +1138,7 @@ var __spreadValues$1 = (a, b) => {
1138
1138
  }
1139
1139
  return a;
1140
1140
  };
1141
- const getDb = (adapter) => pqb.createDb({ adapter, columnTypes: pqb.columnTypes });
1141
+ const getDb = (adapter) => pqb.createDb({ adapter });
1142
1142
  const migrateOrRollback = async (options, config, args, up) => {
1143
1143
  var _a, _b, _c, _d, _e;
1144
1144
  config = __spreadValues$1({}, config);
@@ -1718,24 +1718,8 @@ const fkeyActionMap = {
1718
1718
  };
1719
1719
  const structureToAst = async (db) => {
1720
1720
  const ast = [];
1721
- const [
1722
- schemas,
1723
- tables,
1724
- allColumns,
1725
- allPrimaryKeys,
1726
- allIndexes,
1727
- allForeignKeys,
1728
- extensions
1729
- ] = await Promise.all([
1730
- db.getSchemas(),
1731
- db.getTables(),
1732
- db.getColumns(),
1733
- db.getPrimaryKeys(),
1734
- db.getIndexes(),
1735
- db.getForeignKeys(),
1736
- db.getExtensions()
1737
- ]);
1738
- for (const name of schemas) {
1721
+ const data = await getData(db);
1722
+ for (const name of data.schemas) {
1739
1723
  if (name === "public")
1740
1724
  continue;
1741
1725
  ast.push({
@@ -1744,108 +1728,51 @@ const structureToAst = async (db) => {
1744
1728
  name
1745
1729
  });
1746
1730
  }
1747
- for (const table of tables) {
1748
- const { schemaName, name } = table;
1749
- if (name === "schemaMigrations")
1750
- continue;
1751
- const belongsToTable = makeBelongsToTable(schemaName, name);
1752
- const columns = allColumns.filter(belongsToTable);
1753
- const primaryKey = allPrimaryKeys.find(belongsToTable);
1754
- const tableIndexes = allIndexes.filter(belongsToTable);
1755
- const tableForeignKeys = allForeignKeys.filter(belongsToTable);
1756
- const shape = {};
1757
- for (let item of columns) {
1758
- const isSerial = getIsSerial(item);
1759
- if (isSerial) {
1760
- item = __spreadProps(__spreadValues({}, item), { default: void 0 });
1761
- }
1762
- const klass = pqb.columnsByType[getColumnType(item, isSerial)];
1763
- if (!klass) {
1764
- throw new Error(`Column type \`${item.type}\` is not supported`);
1731
+ const pendingTables = {};
1732
+ for (const table of data.tables) {
1733
+ const key = `${table.schemaName}.${table.name}`;
1734
+ const dependsOn = /* @__PURE__ */ new Set();
1735
+ for (const fk of data.foreignKeys) {
1736
+ if (fk.schemaName !== table.schemaName || fk.tableName !== table.name)
1737
+ continue;
1738
+ const otherKey = `${fk.foreignTableSchemaName}.${fk.foreignTableName}`;
1739
+ if (otherKey !== key) {
1740
+ dependsOn.add(otherKey);
1765
1741
  }
1766
- let column = pqb.instantiateColumn(klass, item);
1767
- if ((primaryKey == null ? void 0 : primaryKey.columnNames.length) === 1 && (primaryKey == null ? void 0 : primaryKey.columnNames[0]) === item.name) {
1768
- column = column.primaryKey();
1769
- }
1770
- const indexes = tableIndexes.filter(
1771
- (it) => it.columns.length === 1 && "column" in it.columns[0] && it.columns[0].column === item.name
1772
- );
1773
- for (const index of indexes) {
1774
- const options = index.columns[0];
1775
- column = column.index({
1776
- collate: options.collate,
1777
- opclass: options.opclass,
1778
- order: options.order,
1779
- name: index.name !== getIndexName(name, index.columns) ? index.name : void 0,
1780
- using: index.using === "btree" ? void 0 : index.using,
1781
- unique: index.isUnique,
1782
- include: index.include,
1783
- with: index.with,
1784
- tablespace: index.tablespace,
1785
- where: index.where
1786
- });
1787
- }
1788
- const foreignKeys = tableForeignKeys.filter(
1789
- (it) => it.columnNames.length === 1 && it.columnNames[0] === item.name
1790
- );
1791
- for (const foreignKey of foreignKeys) {
1792
- column = column.foreignKey(
1793
- foreignKey.foreignTableName,
1794
- foreignKey.foreignColumnNames[0],
1795
- {
1796
- name: foreignKey.name && foreignKey.name !== getForeignKeyName(name, foreignKey.columnNames) ? foreignKey.name : void 0,
1797
- match: matchMap[foreignKey.match],
1798
- onUpdate: fkeyActionMap[foreignKey.onUpdate],
1799
- onDelete: fkeyActionMap[foreignKey.onDelete]
1800
- }
1801
- );
1742
+ }
1743
+ pendingTables[key] = { table, dependsOn };
1744
+ }
1745
+ for (const key in pendingTables) {
1746
+ const { table, dependsOn } = pendingTables[key];
1747
+ if (!dependsOn.size) {
1748
+ pushTableAst(ast, data, table, pendingTables);
1749
+ }
1750
+ }
1751
+ const outerFKeys = [];
1752
+ for (const key in pendingTables) {
1753
+ const innerFKeys = [];
1754
+ const { table } = pendingTables[key];
1755
+ for (const fkey of data.foreignKeys) {
1756
+ if (fkey.schemaName !== table.schemaName || fkey.tableName !== table.name)
1757
+ continue;
1758
+ const otherKey = `${fkey.foreignTableSchemaName}.${fkey.foreignTableName}`;
1759
+ if (!pendingTables[otherKey] || otherKey === key) {
1760
+ innerFKeys.push(fkey);
1761
+ } else {
1762
+ outerFKeys.push([fkey, table]);
1802
1763
  }
1803
- shape[item.name] = column;
1804
1764
  }
1805
- ast.push({
1806
- type: "table",
1765
+ pushTableAst(ast, data, table, pendingTables, innerFKeys);
1766
+ }
1767
+ for (const [fkey, table] of outerFKeys) {
1768
+ ast.push(__spreadProps(__spreadValues({}, foreignKeyToAst(fkey)), {
1769
+ type: "foreignKey",
1807
1770
  action: "create",
1808
- schema: schemaName === "public" ? void 0 : schemaName,
1809
- comment: table.comment,
1810
- name,
1811
- shape,
1812
- noPrimaryKey: primaryKey ? "error" : "ignore",
1813
- primaryKey: primaryKey && primaryKey.columnNames.length > 1 ? {
1814
- columns: primaryKey.columnNames,
1815
- options: primaryKey.name === `${name}_pkey` ? void 0 : { name: primaryKey.name }
1816
- } : void 0,
1817
- indexes: tableIndexes.filter(
1818
- (index) => index.columns.length > 1 || index.columns.some((it) => "expression" in it)
1819
- ).map((index) => ({
1820
- columns: index.columns.map((it) => __spreadProps(__spreadValues({}, "column" in it ? { column: it.column } : { expression: it.expression }), {
1821
- collate: it.collate,
1822
- opclass: it.opclass,
1823
- order: it.order
1824
- })),
1825
- options: {
1826
- name: index.name !== getIndexName(name, index.columns) ? index.name : void 0,
1827
- using: index.using === "btree" ? void 0 : index.using,
1828
- unique: index.isUnique,
1829
- include: index.include,
1830
- with: index.with,
1831
- tablespace: index.tablespace,
1832
- where: index.where
1833
- }
1834
- })),
1835
- foreignKeys: tableForeignKeys.filter((it) => it.columnNames.length > 1).map((it) => ({
1836
- columns: it.columnNames,
1837
- fnOrTable: it.foreignTableName,
1838
- foreignColumns: it.foreignColumnNames,
1839
- options: {
1840
- name: it.name && it.name !== getForeignKeyName(name, it.columnNames) ? it.name : void 0,
1841
- match: matchMap[it.match],
1842
- onUpdate: fkeyActionMap[it.onUpdate],
1843
- onDelete: fkeyActionMap[it.onDelete]
1844
- }
1845
- }))
1846
- });
1771
+ tableSchema: table.schemaName === "public" ? void 0 : table.schemaName,
1772
+ tableName: fkey.tableName
1773
+ }));
1847
1774
  }
1848
- for (const it of extensions) {
1775
+ for (const it of data.extensions) {
1849
1776
  ast.push({
1850
1777
  type: "extension",
1851
1778
  action: "create",
@@ -1856,6 +1783,34 @@ const structureToAst = async (db) => {
1856
1783
  }
1857
1784
  return ast;
1858
1785
  };
1786
+ const getData = async (db) => {
1787
+ const [
1788
+ schemas,
1789
+ tables,
1790
+ columns,
1791
+ primaryKeys,
1792
+ indexes,
1793
+ foreignKeys,
1794
+ extensions
1795
+ ] = await Promise.all([
1796
+ db.getSchemas(),
1797
+ db.getTables(),
1798
+ db.getColumns(),
1799
+ db.getPrimaryKeys(),
1800
+ db.getIndexes(),
1801
+ db.getForeignKeys(),
1802
+ db.getExtensions()
1803
+ ]);
1804
+ return {
1805
+ schemas,
1806
+ tables,
1807
+ columns,
1808
+ primaryKeys,
1809
+ indexes,
1810
+ foreignKeys,
1811
+ extensions
1812
+ };
1813
+ };
1859
1814
  const makeBelongsToTable = (schema, table) => (item) => item.schemaName === schema && item.tableName === table;
1860
1815
  const getIsSerial = (item) => {
1861
1816
  if (item.type === "int2" || item.type === "int4" || item.type === "int8") {
@@ -1873,16 +1828,134 @@ const getColumnType = (item, isSerial) => {
1873
1828
  }
1874
1829
  return item.type;
1875
1830
  };
1831
+ const pushTableAst = (ast, data, table, pendingTables, innerFKeys = data.foreignKeys) => {
1832
+ const { schemaName, name } = table;
1833
+ const key = `${schemaName}.${table.name}`;
1834
+ delete pendingTables[key];
1835
+ if (name === "schemaMigrations")
1836
+ return;
1837
+ const belongsToTable = makeBelongsToTable(schemaName, name);
1838
+ const columns = data.columns.filter(belongsToTable);
1839
+ const primaryKey = data.primaryKeys.find(belongsToTable);
1840
+ const tableIndexes = data.indexes.filter(belongsToTable);
1841
+ const tableForeignKeys = innerFKeys.filter(belongsToTable);
1842
+ const shape = {};
1843
+ for (let item of columns) {
1844
+ const isSerial = getIsSerial(item);
1845
+ if (isSerial) {
1846
+ item = __spreadProps(__spreadValues({}, item), { default: void 0 });
1847
+ }
1848
+ const klass = pqb.columnsByType[getColumnType(item, isSerial)];
1849
+ if (!klass) {
1850
+ throw new Error(`Column type \`${item.type}\` is not supported`);
1851
+ }
1852
+ let column = pqb.instantiateColumn(klass, item);
1853
+ if ((primaryKey == null ? void 0 : primaryKey.columnNames.length) === 1 && (primaryKey == null ? void 0 : primaryKey.columnNames[0]) === item.name) {
1854
+ column = column.primaryKey();
1855
+ }
1856
+ const indexes = tableIndexes.filter(
1857
+ (it) => it.columns.length === 1 && "column" in it.columns[0] && it.columns[0].column === item.name
1858
+ );
1859
+ for (const index of indexes) {
1860
+ const options = index.columns[0];
1861
+ column = column.index({
1862
+ collate: options.collate,
1863
+ opclass: options.opclass,
1864
+ order: options.order,
1865
+ name: index.name !== getIndexName(name, index.columns) ? index.name : void 0,
1866
+ using: index.using === "btree" ? void 0 : index.using,
1867
+ unique: index.isUnique,
1868
+ include: index.include,
1869
+ with: index.with,
1870
+ tablespace: index.tablespace,
1871
+ where: index.where
1872
+ });
1873
+ }
1874
+ const foreignKeys = tableForeignKeys.filter(
1875
+ (it) => it.columnNames.length === 1 && it.columnNames[0] === item.name
1876
+ );
1877
+ for (const foreignKey of foreignKeys) {
1878
+ column = column.foreignKey(
1879
+ foreignKey.foreignTableName,
1880
+ foreignKey.foreignColumnNames[0],
1881
+ {
1882
+ name: foreignKey.name && foreignKey.name !== getForeignKeyName(name, foreignKey.columnNames) ? foreignKey.name : void 0,
1883
+ match: matchMap[foreignKey.match],
1884
+ onUpdate: fkeyActionMap[foreignKey.onUpdate],
1885
+ onDelete: fkeyActionMap[foreignKey.onDelete]
1886
+ }
1887
+ );
1888
+ }
1889
+ shape[item.name] = column;
1890
+ }
1891
+ ast.push({
1892
+ type: "table",
1893
+ action: "create",
1894
+ schema: schemaName === "public" ? void 0 : schemaName,
1895
+ comment: table.comment,
1896
+ name,
1897
+ shape,
1898
+ noPrimaryKey: primaryKey ? "error" : "ignore",
1899
+ primaryKey: primaryKey && primaryKey.columnNames.length > 1 ? {
1900
+ columns: primaryKey.columnNames,
1901
+ options: primaryKey.name === `${name}_pkey` ? void 0 : { name: primaryKey.name }
1902
+ } : void 0,
1903
+ indexes: tableIndexes.filter(
1904
+ (index) => index.columns.length > 1 || index.columns.some((it) => "expression" in it)
1905
+ ).map((index) => ({
1906
+ columns: index.columns.map((it) => __spreadProps(__spreadValues({}, "column" in it ? { column: it.column } : { expression: it.expression }), {
1907
+ collate: it.collate,
1908
+ opclass: it.opclass,
1909
+ order: it.order
1910
+ })),
1911
+ options: {
1912
+ name: index.name !== getIndexName(name, index.columns) ? index.name : void 0,
1913
+ using: index.using === "btree" ? void 0 : index.using,
1914
+ unique: index.isUnique,
1915
+ include: index.include,
1916
+ with: index.with,
1917
+ tablespace: index.tablespace,
1918
+ where: index.where
1919
+ }
1920
+ })),
1921
+ foreignKeys: tableForeignKeys.filter((it) => it.columnNames.length > 1).map(foreignKeyToAst)
1922
+ });
1923
+ for (const otherKey in pendingTables) {
1924
+ const item = pendingTables[otherKey];
1925
+ if (item.dependsOn.delete(key) && item.dependsOn.size === 0) {
1926
+ pushTableAst(ast, data, item.table, pendingTables);
1927
+ }
1928
+ }
1929
+ };
1930
+ const foreignKeyToAst = (fkey) => ({
1931
+ columns: fkey.columnNames,
1932
+ fnOrTable: fkey.foreignTableName,
1933
+ foreignColumns: fkey.foreignColumnNames,
1934
+ options: {
1935
+ name: fkey.name && fkey.name !== getForeignKeyName(fkey.tableName, fkey.columnNames) ? fkey.name : void 0,
1936
+ match: matchMap[fkey.match],
1937
+ onUpdate: fkeyActionMap[fkey.onUpdate],
1938
+ onDelete: fkeyActionMap[fkey.onDelete]
1939
+ }
1940
+ });
1876
1941
 
1877
1942
  const astToMigration = (ast) => {
1878
1943
  const code = [];
1879
1944
  for (const item of ast) {
1880
1945
  if (item.type === "schema" && item.action === "create") {
1881
1946
  code.push(createSchema(item));
1947
+ } else if (item.type === "extension" && item.action === "create") {
1948
+ if (code.length)
1949
+ code.push([]);
1950
+ code.push(...createExtension(item));
1882
1951
  } else if (item.type === "table" && item.action === "create") {
1883
1952
  if (code.length)
1884
1953
  code.push([]);
1885
1954
  code.push(...createTable(item));
1955
+ } else if (item.type === "foreignKey") {
1956
+ if (code.length)
1957
+ code.push([]);
1958
+ code.push(...createForeignKey(item));
1886
1959
  }
1887
1960
  }
1888
1961
  if (!code.length)
@@ -1897,6 +1970,21 @@ ${pqb.codeToString(code, " ", " ")}
1897
1970
  const createSchema = (ast) => {
1898
1971
  return `await db.createSchema(${pqb.singleQuote(ast.name)});`;
1899
1972
  };
1973
+ const createExtension = (ast) => {
1974
+ const code = [`await db.createExtension(${pqb.singleQuote(ast.name)}`];
1975
+ if (ast.schema || ast.version) {
1976
+ pqb.addCode(code, ", {");
1977
+ if (ast.schema) {
1978
+ code.push([`schema: ${pqb.singleQuote(ast.schema)},`]);
1979
+ }
1980
+ if (ast.version) {
1981
+ code.push([`version: ${pqb.singleQuote(ast.version)},`]);
1982
+ }
1983
+ pqb.addCode(code, "}");
1984
+ }
1985
+ pqb.addCode(code, ")");
1986
+ return code;
1987
+ };
1900
1988
  const createTable = (ast) => {
1901
1989
  const code = [];
1902
1990
  pqb.addCode(code, `await db.createTable(${quoteSchemaTable(ast)}, (t) => ({`);
@@ -1932,6 +2020,19 @@ const isTimestamp = (column) => {
1932
2020
  const { default: def } = column.data;
1933
2021
  return column instanceof pqb.TimestampColumn && !column.data.isNullable && def && typeof def === "object" && pqb.isRaw(def) && def.__raw === "now()";
1934
2022
  };
2023
+ const createForeignKey = (item) => {
2024
+ return [
2025
+ `await db.addForeignKey(`,
2026
+ [
2027
+ `${quoteSchemaTable({
2028
+ schema: item.tableSchema,
2029
+ name: item.tableName
2030
+ })},`,
2031
+ ...pqb.foreignKeyArgsToCode(item)
2032
+ ],
2033
+ ");"
2034
+ ];
2035
+ };
1935
2036
 
1936
2037
  const pullDbStructure = async (options, config) => {
1937
2038
  const adapter = new pqb.Adapter(options);