joist-migration-utils 2.3.0-next.41 → 2.3.0-next.43
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/build/_virtual/_rolldown/runtime.cjs +23 -0
- package/build/_virtual/_rolldown/runtime.js +5 -0
- package/build/index.cjs +44 -0
- package/build/index.cjs.map +1 -0
- package/build/index.d.cts +7 -0
- package/build/index.d.cts.map +1 -0
- package/build/index.d.mts +7 -0
- package/build/index.d.mts.map +1 -0
- package/build/index.js +22 -39
- package/build/index.js.map +1 -1
- package/build/migrate.cjs +20 -0
- package/build/migrate.cjs.map +1 -0
- package/build/migrate.d.cts +6 -0
- package/build/migrate.d.cts.map +1 -0
- package/build/migrate.d.mts +6 -0
- package/build/migrate.d.mts.map +1 -0
- package/build/migrate.js +15 -17
- package/build/migrate.js.map +1 -1
- package/build/utils.cjs +272 -0
- package/build/utils.cjs.map +1 -0
- package/build/utils.d.cts +97 -0
- package/build/utils.d.cts.map +1 -0
- package/build/utils.d.mts +97 -0
- package/build/utils.d.mts.map +1 -0
- package/build/utils.js +192 -175
- package/build/utils.js.map +1 -1
- package/package.json +27 -4
- package/build/index.d.ts +0 -3
- package/build/migrate.d.ts +0 -2
- package/build/utils.d.ts +0 -94
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
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
|
+
value: mod,
|
|
20
|
+
enumerable: true
|
|
21
|
+
}) : target, mod));
|
|
22
|
+
//#endregion
|
|
23
|
+
exports.__toESM = __toESM;
|
package/build/index.cjs
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_migrate = require("./migrate.cjs");
|
|
3
|
+
const require_utils = require("./utils.cjs");
|
|
4
|
+
let joist_utils = require("joist-utils");
|
|
5
|
+
let pg = require("pg");
|
|
6
|
+
//#region src/index.ts
|
|
7
|
+
async function joistMigrate() {
|
|
8
|
+
const client = new pg.Client((0, joist_utils.newPgConnectionConfig)());
|
|
9
|
+
await client.connect();
|
|
10
|
+
try {
|
|
11
|
+
await require_migrate.runMigrationsIfNeeded(client, "./migrations");
|
|
12
|
+
} finally {
|
|
13
|
+
await client.end();
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
if (typeof module !== "undefined" && require.main === module) {
|
|
17
|
+
if (Object.fromEntries === void 0) throw new Error("Joist requires Node v12.4.0+");
|
|
18
|
+
joistMigrate().catch((err) => {
|
|
19
|
+
console.error(err);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
exports.addColumns = require_utils.addColumns;
|
|
25
|
+
exports.addEnumValue = require_utils.addEnumValue;
|
|
26
|
+
exports.commentData = require_utils.commentData;
|
|
27
|
+
exports.createCreatedAtFunction = require_utils.createCreatedAtFunction;
|
|
28
|
+
exports.createEntityTable = require_utils.createEntityTable;
|
|
29
|
+
exports.createEnumTable = require_utils.createEnumTable;
|
|
30
|
+
exports.createManyToManyTable = require_utils.createManyToManyTable;
|
|
31
|
+
exports.createSubTable = require_utils.createSubTable;
|
|
32
|
+
exports.createTriggers = require_utils.createTriggers;
|
|
33
|
+
exports.createUnnestArraysFunction = require_utils.createUnnestArraysFunction;
|
|
34
|
+
exports.createUpdatedAtFunction = require_utils.createUpdatedAtFunction;
|
|
35
|
+
exports.enumArrayColumn = require_utils.enumArrayColumn;
|
|
36
|
+
exports.fail = require_utils.fail;
|
|
37
|
+
exports.foreignKey = require_utils.foreignKey;
|
|
38
|
+
exports.joistMigrate = joistMigrate;
|
|
39
|
+
exports.renameRelation = require_utils.renameRelation;
|
|
40
|
+
exports.runMigrationsIfNeeded = require_migrate.runMigrationsIfNeeded;
|
|
41
|
+
exports.unnest_arrays = require_utils.unnest_arrays;
|
|
42
|
+
exports.updateEnumValue = require_utils.updateEnumValue;
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["Client","newPgConnectionConfig","runMigrationsIfNeeded"],"sources":["../src/index.ts"],"sourcesContent":["import { newPgConnectionConfig } from \"joist-utils\";\nimport { Client } from \"pg\";\n\nimport { runMigrationsIfNeeded } from \"./migrate.ts\";\n\nexport * from \"./migrate.ts\";\nexport * from \"./utils.ts\";\n\nexport async function joistMigrate(): Promise<void> {\n const client = new Client(newPgConnectionConfig());\n await client.connect();\n try {\n await runMigrationsIfNeeded(client, \"./migrations\");\n } finally {\n await client.end();\n }\n}\n\n// If we're being run locally.\nif (typeof module !== \"undefined\" && require.main === module) {\n if (Object.fromEntries === undefined) {\n throw new Error(\"Joist requires Node v12.4.0+\");\n }\n joistMigrate().catch((err) => {\n console.error(err);\n process.exit(1);\n });\n}\n"],"mappings":";;;;;;AAQA,eAAsB,eAA8B;CAClD,MAAM,SAAS,IAAIA,GAAAA,QAAAA,GAAOC,YAAAA,sBAAAA,CAAsB,CAAC;CACjD,MAAM,OAAO,QAAQ;CACrB,IAAI;EACF,MAAMC,gBAAAA,sBAAsB,QAAQ,cAAc;CACpD,UAAU;EACR,MAAM,OAAO,IAAI;CACnB;AACF;AAGA,IAAI,OAAO,WAAW,eAAe,QAAQ,SAAS,QAAQ;CAC5D,IAAI,OAAO,gBAAgB,KAAA,GACzB,MAAM,IAAI,MAAM,8BAA8B;CAEhD,aAAa,CAAC,CAAC,OAAO,QAAQ;EAC5B,QAAQ,MAAM,GAAG;EACjB,QAAQ,KAAK,CAAC;CAChB,CAAC;AACH"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { runMigrationsIfNeeded } from "./migrate.cjs";
|
|
2
|
+
import { FieldNameOverrides, RenameRelationOpts, addColumns, addEnumValue, commentData, createCreatedAtFunction, createEntityTable, createEnumTable, createManyToManyTable, createSubTable, createTriggers, createUnnestArraysFunction, createUpdatedAtFunction, enumArrayColumn, fail, foreignKey, renameRelation, unnest_arrays, updateEnumValue } from "./utils.cjs";
|
|
3
|
+
//#region src/index.d.ts
|
|
4
|
+
declare function joistMigrate(): Promise<void>;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { FieldNameOverrides, RenameRelationOpts, addColumns, addEnumValue, commentData, createCreatedAtFunction, createEntityTable, createEnumTable, createManyToManyTable, createSubTable, createTriggers, createUnnestArraysFunction, createUpdatedAtFunction, enumArrayColumn, fail, foreignKey, joistMigrate, renameRelation, runMigrationsIfNeeded, unnest_arrays, updateEnumValue };
|
|
7
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"mappings":";;;iBAQsB,gBAAgB"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { runMigrationsIfNeeded } from "./migrate.mjs";
|
|
2
|
+
import { FieldNameOverrides, RenameRelationOpts, addColumns, addEnumValue, commentData, createCreatedAtFunction, createEntityTable, createEnumTable, createManyToManyTable, createSubTable, createTriggers, createUnnestArraysFunction, createUpdatedAtFunction, enumArrayColumn, fail, foreignKey, renameRelation, unnest_arrays, updateEnumValue } from "./utils.mjs";
|
|
3
|
+
//#region src/index.d.ts
|
|
4
|
+
declare function joistMigrate(): Promise<void>;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { FieldNameOverrides, RenameRelationOpts, addColumns, addEnumValue, commentData, createCreatedAtFunction, createEntityTable, createEnumTable, createManyToManyTable, createSubTable, createTriggers, createUnnestArraysFunction, createUpdatedAtFunction, enumArrayColumn, fail, foreignKey, joistMigrate, renameRelation, runMigrationsIfNeeded, unnest_arrays, updateEnumValue };
|
|
7
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";;;iBAQsB,gBAAgB"}
|
package/build/index.js
CHANGED
|
@@ -1,43 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.joistMigrate = joistMigrate;
|
|
18
|
-
const joist_utils_1 = require("joist-utils");
|
|
19
|
-
const pg_1 = require("pg");
|
|
20
|
-
const migrate_1 = require("./migrate");
|
|
21
|
-
__exportStar(require("./migrate"), exports);
|
|
22
|
-
__exportStar(require("./utils"), exports);
|
|
1
|
+
import { __require } from "./_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { runMigrationsIfNeeded } from "./migrate.js";
|
|
3
|
+
import { addColumns, addEnumValue, commentData, createCreatedAtFunction, createEntityTable, createEnumTable, createManyToManyTable, createSubTable, createTriggers, createUnnestArraysFunction, createUpdatedAtFunction, enumArrayColumn, fail, foreignKey, renameRelation, unnest_arrays, updateEnumValue } from "./utils.js";
|
|
4
|
+
import { newPgConnectionConfig } from "joist-utils";
|
|
5
|
+
import { Client } from "pg";
|
|
6
|
+
//#region src/index.ts
|
|
23
7
|
async function joistMigrate() {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
8
|
+
const client = new Client(newPgConnectionConfig());
|
|
9
|
+
await client.connect();
|
|
10
|
+
try {
|
|
11
|
+
await runMigrationsIfNeeded(client, "./migrations");
|
|
12
|
+
} finally {
|
|
13
|
+
await client.end();
|
|
14
|
+
}
|
|
32
15
|
}
|
|
33
|
-
|
|
34
|
-
if (
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
console.error(err);
|
|
40
|
-
process.exit(1);
|
|
41
|
-
});
|
|
16
|
+
if (typeof module !== "undefined" && __require.main === module) {
|
|
17
|
+
if (Object.fromEntries === void 0) throw new Error("Joist requires Node v12.4.0+");
|
|
18
|
+
joistMigrate().catch((err) => {
|
|
19
|
+
console.error(err);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
});
|
|
42
22
|
}
|
|
23
|
+
//#endregion
|
|
24
|
+
export { addColumns, addEnumValue, commentData, createCreatedAtFunction, createEntityTable, createEnumTable, createManyToManyTable, createSubTable, createTriggers, createUnnestArraysFunction, createUpdatedAtFunction, enumArrayColumn, fail, foreignKey, joistMigrate, renameRelation, runMigrationsIfNeeded, unnest_arrays, updateEnumValue };
|
|
25
|
+
|
|
43
26
|
//# sourceMappingURL=index.js.map
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { newPgConnectionConfig } from \"joist-utils\";\nimport { Client } from \"pg\";\n\nimport { runMigrationsIfNeeded } from \"./migrate.ts\";\n\nexport * from \"./migrate.ts\";\nexport * from \"./utils.ts\";\n\nexport async function joistMigrate(): Promise<void> {\n const client = new Client(newPgConnectionConfig());\n await client.connect();\n try {\n await runMigrationsIfNeeded(client, \"./migrations\");\n } finally {\n await client.end();\n }\n}\n\n// If we're being run locally.\nif (typeof module !== \"undefined\" && require.main === module) {\n if (Object.fromEntries === undefined) {\n throw new Error(\"Joist requires Node v12.4.0+\");\n }\n joistMigrate().catch((err) => {\n console.error(err);\n process.exit(1);\n });\n}\n"],"mappings":";;;;;;AAQA,eAAsB,eAA8B;CAClD,MAAM,SAAS,IAAI,OAAO,sBAAsB,CAAC;CACjD,MAAM,OAAO,QAAQ;CACrB,IAAI;EACF,MAAM,sBAAsB,QAAQ,cAAc;CACpD,UAAU;EACR,MAAM,OAAO,IAAI;CACnB;AACF;AAGA,IAAI,OAAO,WAAW,eAAA,UAAuB,SAAS,QAAQ;CAC5D,IAAI,OAAO,gBAAgB,KAAA,GACzB,MAAM,IAAI,MAAM,8BAA8B;CAEhD,aAAa,CAAC,CAAC,OAAO,QAAQ;EAC5B,QAAQ,MAAM,GAAG;EACjB,QAAQ,KAAK,CAAC;CAChB,CAAC;AACH"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
require("pg");
|
|
3
|
+
let node_pg_migrate = require("node-pg-migrate");
|
|
4
|
+
//#region src/migrate.ts
|
|
5
|
+
const productionDirectory = "/home/node/app/migrations";
|
|
6
|
+
async function runMigrationsIfNeeded(client, dir = productionDirectory) {
|
|
7
|
+
await (0, node_pg_migrate.runner)({
|
|
8
|
+
dbClient: client,
|
|
9
|
+
migrationsTable: "migrations",
|
|
10
|
+
dir,
|
|
11
|
+
count: void 0,
|
|
12
|
+
direction: "up",
|
|
13
|
+
ignorePattern: "(\\..*)|(.*\\.d\\.ts)|(.*utils\\.[jt]s)|(migrate\\.[jt]s)|(migrate\\.test\\.[jt]s)",
|
|
14
|
+
decamelize: process.env.DECAMELIZE ? process.env.DECAMELIZE === "true" : true
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
exports.runMigrationsIfNeeded = runMigrationsIfNeeded;
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=migrate.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.cjs","names":["runner"],"sources":["../src/migrate.ts"],"sourcesContent":["import { runner } from \"node-pg-migrate\";\nimport { type Client } from \"pg\";\n\nconst productionDirectory = \"/home/node/app/migrations\";\n\nexport async function runMigrationsIfNeeded(client: Client, dir: string = productionDirectory): Promise<void> {\n await runner({\n dbClient: client,\n migrationsTable: \"migrations\",\n dir,\n count: undefined as any as number,\n direction: \"up\",\n ignorePattern: \"(\\\\..*)|(.*\\\\.d\\\\.ts)|(.*utils\\\\.[jt]s)|(migrate\\\\.[jt]s)|(migrate\\\\.test\\\\.[jt]s)\",\n // I generally dislike the magic of decamelize, but pragmatically it seems like a good foot-gun\n // mitigation to keep schemas always underscores/snake-based.\n // That said, provide an escape hatch, via the DECAMELIZE env var, which we also use for tests\n // since we want to specifically regression test the behavior of camelCased columns.\n decamelize: process.env.DECAMELIZE ? process.env.DECAMELIZE === \"true\" : true,\n });\n}\n"],"mappings":";;;;AAGA,MAAM,sBAAsB;AAE5B,eAAsB,sBAAsB,QAAgB,MAAc,qBAAoC;CAC5G,OAAA,GAAMA,gBAAAA,OAAAA,CAAO;EACX,UAAU;EACV,iBAAiB;EACjB;EACA,OAAO,KAAA;EACP,WAAW;EACX,eAAe;EAKf,YAAY,QAAQ,IAAI,aAAa,QAAQ,IAAI,eAAe,SAAS;CAC3E,CAAC;AACH"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.d.cts","names":[],"sources":["../src/migrate.ts"],"mappings":";;iBAKsB,sBAAsB,QAAQ,QAAQ,eAAoC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.d.mts","names":[],"sources":["../src/migrate.ts"],"mappings":";;iBAKsB,sBAAsB,QAAQ,QAAQ,eAAoC"}
|
package/build/migrate.js
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const node_pg_migrate_1 = require("node-pg-migrate");
|
|
1
|
+
import "pg";
|
|
2
|
+
import { runner } from "node-pg-migrate";
|
|
3
|
+
//#region src/migrate.ts
|
|
5
4
|
const productionDirectory = "/home/node/app/migrations";
|
|
6
5
|
async function runMigrationsIfNeeded(client, dir = productionDirectory) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
// That said, provide an escape hatch, via the DECAMELIZE env var, which we also use for tests
|
|
17
|
-
// since we want to specifically regression test the behavior of camelCased columns.
|
|
18
|
-
decamelize: process.env.DECAMELIZE ? process.env.DECAMELIZE === "true" : true,
|
|
19
|
-
});
|
|
6
|
+
await runner({
|
|
7
|
+
dbClient: client,
|
|
8
|
+
migrationsTable: "migrations",
|
|
9
|
+
dir,
|
|
10
|
+
count: void 0,
|
|
11
|
+
direction: "up",
|
|
12
|
+
ignorePattern: "(\\..*)|(.*\\.d\\.ts)|(.*utils\\.[jt]s)|(migrate\\.[jt]s)|(migrate\\.test\\.[jt]s)",
|
|
13
|
+
decamelize: process.env.DECAMELIZE ? process.env.DECAMELIZE === "true" : true
|
|
14
|
+
});
|
|
20
15
|
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { runMigrationsIfNeeded };
|
|
18
|
+
|
|
21
19
|
//# sourceMappingURL=migrate.js.map
|
package/build/migrate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.js","
|
|
1
|
+
{"version":3,"file":"migrate.js","names":[],"sources":["../src/migrate.ts"],"sourcesContent":["import { runner } from \"node-pg-migrate\";\nimport { type Client } from \"pg\";\n\nconst productionDirectory = \"/home/node/app/migrations\";\n\nexport async function runMigrationsIfNeeded(client: Client, dir: string = productionDirectory): Promise<void> {\n await runner({\n dbClient: client,\n migrationsTable: \"migrations\",\n dir,\n count: undefined as any as number,\n direction: \"up\",\n ignorePattern: \"(\\\\..*)|(.*\\\\.d\\\\.ts)|(.*utils\\\\.[jt]s)|(migrate\\\\.[jt]s)|(migrate\\\\.test\\\\.[jt]s)\",\n // I generally dislike the magic of decamelize, but pragmatically it seems like a good foot-gun\n // mitigation to keep schemas always underscores/snake-based.\n // That said, provide an escape hatch, via the DECAMELIZE env var, which we also use for tests\n // since we want to specifically regression test the behavior of camelCased columns.\n decamelize: process.env.DECAMELIZE ? process.env.DECAMELIZE === \"true\" : true,\n });\n}\n"],"mappings":";;;AAGA,MAAM,sBAAsB;AAE5B,eAAsB,sBAAsB,QAAgB,MAAc,qBAAoC;CAC5G,MAAM,OAAO;EACX,UAAU;EACV,iBAAiB;EACjB;EACA,OAAO,KAAA;EACP,WAAW;EACX,eAAe;EAKf,YAAY,QAAQ,IAAI,aAAa,QAAQ,IAAI,eAAe,SAAS;CAC3E,CAAC;AACH"}
|
package/build/utils.cjs
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_runtime = require("./_virtual/_rolldown/runtime.cjs");
|
|
3
|
+
let node_pg_migrate = require("node-pg-migrate");
|
|
4
|
+
let pluralize = require("pluralize");
|
|
5
|
+
pluralize = require_runtime.__toESM(pluralize, 1);
|
|
6
|
+
//#region src/utils.ts
|
|
7
|
+
const { singular } = pluralize.default;
|
|
8
|
+
/**
|
|
9
|
+
* Creates an entity table with our conventions.
|
|
10
|
+
*
|
|
11
|
+
* Specifically an `id` auto-increment column (via a sequence) and `created_at` and `updated_at`
|
|
12
|
+
* columns.
|
|
13
|
+
*/
|
|
14
|
+
function createEntityTable(b, tableName, columns) {
|
|
15
|
+
b.createTable(tableName, {
|
|
16
|
+
id: "id",
|
|
17
|
+
...columns,
|
|
18
|
+
created_at: {
|
|
19
|
+
type: "timestamptz",
|
|
20
|
+
notNull: true
|
|
21
|
+
},
|
|
22
|
+
updated_at: {
|
|
23
|
+
type: "timestamptz",
|
|
24
|
+
notNull: true
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
Object.entries(columns).forEach(([name, def]) => {
|
|
28
|
+
if (typeof def === "object" && def.references) b.addIndex(tableName, [name], { method: "btree" });
|
|
29
|
+
});
|
|
30
|
+
createTriggers(b, tableName);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Creates a subtype table using class-per-table inheritance.
|
|
34
|
+
*
|
|
35
|
+
* The subtable will use the base table's id as its identity, and when loading rows of the base
|
|
36
|
+
* type, Joist will automatically stitch together rows across each table into a single instance.
|
|
37
|
+
*/
|
|
38
|
+
function createSubTable(b, baseTableName, subTableName, columns) {
|
|
39
|
+
b.createTable(subTableName, {
|
|
40
|
+
id: {
|
|
41
|
+
type: "int",
|
|
42
|
+
references: `${baseTableName}`,
|
|
43
|
+
primaryKey: true,
|
|
44
|
+
deferrable: true,
|
|
45
|
+
deferred: true,
|
|
46
|
+
onDelete: "CASCADE"
|
|
47
|
+
},
|
|
48
|
+
...columns
|
|
49
|
+
});
|
|
50
|
+
Object.entries(columns).forEach(([name, def]) => {
|
|
51
|
+
if (typeof def === "object" && def.references) b.addIndex(subTableName, [name], { method: "btree" });
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function createEnumTable(b, tableName, values) {
|
|
55
|
+
b.createTable(tableName, {
|
|
56
|
+
id: "id",
|
|
57
|
+
code: {
|
|
58
|
+
type: "text",
|
|
59
|
+
notNull: true
|
|
60
|
+
},
|
|
61
|
+
name: {
|
|
62
|
+
type: "text",
|
|
63
|
+
notNull: true
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
b.addConstraint(tableName, `${tableName}_unique_enum_code_constraint`, "UNIQUE (code)");
|
|
67
|
+
values.forEach((value) => addEnumValue(b, tableName, value));
|
|
68
|
+
}
|
|
69
|
+
function addEnumValue(b, tableName, value) {
|
|
70
|
+
const [code, name] = value;
|
|
71
|
+
validateEnumCode(code);
|
|
72
|
+
b.sql(`INSERT INTO ${tableName} (code, name) VALUES ('${code}', '${name.replace("'", "''")}');`);
|
|
73
|
+
}
|
|
74
|
+
function updateEnumValue(b, tableName, previousCode, value) {
|
|
75
|
+
const [code, name] = value;
|
|
76
|
+
validateEnumCode(code);
|
|
77
|
+
b.sql(`UPDATE ${tableName} SET code ='${code}', name = '${name.replace("'", "''")}' WHERE code = '${previousCode}';`);
|
|
78
|
+
}
|
|
79
|
+
function validateEnumCode(code) {
|
|
80
|
+
const codeRegex = /^[A-Z0-9_]+$/;
|
|
81
|
+
if (!codeRegex.test(code)) throw `ERROR: Invalid enum code specified: ${code}. Codes must match the regex: ${codeRegex}`;
|
|
82
|
+
}
|
|
83
|
+
/** Makes a trigger to update the `updated_at` column. */
|
|
84
|
+
function createTriggers(b, tableName) {
|
|
85
|
+
b.createTrigger(tableName, `${tableName}_created_at`, {
|
|
86
|
+
when: "BEFORE",
|
|
87
|
+
operation: "INSERT",
|
|
88
|
+
level: "ROW",
|
|
89
|
+
function: "trigger_maybe_set_created_at"
|
|
90
|
+
});
|
|
91
|
+
b.createTrigger(tableName, `${tableName}_updated_at`, {
|
|
92
|
+
when: "BEFORE",
|
|
93
|
+
operation: "UPDATE",
|
|
94
|
+
level: "ROW",
|
|
95
|
+
function: "trigger_maybe_set_updated_at"
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
function createUpdatedAtFunction(b) {
|
|
99
|
+
b.createFunction("trigger_maybe_set_updated_at", [], {
|
|
100
|
+
replace: true,
|
|
101
|
+
language: "plpgsql",
|
|
102
|
+
returns: "TRIGGER"
|
|
103
|
+
}, "BEGIN IF NEW.updated_at = OLD.updated_at THEN NEW.updated_at = NOW(); END IF; RETURN NEW; END;");
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Unnests a 2d array like `[[a, b], [c, d]]` into two rows of `[a, b]` and `[c, d]`.
|
|
107
|
+
*
|
|
108
|
+
* This custom function is a key part of Joist's bulk INSERT/UPDATE that sends "all firstNames as
|
|
109
|
+
* a single param", because it lets us support array columns as a single parameter (i.e. an array
|
|
110
|
+
* of arrays).
|
|
111
|
+
*
|
|
112
|
+
* Postgres's built-in `unnest` is too aggressive when flattening, and will unnest the 2d array
|
|
113
|
+
* of `[[a, b], [c, d]]` into four rows of `a`, `b`, `c`, and `d`, which is not what we want.
|
|
114
|
+
*
|
|
115
|
+
* Additionally, Postgres does not support "jagged arrays", i.e. 2D arrays where some
|
|
116
|
+
* sub-arrays are longer than others, e.g. `[[a, b], [c, d, e]]`. Instead, it treats arrays
|
|
117
|
+
* more as the mathematical concept of a matrix, than "a list of lists".
|
|
118
|
+
*
|
|
119
|
+
* To work around this, our PostgresDriver auto-pads all 2D arrays to the same length, by
|
|
120
|
+
* appending `NULL`, and then `unnest_arrays` prunes all `NULL`s from the resulting 1D arrays.
|
|
121
|
+
* See `fillArrayWithNulls`.
|
|
122
|
+
*
|
|
123
|
+
*
|
|
124
|
+
* This means we purposefully do not/cannot support `NULL` values _within_ array columns,
|
|
125
|
+
* i.e. `nick_names=[a, NULL, b]` (without some additional heuristics).
|
|
126
|
+
*
|
|
127
|
+
* That said, we do need to support nullable array columns, i.e. `nick_names=NULL`, which we
|
|
128
|
+
* detect by prefixing an additional marker element to each sub-array that indicates whether the
|
|
129
|
+
* array column is null or not, and then conditionally enabling this with the `nullable=true`
|
|
130
|
+
* param to `unnest_arrays`.
|
|
131
|
+
*/
|
|
132
|
+
const unnest_arrays = `
|
|
133
|
+
CREATE OR REPLACE FUNCTION unnest_arrays(arr ANYARRAY, nullable BOOLEAN = false, OUT a ANYARRAY)
|
|
134
|
+
RETURNS SETOF ANYARRAY
|
|
135
|
+
LANGUAGE plpgsql IMMUTABLE STRICT AS
|
|
136
|
+
$func$
|
|
137
|
+
BEGIN
|
|
138
|
+
FOREACH a SLICE 1 IN ARRAY arr LOOP
|
|
139
|
+
IF nullable THEN
|
|
140
|
+
IF a[1] IS NULL THEN a := NULL;
|
|
141
|
+
ELSE a := a[2:array_length(a, 1)];
|
|
142
|
+
END IF;
|
|
143
|
+
END IF;
|
|
144
|
+
a := array_remove(a, NULL);
|
|
145
|
+
RETURN NEXT;
|
|
146
|
+
END LOOP;
|
|
147
|
+
END
|
|
148
|
+
$func$;
|
|
149
|
+
`;
|
|
150
|
+
function createUnnestArraysFunction(b) {
|
|
151
|
+
b.sql(unnest_arrays);
|
|
152
|
+
}
|
|
153
|
+
function createCreatedAtFunction(b) {
|
|
154
|
+
b.createFunction("trigger_maybe_set_created_at", [], {
|
|
155
|
+
replace: true,
|
|
156
|
+
language: "plpgsql",
|
|
157
|
+
returns: "TRIGGER"
|
|
158
|
+
}, "BEGIN IF NEW.created_at IS NULL THEN NEW.created_at = NOW(); END IF; IF NEW.updated_at IS NULL THEN NEW.updated_at = NOW(); END IF; RETURN NEW; END;");
|
|
159
|
+
}
|
|
160
|
+
function foreignKey(otherTable, opts) {
|
|
161
|
+
return {
|
|
162
|
+
type: "integer",
|
|
163
|
+
references: otherTable,
|
|
164
|
+
deferrable: true,
|
|
165
|
+
deferred: true,
|
|
166
|
+
...foreignKeyOptsWithMaybeComment(opts)
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function renameRelation(b, tableName, columnName, opts) {
|
|
170
|
+
b.alterColumn(tableName, columnName, foreignKeyOptsWithMaybeComment(opts));
|
|
171
|
+
}
|
|
172
|
+
function commentData(data, comment) {
|
|
173
|
+
return `${comment ?? ""}[pg-structure]${JSON.stringify(data)}[/pg-structure]`;
|
|
174
|
+
}
|
|
175
|
+
function foreignKeyOptsWithMaybeComment(opts) {
|
|
176
|
+
let { comment, fieldName, otherFieldName, ...rest } = opts;
|
|
177
|
+
if (fieldName || otherFieldName) {
|
|
178
|
+
const overrides = {
|
|
179
|
+
fieldName,
|
|
180
|
+
otherFieldName
|
|
181
|
+
};
|
|
182
|
+
return {
|
|
183
|
+
...rest,
|
|
184
|
+
comment: commentData(overrides, comment)
|
|
185
|
+
};
|
|
186
|
+
} else if (comment) return {
|
|
187
|
+
...rest,
|
|
188
|
+
comment
|
|
189
|
+
};
|
|
190
|
+
else return rest;
|
|
191
|
+
}
|
|
192
|
+
function enumArrayColumn(enumTable, opts) {
|
|
193
|
+
return {
|
|
194
|
+
type: "integer[]",
|
|
195
|
+
comment: `enum=${enumTable}`,
|
|
196
|
+
notNull: false,
|
|
197
|
+
default: node_pg_migrate.PgLiteral.create("array[]::integer[]"),
|
|
198
|
+
...opts
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function maybeTableOrColumn(maybeTableOrColumn) {
|
|
202
|
+
if (typeof maybeTableOrColumn === "string") return [
|
|
203
|
+
maybeTableOrColumn,
|
|
204
|
+
`${singular(maybeTableOrColumn)}_id`,
|
|
205
|
+
void 0
|
|
206
|
+
];
|
|
207
|
+
else {
|
|
208
|
+
const { table, column, collectionName } = maybeTableOrColumn;
|
|
209
|
+
return [
|
|
210
|
+
table,
|
|
211
|
+
column ?? `${singular(table)}_id`,
|
|
212
|
+
collectionName
|
|
213
|
+
];
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
function createManyToManyTable(b, tableName, tableOrColumn1, tableOrColumn2, options) {
|
|
217
|
+
const [table1, column1, otherFieldName1] = maybeTableOrColumn(tableOrColumn1);
|
|
218
|
+
const [table2, column2, otherFieldName2] = maybeTableOrColumn(tableOrColumn2);
|
|
219
|
+
b.createTable(tableName, {
|
|
220
|
+
id: "id",
|
|
221
|
+
[column1]: foreignKey(table1, {
|
|
222
|
+
notNull: true,
|
|
223
|
+
onDelete: "CASCADE",
|
|
224
|
+
otherFieldName: otherFieldName1
|
|
225
|
+
}),
|
|
226
|
+
[column2]: foreignKey(table2, {
|
|
227
|
+
notNull: true,
|
|
228
|
+
onDelete: "CASCADE",
|
|
229
|
+
otherFieldName: otherFieldName2
|
|
230
|
+
}),
|
|
231
|
+
created_at: {
|
|
232
|
+
type: "timestamptz",
|
|
233
|
+
notNull: true,
|
|
234
|
+
default: b.func("NOW()")
|
|
235
|
+
}
|
|
236
|
+
}, options);
|
|
237
|
+
b.createIndex(tableName, [column1, column2], {
|
|
238
|
+
unique: true,
|
|
239
|
+
ifNotExists: options?.ifNotExists
|
|
240
|
+
});
|
|
241
|
+
b.createIndex(tableName, [column2]);
|
|
242
|
+
}
|
|
243
|
+
/** Adds columns + auto-indexes any foreign keys. */
|
|
244
|
+
function addColumns(b, tableName, columns) {
|
|
245
|
+
b.addColumns(tableName, columns);
|
|
246
|
+
Object.entries(columns).forEach(([name, def]) => {
|
|
247
|
+
if (typeof def === "object" && def.references) b.addIndex(tableName, [name], { method: "btree" });
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
function fail(message) {
|
|
251
|
+
throw new Error(message || "Failed");
|
|
252
|
+
}
|
|
253
|
+
//#endregion
|
|
254
|
+
exports.addColumns = addColumns;
|
|
255
|
+
exports.addEnumValue = addEnumValue;
|
|
256
|
+
exports.commentData = commentData;
|
|
257
|
+
exports.createCreatedAtFunction = createCreatedAtFunction;
|
|
258
|
+
exports.createEntityTable = createEntityTable;
|
|
259
|
+
exports.createEnumTable = createEnumTable;
|
|
260
|
+
exports.createManyToManyTable = createManyToManyTable;
|
|
261
|
+
exports.createSubTable = createSubTable;
|
|
262
|
+
exports.createTriggers = createTriggers;
|
|
263
|
+
exports.createUnnestArraysFunction = createUnnestArraysFunction;
|
|
264
|
+
exports.createUpdatedAtFunction = createUpdatedAtFunction;
|
|
265
|
+
exports.enumArrayColumn = enumArrayColumn;
|
|
266
|
+
exports.fail = fail;
|
|
267
|
+
exports.foreignKey = foreignKey;
|
|
268
|
+
exports.renameRelation = renameRelation;
|
|
269
|
+
exports.unnest_arrays = unnest_arrays;
|
|
270
|
+
exports.updateEnumValue = updateEnumValue;
|
|
271
|
+
|
|
272
|
+
//# sourceMappingURL=utils.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.cjs","names":["PgLiteral"],"sources":["../src/utils.ts"],"sourcesContent":["import {\n type ColumnDefinition,\n type ColumnDefinitions,\n type DropOptions,\n type MigrationBuilder,\n PgLiteral,\n type TableOptions,\n} from \"node-pg-migrate\";\nimport pluralize from \"pluralize\";\n\nconst { singular } = pluralize;\n\n/**\n * Creates an entity table with our conventions.\n *\n * Specifically an `id` auto-increment column (via a sequence) and `created_at` and `updated_at`\n * columns.\n */\nexport function createEntityTable(b: MigrationBuilder, tableName: string, columns: ColumnDefinitions): void {\n b.createTable(tableName, {\n id: \"id\",\n ...columns,\n created_at: { type: \"timestamptz\", notNull: true },\n updated_at: { type: \"timestamptz\", notNull: true },\n });\n\n // Postgres doesn't automatically index foreign keys, so any column def points at\n // another table, assume we'll be doing a lot of lookups on this column and should fk it.\n Object.entries(columns).forEach(([name, def]) => {\n if (typeof def === \"object\" && def.references) {\n b.addIndex(tableName, [name], { method: \"btree\" });\n }\n });\n\n createTriggers(b, tableName);\n}\n\n/**\n * Creates a subtype table using class-per-table inheritance.\n *\n * The subtable will use the base table's id as its identity, and when loading rows of the base\n * type, Joist will automatically stitch together rows across each table into a single instance.\n */\nexport function createSubTable(\n b: MigrationBuilder,\n baseTableName: string,\n subTableName: string,\n columns: ColumnDefinitions,\n): void {\n b.createTable(subTableName, {\n id: {\n type: \"int\",\n references: `${baseTableName}`,\n primaryKey: true,\n deferrable: true,\n deferred: true,\n onDelete: \"CASCADE\",\n },\n ...columns,\n });\n // Postgres doesn't automatically index foreign keys, so any column def points at\n // another table, assume we'll be doing a lot of lookups on this column and should fk it.\n Object.entries(columns).forEach(([name, def]) => {\n if (typeof def === \"object\" && def.references) {\n b.addIndex(subTableName, [name], { method: \"btree\" });\n }\n });\n}\n\nexport function createEnumTable(b: MigrationBuilder, tableName: string, values: Array<[string, string]>): void {\n b.createTable(tableName, {\n id: \"id\",\n code: { type: \"text\", notNull: true },\n name: { type: \"text\", notNull: true },\n });\n b.addConstraint(tableName, `${tableName}_unique_enum_code_constraint`, \"UNIQUE (code)\");\n values.forEach((value) => addEnumValue(b, tableName, value));\n}\nexport function addEnumValue(b: MigrationBuilder, tableName: string, value: [string, string]): void {\n const [code, name] = value;\n validateEnumCode(code);\n b.sql(`INSERT INTO ${tableName} (code, name) VALUES ('${code}', '${name.replace(\"'\", \"''\")}');`);\n}\n\nexport function updateEnumValue(\n b: MigrationBuilder,\n tableName: string,\n previousCode: string,\n value: [string, string],\n): void {\n const [code, name] = value;\n validateEnumCode(code);\n b.sql(`UPDATE ${tableName} SET code ='${code}', name = '${name.replace(\"'\", \"''\")}' WHERE code = '${previousCode}';`);\n}\n\nfunction validateEnumCode(code: string): void {\n const codeRegex = /^[A-Z0-9_]+$/;\n if (!codeRegex.test(code))\n throw `ERROR: Invalid enum code specified: ${code}. Codes must match the regex: ${codeRegex}`;\n}\n\n/** Makes a trigger to update the `updated_at` column. */\nexport function createTriggers(b: MigrationBuilder, tableName: string): void {\n b.createTrigger(tableName, `${tableName}_created_at`, {\n when: \"BEFORE\",\n operation: \"INSERT\",\n level: \"ROW\",\n function: \"trigger_maybe_set_created_at\",\n });\n b.createTrigger(tableName, `${tableName}_updated_at`, {\n when: \"BEFORE\",\n operation: \"UPDATE\",\n level: \"ROW\",\n function: \"trigger_maybe_set_updated_at\",\n });\n}\n\nexport function createUpdatedAtFunction(b: MigrationBuilder): void {\n b.createFunction(\n \"trigger_maybe_set_updated_at\",\n [],\n { replace: true, language: \"plpgsql\", returns: \"TRIGGER\" },\n \"BEGIN IF NEW.updated_at = OLD.updated_at THEN NEW.updated_at = NOW(); END IF; RETURN NEW; END;\",\n );\n}\n\n/**\n * Unnests a 2d array like `[[a, b], [c, d]]` into two rows of `[a, b]` and `[c, d]`.\n *\n * This custom function is a key part of Joist's bulk INSERT/UPDATE that sends \"all firstNames as\n * a single param\", because it lets us support array columns as a single parameter (i.e. an array\n * of arrays).\n *\n * Postgres's built-in `unnest` is too aggressive when flattening, and will unnest the 2d array\n * of `[[a, b], [c, d]]` into four rows of `a`, `b`, `c`, and `d`, which is not what we want.\n *\n * Additionally, Postgres does not support \"jagged arrays\", i.e. 2D arrays where some\n * sub-arrays are longer than others, e.g. `[[a, b], [c, d, e]]`. Instead, it treats arrays\n * more as the mathematical concept of a matrix, than \"a list of lists\".\n *\n * To work around this, our PostgresDriver auto-pads all 2D arrays to the same length, by\n * appending `NULL`, and then `unnest_arrays` prunes all `NULL`s from the resulting 1D arrays.\n * See `fillArrayWithNulls`.\n *\n *\n * This means we purposefully do not/cannot support `NULL` values _within_ array columns,\n * i.e. `nick_names=[a, NULL, b]` (without some additional heuristics).\n *\n * That said, we do need to support nullable array columns, i.e. `nick_names=NULL`, which we\n * detect by prefixing an additional marker element to each sub-array that indicates whether the\n * array column is null or not, and then conditionally enabling this with the `nullable=true`\n * param to `unnest_arrays`.\n */\nexport const unnest_arrays = `\nCREATE OR REPLACE FUNCTION unnest_arrays(arr ANYARRAY, nullable BOOLEAN = false, OUT a ANYARRAY)\n RETURNS SETOF ANYARRAY\n LANGUAGE plpgsql IMMUTABLE STRICT AS\n$func$\nBEGIN\n FOREACH a SLICE 1 IN ARRAY arr LOOP\n IF nullable THEN\n IF a[1] IS NULL THEN a := NULL;\n ELSE a := a[2:array_length(a, 1)];\n END IF;\n END IF;\n a := array_remove(a, NULL);\n RETURN NEXT;\n END LOOP;\nEND\n$func$;\n`;\n\nexport function createUnnestArraysFunction(b: MigrationBuilder): void {\n b.sql(unnest_arrays);\n}\n\nexport function createCreatedAtFunction(b: MigrationBuilder): void {\n b.createFunction(\n \"trigger_maybe_set_created_at\",\n [],\n { replace: true, language: \"plpgsql\", returns: \"TRIGGER\" },\n \"BEGIN IF NEW.created_at IS NULL THEN NEW.created_at = NOW(); END IF; IF NEW.updated_at IS NULL THEN NEW.updated_at = NOW(); END IF; RETURN NEW; END;\",\n );\n}\n\nexport type FieldNameOverrides = {\n fieldName?: string;\n otherFieldName?: string;\n};\ntype ForeignKeyOpts = Partial<ColumnDefinition> & Required<Pick<ColumnDefinition, \"notNull\">> & FieldNameOverrides;\nexport function foreignKey(otherTable: string, opts: ForeignKeyOpts): ColumnDefinition {\n return {\n type: \"integer\",\n references: otherTable,\n deferrable: true,\n deferred: true,\n ...foreignKeyOptsWithMaybeComment(opts),\n };\n}\n\nexport type RenameRelationOpts = FieldNameOverrides & Pick<ColumnDefinition, \"comment\">;\nexport function renameRelation(b: MigrationBuilder, tableName: string, columnName: string, opts: RenameRelationOpts) {\n b.alterColumn(tableName, columnName, foreignKeyOptsWithMaybeComment(opts));\n}\n\nexport function commentData(data: any, comment?: string | null): string {\n return `${comment ?? \"\"}[pg-structure]${JSON.stringify(data)}[/pg-structure]`;\n}\n\nfunction foreignKeyOptsWithMaybeComment<T extends RenameRelationOpts, R extends Omit<T, keyof FieldNameOverrides>>(\n opts: T,\n): R {\n let { comment, fieldName, otherFieldName, ...rest } = opts;\n if (fieldName || otherFieldName) {\n const overrides = { fieldName, otherFieldName };\n return { ...(rest as R), comment: commentData(overrides, comment) };\n } else if (comment) {\n return { ...(rest as R), comment };\n } else {\n return rest as R;\n }\n}\n\nexport function enumArrayColumn(enumTable: string, opts?: Pick<ColumnDefinition, \"notNull\">): ColumnDefinition {\n // We use `notNull: false` to facilitate adding to tables with existing rows,\n // but note that we coalesce null to `[]` anyway in the serde logic, so it\n // doesn't really matter to application logic whether it's notNull or not.\n return {\n type: \"integer[]\",\n comment: `enum=${enumTable}`,\n notNull: false,\n default: PgLiteral.create(\"array[]::integer[]\"),\n ...opts,\n };\n}\n\ntype ManyToManyColumn = {\n /** The target table for this m2m table, i.e. for a `books_to_tags`, this might be `books`. */\n table: string;\n /** The column name within the m2m table, i.e. for a `books_to_tags`, this might be `book_id`. */\n column?: string;\n /**\n * The name of the collection that *points to* these rows, i.e. for `books_to_tags` and the `book_id`\n * column, `collectionName=taggedBooks` b/c `t1.taggedBooks` does a `SELECT book_id WHERE tag_id=t:1`.\n *\n * For self-referential m2m tables, i.e. `author_to_mentors`, these names can be confusing, i.e.:\n *\n * ```\n * createManyToManyTable(\n * b,\n * \"author_to_mentors\",\n * // column=mentor_id, collectionName=mentors ==> `a.mentors` does `select mentor_id WHERE mentee_id=a:1`\n * { table: \"authors\", column: \"mentor_id\", collectionName: \"mentors\" },\n * // column=mentee_id, collectionName=mentees ==> `a.mentees` does `select mentee_id WHERE mentor_id=a:1`\n * { table: \"authors\", column: \"mentee_id\", collectionName: \"mentees\" },\n * );\n * ````\n */\n collectionName?: string;\n};\n\nfunction maybeTableOrColumn(maybeTableOrColumn: string | ManyToManyColumn): [string, string, string | undefined] {\n if (typeof maybeTableOrColumn === \"string\") {\n return [maybeTableOrColumn, `${singular(maybeTableOrColumn)}_id`, undefined];\n } else {\n const { table, column, collectionName } = maybeTableOrColumn;\n return [table, column ?? `${singular(table)}_id`, collectionName];\n }\n}\n\n/** Creates a many-to-many table between `table1` and `table2` with our conventions. */\nexport function createManyToManyTable(\n b: MigrationBuilder,\n tableName: string,\n table1: string,\n table2: string,\n options?: TableOptions & DropOptions,\n): void;\nexport function createManyToManyTable(\n b: MigrationBuilder,\n tableName: string,\n column1: ManyToManyColumn,\n column2: ManyToManyColumn,\n options?: TableOptions & DropOptions,\n): void;\nexport function createManyToManyTable(\n b: MigrationBuilder,\n tableName: string,\n table1: string,\n column2: ManyToManyColumn,\n options?: TableOptions & DropOptions,\n): void;\nexport function createManyToManyTable(\n b: MigrationBuilder,\n tableName: string,\n column1: ManyToManyColumn,\n table2: string,\n options?: TableOptions & DropOptions,\n): void;\nexport function createManyToManyTable(\n b: MigrationBuilder,\n tableName: string,\n tableOrColumn1: string | ManyToManyColumn,\n tableOrColumn2: string | ManyToManyColumn,\n options?: TableOptions & DropOptions,\n) {\n const [table1, column1, otherFieldName1] = maybeTableOrColumn(tableOrColumn1);\n const [table2, column2, otherFieldName2] = maybeTableOrColumn(tableOrColumn2);\n b.createTable(\n tableName,\n {\n id: \"id\",\n [column1]: foreignKey(table1, { notNull: true, onDelete: \"CASCADE\", otherFieldName: otherFieldName1 }),\n [column2]: foreignKey(table2, { notNull: true, onDelete: \"CASCADE\", otherFieldName: otherFieldName2 }),\n created_at: { type: \"timestamptz\", notNull: true, default: b.func(\"NOW()\") },\n },\n options,\n );\n b.createIndex(tableName, [column1, column2], { unique: true, ifNotExists: options?.ifNotExists });\n b.createIndex(tableName, [column2]); // Improves lookup performance when querying just column2\n}\n\n/** Adds columns + auto-indexes any foreign keys. */\nexport function addColumns(b: MigrationBuilder, tableName: string, columns: ColumnDefinitions): void {\n b.addColumns(tableName, columns);\n Object.entries(columns).forEach(([name, def]) => {\n if (typeof def === \"object\" && def.references) {\n b.addIndex(tableName, [name], { method: \"btree\" });\n }\n });\n}\n\nexport function fail(message?: string): never {\n throw new Error(message || \"Failed\");\n}\n"],"mappings":"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"}
|