pgpm 5.13.0 → 5.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/commands/deploy.js +31 -6
- package/commands/package.js +12 -2
- package/commands/revert.js +1 -0
- package/commands/verify.js +1 -0
- package/commands.js +27 -1
- package/esm/commands/deploy.js +32 -7
- package/esm/commands/package.js +12 -2
- package/esm/commands/revert.js +1 -0
- package/esm/commands/verify.js +1 -0
- package/esm/commands.js +28 -2
- package/esm/utils/display.js +5 -0
- package/esm/utils/engine-gating.js +28 -0
- package/esm/utils/engine.js +89 -0
- package/esm/utils/index.js +2 -0
- package/package.json +8 -8
- package/utils/display.d.ts +1 -1
- package/utils/display.js +5 -0
- package/utils/engine-gating.d.ts +6 -0
- package/utils/engine-gating.js +32 -0
- package/utils/engine.d.ts +57 -0
- package/utils/engine.js +97 -0
- package/utils/index.d.ts +2 -0
- package/utils/index.js +2 -0
package/commands/deploy.js
CHANGED
|
@@ -17,11 +17,18 @@ Deploy Command:
|
|
|
17
17
|
Options:
|
|
18
18
|
--help, -h Show this help message
|
|
19
19
|
--createdb Create database if it doesn't exist
|
|
20
|
+
--engine <name> Migration backend to deploy to (default: pg).
|
|
21
|
+
Built-in engines: pg (Postgres server), pglite (in-process WASM).
|
|
22
|
+
--driver <pkg> Driver plugin package to deploy through (escape hatch for --engine)
|
|
23
|
+
--pglite[=dataDir] Sugar for --engine pglite; persists to <dataDir> when given
|
|
20
24
|
--recursive Deploy recursively through dependencies
|
|
21
25
|
--package <name> Target specific package
|
|
22
26
|
--to <target> Deploy to specific change or tag
|
|
23
27
|
--tx Use transactions (default: true)
|
|
24
|
-
--fast
|
|
28
|
+
--fast Fast strategy: one-shot SQL + bulk migration ledger,
|
|
29
|
+
reading each module's verified sql/*.bundle.tar.gz artifact
|
|
30
|
+
when present and building it from deploy/ when not
|
|
31
|
+
--bundled Alias for --fast
|
|
25
32
|
--logOnly Log-only mode, skip script execution
|
|
26
33
|
--usePlan Use deployment plan
|
|
27
34
|
--cache Enable caching
|
|
@@ -32,6 +39,9 @@ Examples:
|
|
|
32
39
|
pgpm deploy --createdb Deploy with database creation
|
|
33
40
|
pgpm deploy --package mypackage --to @v1.0.0 Deploy specific package to tag
|
|
34
41
|
pgpm deploy --fast --no-tx Fast deployment without transactions
|
|
42
|
+
pgpm deploy --bundled Same as --fast
|
|
43
|
+
pgpm deploy --engine pglite Deploy into in-process PGlite (no server)
|
|
44
|
+
pgpm deploy --pglite=./.pglite Deploy into a persisted PGlite data directory
|
|
35
45
|
`;
|
|
36
46
|
exports.default = async (argv, prompter, _options) => {
|
|
37
47
|
// Show usage if explicitly requested
|
|
@@ -90,6 +100,14 @@ exports.default = async (argv, prompter, _options) => {
|
|
|
90
100
|
default: false,
|
|
91
101
|
required: false
|
|
92
102
|
},
|
|
103
|
+
{
|
|
104
|
+
name: 'bundled',
|
|
105
|
+
type: 'confirm',
|
|
106
|
+
message: 'Prefer prebuilt bundle artifacts (alias of fast)?',
|
|
107
|
+
useDefault: true,
|
|
108
|
+
default: false,
|
|
109
|
+
required: false
|
|
110
|
+
},
|
|
93
111
|
{
|
|
94
112
|
name: 'logOnly',
|
|
95
113
|
type: 'confirm',
|
|
@@ -99,17 +117,23 @@ exports.default = async (argv, prompter, _options) => {
|
|
|
99
117
|
required: false
|
|
100
118
|
}
|
|
101
119
|
];
|
|
102
|
-
let { yes, recursive, createdb, cwd, tx, fast, logOnly } = await prompter.prompt(argv, questions);
|
|
120
|
+
let { yes, recursive, createdb, cwd, tx, fast, bundled, logOnly } = await prompter.prompt(argv, questions);
|
|
103
121
|
if (!yes) {
|
|
104
122
|
log.info('Operation cancelled.');
|
|
105
123
|
return;
|
|
106
124
|
}
|
|
107
125
|
log.debug(`Using current directory: ${cwd}`);
|
|
126
|
+
const { engine, capabilities } = (0, utils_1.getActiveEngine)();
|
|
108
127
|
if (createdb) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
128
|
+
if (capabilities.createdb) {
|
|
129
|
+
log.info(`Creating database ${database}...`);
|
|
130
|
+
(0, child_process_1.execSync)(`createdb ${database}`, {
|
|
131
|
+
env: (0, pg_env_1.getSpawnEnvWithPg)(pgEnv)
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
log.info(`Skipping createdb: the "${engine.name}" engine's instance is the database.`);
|
|
136
|
+
}
|
|
113
137
|
}
|
|
114
138
|
let packageName;
|
|
115
139
|
if (recursive) {
|
|
@@ -120,6 +144,7 @@ exports.default = async (argv, prompter, _options) => {
|
|
|
120
144
|
deployment: {
|
|
121
145
|
useTx: tx !== false,
|
|
122
146
|
fast: fast !== false,
|
|
147
|
+
bundled: bundled === true,
|
|
123
148
|
usePlan: argv.usePlan !== false,
|
|
124
149
|
cache: argv.cache !== false,
|
|
125
150
|
logOnly: argv.logOnly !== false,
|
package/commands/package.js
CHANGED
|
@@ -14,12 +14,14 @@ Options:
|
|
|
14
14
|
--pretty Pretty-print output (default: true)
|
|
15
15
|
--functionDelimiter <delimiter> Function delimiter (default: $EOFCODE$)
|
|
16
16
|
--outputDiff Export AST diff files when round-trip mismatch detected (default: false)
|
|
17
|
+
--bundle Also emit sql/<name>--<version>.bundle.tar.gz (default: true)
|
|
17
18
|
--cwd <directory> Working directory (default: current directory)
|
|
18
19
|
|
|
19
20
|
Examples:
|
|
20
21
|
pgpm package Package with defaults
|
|
21
22
|
pgpm package --no-plan Package without plan
|
|
22
23
|
pgpm package --outputDiff Package and export AST diff files if mismatch detected
|
|
24
|
+
pgpm package --no-bundle Package without emitting the bundle artifact
|
|
23
25
|
`;
|
|
24
26
|
exports.default = async (argv, prompter, _options) => {
|
|
25
27
|
// Show usage if explicitly requested
|
|
@@ -55,9 +57,16 @@ exports.default = async (argv, prompter, _options) => {
|
|
|
55
57
|
default: false,
|
|
56
58
|
useDefault: true,
|
|
57
59
|
required: false
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
type: 'confirm',
|
|
63
|
+
name: 'bundle',
|
|
64
|
+
default: true,
|
|
65
|
+
useDefault: true,
|
|
66
|
+
required: false
|
|
58
67
|
}
|
|
59
68
|
];
|
|
60
|
-
let { cwd, plan, pretty, functionDelimiter, outputDiff } = await prompter.prompt(argv, questions);
|
|
69
|
+
let { cwd, plan, pretty, functionDelimiter, outputDiff, bundle } = await prompter.prompt(argv, questions);
|
|
61
70
|
const project = new core_1.PgpmPackage(cwd);
|
|
62
71
|
project.ensureModule();
|
|
63
72
|
const info = project.getModuleInfo();
|
|
@@ -69,7 +78,8 @@ exports.default = async (argv, prompter, _options) => {
|
|
|
69
78
|
packageDir: project.modulePath,
|
|
70
79
|
pretty,
|
|
71
80
|
functionDelimiter,
|
|
72
|
-
outputDiff
|
|
81
|
+
outputDiff,
|
|
82
|
+
bundle: bundle !== false
|
|
73
83
|
});
|
|
74
84
|
return argv;
|
|
75
85
|
};
|
package/commands/revert.js
CHANGED
|
@@ -22,6 +22,7 @@ Options:
|
|
|
22
22
|
--to <target> Revert to specific change or tag
|
|
23
23
|
--to Interactive selection of deployed changes
|
|
24
24
|
--tx Use transactions (default: true)
|
|
25
|
+
--engine <name> Migration backend to revert in (default: pg; also pglite)
|
|
25
26
|
--cwd <directory> Working directory (default: current directory)
|
|
26
27
|
|
|
27
28
|
Examples:
|
package/commands/verify.js
CHANGED
|
@@ -21,6 +21,7 @@ Options:
|
|
|
21
21
|
--package <name> Verify specific package
|
|
22
22
|
--to <target> Verify up to specific change or tag
|
|
23
23
|
--to Interactive selection of deployed changes
|
|
24
|
+
--engine <name> Migration backend to verify against (default: pg; also pglite)
|
|
24
25
|
--cwd <directory> Working directory (default: current directory)
|
|
25
26
|
|
|
26
27
|
Examples:
|
package/commands.js
CHANGED
|
@@ -37,6 +37,12 @@ const update_1 = __importDefault(require("./commands/update"));
|
|
|
37
37
|
const upgrade_1 = __importDefault(require("./commands/upgrade"));
|
|
38
38
|
const verify_1 = __importDefault(require("./commands/verify"));
|
|
39
39
|
const utils_2 = require("./utils");
|
|
40
|
+
/**
|
|
41
|
+
* Commands that never talk to a database and must not activate a driver.
|
|
42
|
+
* `init` owns its own `--pglite` meaning (scaffold from the PGlite boilerplates),
|
|
43
|
+
* and it runs before the plugin it would scaffold is even installed.
|
|
44
|
+
*/
|
|
45
|
+
const ENGINE_EXEMPT_COMMANDS = new Set(['init']);
|
|
40
46
|
const withPgTeardown = (fn, skipTeardown = false) => async (...args) => {
|
|
41
47
|
try {
|
|
42
48
|
await fn(...args);
|
|
@@ -144,7 +150,27 @@ const commands = async (argv, prompter, options) => {
|
|
|
144
150
|
console.log(utils_2.usageText);
|
|
145
151
|
await (0, inquirerer_1.cliExitWithError)(`Unknown command: ${command}`, { beforeExit: pg_cache_1.teardownPgPools });
|
|
146
152
|
}
|
|
147
|
-
|
|
153
|
+
// Activate the selected migration backend (`--engine`/`--driver`/`--pglite` or
|
|
154
|
+
// pgpm.json) before the command runs: the driver plugin registers its
|
|
155
|
+
// pool/client factories, so the unmodified engine targets it. The built-in
|
|
156
|
+
// `pg` engine activates nothing and behaves exactly as before.
|
|
157
|
+
const engineArgv = newArgv;
|
|
158
|
+
const { engine, capabilities } = ENGINE_EXEMPT_COMMANDS.has(command)
|
|
159
|
+
? (0, utils_2.getActiveEngine)()
|
|
160
|
+
: await (0, utils_2.activateEngine)(engineArgv, engineArgv.cwd).catch(async (error) => {
|
|
161
|
+
await (0, inquirerer_1.cliExitWithError)(error.message, { beforeExit: pg_cache_1.teardownPgPools });
|
|
162
|
+
throw error;
|
|
163
|
+
});
|
|
164
|
+
try {
|
|
165
|
+
const blocked = (0, utils_2.engineCommandBlocker)(command, engine, capabilities);
|
|
166
|
+
if (blocked) {
|
|
167
|
+
await (0, inquirerer_1.cliExitWithError)(blocked, { beforeExit: pg_cache_1.teardownPgPools });
|
|
168
|
+
}
|
|
169
|
+
await commandFn(newArgv, prompter, options);
|
|
170
|
+
}
|
|
171
|
+
finally {
|
|
172
|
+
await (0, utils_2.deactivateEngine)();
|
|
173
|
+
}
|
|
148
174
|
prompter.close();
|
|
149
175
|
return argv;
|
|
150
176
|
};
|
package/esm/commands/deploy.js
CHANGED
|
@@ -3,7 +3,7 @@ import { getEnvOptions } from '@pgpmjs/env';
|
|
|
3
3
|
import { Logger } from '@pgpmjs/logger';
|
|
4
4
|
import { execSync } from 'child_process';
|
|
5
5
|
import { getPgEnvOptions, getSpawnEnvWithPg, } from 'pg-env';
|
|
6
|
-
import { getTargetDatabase, resolvePackageAlias } from '../utils';
|
|
6
|
+
import { getActiveEngine, getTargetDatabase, resolvePackageAlias } from '../utils';
|
|
7
7
|
import { selectPackage } from '../utils/module-utils';
|
|
8
8
|
const deployUsageText = `
|
|
9
9
|
Deploy Command:
|
|
@@ -15,11 +15,18 @@ Deploy Command:
|
|
|
15
15
|
Options:
|
|
16
16
|
--help, -h Show this help message
|
|
17
17
|
--createdb Create database if it doesn't exist
|
|
18
|
+
--engine <name> Migration backend to deploy to (default: pg).
|
|
19
|
+
Built-in engines: pg (Postgres server), pglite (in-process WASM).
|
|
20
|
+
--driver <pkg> Driver plugin package to deploy through (escape hatch for --engine)
|
|
21
|
+
--pglite[=dataDir] Sugar for --engine pglite; persists to <dataDir> when given
|
|
18
22
|
--recursive Deploy recursively through dependencies
|
|
19
23
|
--package <name> Target specific package
|
|
20
24
|
--to <target> Deploy to specific change or tag
|
|
21
25
|
--tx Use transactions (default: true)
|
|
22
|
-
--fast
|
|
26
|
+
--fast Fast strategy: one-shot SQL + bulk migration ledger,
|
|
27
|
+
reading each module's verified sql/*.bundle.tar.gz artifact
|
|
28
|
+
when present and building it from deploy/ when not
|
|
29
|
+
--bundled Alias for --fast
|
|
23
30
|
--logOnly Log-only mode, skip script execution
|
|
24
31
|
--usePlan Use deployment plan
|
|
25
32
|
--cache Enable caching
|
|
@@ -30,6 +37,9 @@ Examples:
|
|
|
30
37
|
pgpm deploy --createdb Deploy with database creation
|
|
31
38
|
pgpm deploy --package mypackage --to @v1.0.0 Deploy specific package to tag
|
|
32
39
|
pgpm deploy --fast --no-tx Fast deployment without transactions
|
|
40
|
+
pgpm deploy --bundled Same as --fast
|
|
41
|
+
pgpm deploy --engine pglite Deploy into in-process PGlite (no server)
|
|
42
|
+
pgpm deploy --pglite=./.pglite Deploy into a persisted PGlite data directory
|
|
33
43
|
`;
|
|
34
44
|
export default async (argv, prompter, _options) => {
|
|
35
45
|
// Show usage if explicitly requested
|
|
@@ -88,6 +98,14 @@ export default async (argv, prompter, _options) => {
|
|
|
88
98
|
default: false,
|
|
89
99
|
required: false
|
|
90
100
|
},
|
|
101
|
+
{
|
|
102
|
+
name: 'bundled',
|
|
103
|
+
type: 'confirm',
|
|
104
|
+
message: 'Prefer prebuilt bundle artifacts (alias of fast)?',
|
|
105
|
+
useDefault: true,
|
|
106
|
+
default: false,
|
|
107
|
+
required: false
|
|
108
|
+
},
|
|
91
109
|
{
|
|
92
110
|
name: 'logOnly',
|
|
93
111
|
type: 'confirm',
|
|
@@ -97,17 +115,23 @@ export default async (argv, prompter, _options) => {
|
|
|
97
115
|
required: false
|
|
98
116
|
}
|
|
99
117
|
];
|
|
100
|
-
let { yes, recursive, createdb, cwd, tx, fast, logOnly } = await prompter.prompt(argv, questions);
|
|
118
|
+
let { yes, recursive, createdb, cwd, tx, fast, bundled, logOnly } = await prompter.prompt(argv, questions);
|
|
101
119
|
if (!yes) {
|
|
102
120
|
log.info('Operation cancelled.');
|
|
103
121
|
return;
|
|
104
122
|
}
|
|
105
123
|
log.debug(`Using current directory: ${cwd}`);
|
|
124
|
+
const { engine, capabilities } = getActiveEngine();
|
|
106
125
|
if (createdb) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
126
|
+
if (capabilities.createdb) {
|
|
127
|
+
log.info(`Creating database ${database}...`);
|
|
128
|
+
execSync(`createdb ${database}`, {
|
|
129
|
+
env: getSpawnEnvWithPg(pgEnv)
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
log.info(`Skipping createdb: the "${engine.name}" engine's instance is the database.`);
|
|
134
|
+
}
|
|
111
135
|
}
|
|
112
136
|
let packageName;
|
|
113
137
|
if (recursive) {
|
|
@@ -118,6 +142,7 @@ export default async (argv, prompter, _options) => {
|
|
|
118
142
|
deployment: {
|
|
119
143
|
useTx: tx !== false,
|
|
120
144
|
fast: fast !== false,
|
|
145
|
+
bundled: bundled === true,
|
|
121
146
|
usePlan: argv.usePlan !== false,
|
|
122
147
|
cache: argv.cache !== false,
|
|
123
148
|
logOnly: argv.logOnly !== false,
|
package/esm/commands/package.js
CHANGED
|
@@ -12,12 +12,14 @@ Options:
|
|
|
12
12
|
--pretty Pretty-print output (default: true)
|
|
13
13
|
--functionDelimiter <delimiter> Function delimiter (default: $EOFCODE$)
|
|
14
14
|
--outputDiff Export AST diff files when round-trip mismatch detected (default: false)
|
|
15
|
+
--bundle Also emit sql/<name>--<version>.bundle.tar.gz (default: true)
|
|
15
16
|
--cwd <directory> Working directory (default: current directory)
|
|
16
17
|
|
|
17
18
|
Examples:
|
|
18
19
|
pgpm package Package with defaults
|
|
19
20
|
pgpm package --no-plan Package without plan
|
|
20
21
|
pgpm package --outputDiff Package and export AST diff files if mismatch detected
|
|
22
|
+
pgpm package --no-bundle Package without emitting the bundle artifact
|
|
21
23
|
`;
|
|
22
24
|
export default async (argv, prompter, _options) => {
|
|
23
25
|
// Show usage if explicitly requested
|
|
@@ -53,9 +55,16 @@ export default async (argv, prompter, _options) => {
|
|
|
53
55
|
default: false,
|
|
54
56
|
useDefault: true,
|
|
55
57
|
required: false
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
type: 'confirm',
|
|
61
|
+
name: 'bundle',
|
|
62
|
+
default: true,
|
|
63
|
+
useDefault: true,
|
|
64
|
+
required: false
|
|
56
65
|
}
|
|
57
66
|
];
|
|
58
|
-
let { cwd, plan, pretty, functionDelimiter, outputDiff } = await prompter.prompt(argv, questions);
|
|
67
|
+
let { cwd, plan, pretty, functionDelimiter, outputDiff, bundle } = await prompter.prompt(argv, questions);
|
|
59
68
|
const project = new PgpmPackage(cwd);
|
|
60
69
|
project.ensureModule();
|
|
61
70
|
const info = project.getModuleInfo();
|
|
@@ -67,7 +76,8 @@ export default async (argv, prompter, _options) => {
|
|
|
67
76
|
packageDir: project.modulePath,
|
|
68
77
|
pretty,
|
|
69
78
|
functionDelimiter,
|
|
70
|
-
outputDiff
|
|
79
|
+
outputDiff,
|
|
80
|
+
bundle: bundle !== false
|
|
71
81
|
});
|
|
72
82
|
return argv;
|
|
73
83
|
};
|
package/esm/commands/revert.js
CHANGED
|
@@ -20,6 +20,7 @@ Options:
|
|
|
20
20
|
--to <target> Revert to specific change or tag
|
|
21
21
|
--to Interactive selection of deployed changes
|
|
22
22
|
--tx Use transactions (default: true)
|
|
23
|
+
--engine <name> Migration backend to revert in (default: pg; also pglite)
|
|
23
24
|
--cwd <directory> Working directory (default: current directory)
|
|
24
25
|
|
|
25
26
|
Examples:
|
package/esm/commands/verify.js
CHANGED
|
@@ -19,6 +19,7 @@ Options:
|
|
|
19
19
|
--package <name> Verify specific package
|
|
20
20
|
--to <target> Verify up to specific change or tag
|
|
21
21
|
--to Interactive selection of deployed changes
|
|
22
|
+
--engine <name> Migration backend to verify against (default: pg; also pglite)
|
|
22
23
|
--cwd <directory> Working directory (default: current directory)
|
|
23
24
|
|
|
24
25
|
Examples:
|
package/esm/commands.js
CHANGED
|
@@ -30,7 +30,13 @@ import tune from './commands/tune';
|
|
|
30
30
|
import updateCmd from './commands/update';
|
|
31
31
|
import upgrade from './commands/upgrade';
|
|
32
32
|
import verify from './commands/verify';
|
|
33
|
-
import { usageText } from './utils';
|
|
33
|
+
import { activateEngine, deactivateEngine, engineCommandBlocker, getActiveEngine, usageText } from './utils';
|
|
34
|
+
/**
|
|
35
|
+
* Commands that never talk to a database and must not activate a driver.
|
|
36
|
+
* `init` owns its own `--pglite` meaning (scaffold from the PGlite boilerplates),
|
|
37
|
+
* and it runs before the plugin it would scaffold is even installed.
|
|
38
|
+
*/
|
|
39
|
+
const ENGINE_EXEMPT_COMMANDS = new Set(['init']);
|
|
34
40
|
const withPgTeardown = (fn, skipTeardown = false) => async (...args) => {
|
|
35
41
|
try {
|
|
36
42
|
await fn(...args);
|
|
@@ -137,7 +143,27 @@ export const commands = async (argv, prompter, options) => {
|
|
|
137
143
|
console.log(usageText);
|
|
138
144
|
await cliExitWithError(`Unknown command: ${command}`, { beforeExit: teardownPgPools });
|
|
139
145
|
}
|
|
140
|
-
|
|
146
|
+
// Activate the selected migration backend (`--engine`/`--driver`/`--pglite` or
|
|
147
|
+
// pgpm.json) before the command runs: the driver plugin registers its
|
|
148
|
+
// pool/client factories, so the unmodified engine targets it. The built-in
|
|
149
|
+
// `pg` engine activates nothing and behaves exactly as before.
|
|
150
|
+
const engineArgv = newArgv;
|
|
151
|
+
const { engine, capabilities } = ENGINE_EXEMPT_COMMANDS.has(command)
|
|
152
|
+
? getActiveEngine()
|
|
153
|
+
: await activateEngine(engineArgv, engineArgv.cwd).catch(async (error) => {
|
|
154
|
+
await cliExitWithError(error.message, { beforeExit: teardownPgPools });
|
|
155
|
+
throw error;
|
|
156
|
+
});
|
|
157
|
+
try {
|
|
158
|
+
const blocked = engineCommandBlocker(command, engine, capabilities);
|
|
159
|
+
if (blocked) {
|
|
160
|
+
await cliExitWithError(blocked, { beforeExit: teardownPgPools });
|
|
161
|
+
}
|
|
162
|
+
await commandFn(newArgv, prompter, options);
|
|
163
|
+
}
|
|
164
|
+
finally {
|
|
165
|
+
await deactivateEngine();
|
|
166
|
+
}
|
|
141
167
|
prompter.close();
|
|
142
168
|
return argv;
|
|
143
169
|
};
|
package/esm/utils/display.js
CHANGED
|
@@ -50,6 +50,11 @@ export const usageText = `
|
|
|
50
50
|
-h, --help Display this help information
|
|
51
51
|
-v, --version Display version information
|
|
52
52
|
--cwd <directory> Working directory (default: current directory)
|
|
53
|
+
--engine <name> Migration backend: pg (default, Postgres server) or
|
|
54
|
+
pglite (in-process WASM Postgres, no server). Also set by
|
|
55
|
+
the "engine" key of pgpm.json or PGPM_ENGINE.
|
|
56
|
+
--driver <pkg> Driver plugin package backing the engine (escape hatch)
|
|
57
|
+
--pglite[=dataDir] Sugar for --engine pglite, persisted to <dataDir> if given
|
|
53
58
|
|
|
54
59
|
Individual Command Help:
|
|
55
60
|
pgpm <command> --help Display detailed help for specific command
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Commands that need a capability the backend may not have. Gating is declared
|
|
3
|
+
* here rather than branching per backend inside each command, so a new driver
|
|
4
|
+
* plugin only has to describe itself through {@link PgpmDriverCapabilities}.
|
|
5
|
+
*/
|
|
6
|
+
const COMMAND_REQUIREMENTS = {
|
|
7
|
+
docker: 'serverLifecycle',
|
|
8
|
+
kill: 'serverLifecycle',
|
|
9
|
+
tune: 'serverLifecycle',
|
|
10
|
+
'admin-users': 'multiConnection',
|
|
11
|
+
dump: 'dump',
|
|
12
|
+
};
|
|
13
|
+
const REQUIREMENT_REASONS = {
|
|
14
|
+
createdb: 'it cannot create databases (the instance is the database)',
|
|
15
|
+
dump: 'it has no pg_dump',
|
|
16
|
+
serverLifecycle: 'it has no server to manage',
|
|
17
|
+
multiConnection: 'it is a single-session backend',
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* The reason a command cannot run on the active engine, or undefined when it can.
|
|
21
|
+
*/
|
|
22
|
+
export const engineCommandBlocker = (command, engine, capabilities) => {
|
|
23
|
+
const requirement = COMMAND_REQUIREMENTS[command];
|
|
24
|
+
if (!requirement || capabilities[requirement])
|
|
25
|
+
return undefined;
|
|
26
|
+
return (`pgpm ${command} is not supported by the "${engine.name}" engine — ` +
|
|
27
|
+
`${REQUIREMENT_REASONS[requirement]}.`);
|
|
28
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { getEnvOptions } from '@pgpmjs/env';
|
|
2
|
+
import { BUILTIN_ENGINES, DEFAULT_ENGINE, } from '@pgpmjs/types';
|
|
3
|
+
import { activateDriver, driverOverrideFromArgv, PGLITE_DRIVER_PLUGIN } from './driver';
|
|
4
|
+
/** Everything a real Postgres server can do — the built-in `pg` engine. */
|
|
5
|
+
export const SERVER_CAPABILITIES = {
|
|
6
|
+
createdb: true,
|
|
7
|
+
dump: true,
|
|
8
|
+
serverLifecycle: true,
|
|
9
|
+
multiConnection: true,
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* The engines available by name: the built-ins, overridden/extended by the
|
|
13
|
+
* `engines` block of `pgpm.json` (sqitch's `[engine "name"]` sections).
|
|
14
|
+
*
|
|
15
|
+
* A configured entry is merged over its built-in, so declaring only options
|
|
16
|
+
* (e.g. `engines.pglite.options.dataDir`) keeps the built-in plugin.
|
|
17
|
+
*/
|
|
18
|
+
export const engineDefinitions = (config) => {
|
|
19
|
+
const definitions = { ...BUILTIN_ENGINES };
|
|
20
|
+
for (const [name, configured] of Object.entries(config.engines ?? {})) {
|
|
21
|
+
definitions[name] = { ...definitions[name], ...configured };
|
|
22
|
+
}
|
|
23
|
+
return definitions;
|
|
24
|
+
};
|
|
25
|
+
const definitionToDriver = (definition, options) => definition.plugin
|
|
26
|
+
? { plugin: definition.plugin, options: { ...definition.options, ...options } }
|
|
27
|
+
: undefined;
|
|
28
|
+
const lookupEngine = (name, config, options) => {
|
|
29
|
+
const definition = engineDefinitions(config)[name];
|
|
30
|
+
if (!definition) {
|
|
31
|
+
const known = Object.keys(engineDefinitions(config)).sort().join(', ');
|
|
32
|
+
throw new Error(`Unknown pgpm engine "${name}". Known engines: ${known}.\n` +
|
|
33
|
+
'Declare it in the "engines" block of pgpm.json, or name its plugin with --driver <package>.');
|
|
34
|
+
}
|
|
35
|
+
return { name, driver: definitionToDriver(definition, options) };
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Resolve which engine a command targets, mirroring sqitch's `core.engine` model:
|
|
39
|
+
* a short engine name selects the backend, and the built-in default is `pg`.
|
|
40
|
+
*
|
|
41
|
+
* Precedence (first match wins):
|
|
42
|
+
* 1. `--driver <package>` — name a driver plugin directly (escape hatch)
|
|
43
|
+
* 2. `--pglite[=dataDir]` — sugar for `--engine pglite`
|
|
44
|
+
* 3. `--engine <name>`
|
|
45
|
+
* 4. the `driver` block of `pgpm.json` — plugin-level configuration
|
|
46
|
+
* 5. the `engine` key of `pgpm.json` / `PGPM_ENGINE`
|
|
47
|
+
* 6. `pg`, the built-in server path
|
|
48
|
+
*/
|
|
49
|
+
export const resolveEngine = (argv, config) => {
|
|
50
|
+
const override = driverOverrideFromArgv(argv);
|
|
51
|
+
if (override) {
|
|
52
|
+
if (override.plugin === PGLITE_DRIVER_PLUGIN && !argv.driver) {
|
|
53
|
+
// `--pglite` is the pglite engine, so it inherits that engine's configured
|
|
54
|
+
// options (e.g. a dataDir declared in pgpm.json) instead of bypassing them.
|
|
55
|
+
return lookupEngine('pglite', config, override.options);
|
|
56
|
+
}
|
|
57
|
+
return { name: override.plugin, driver: override };
|
|
58
|
+
}
|
|
59
|
+
if (argv.engine)
|
|
60
|
+
return lookupEngine(argv.engine, config);
|
|
61
|
+
if (config.driver)
|
|
62
|
+
return { name: config.driver.plugin, driver: config.driver };
|
|
63
|
+
return lookupEngine(config.engine ?? DEFAULT_ENGINE, config);
|
|
64
|
+
};
|
|
65
|
+
let active;
|
|
66
|
+
/**
|
|
67
|
+
* The engine activated for the running command. Commands read this to skip
|
|
68
|
+
* server-only steps (e.g. `deploy --createdb`) instead of hard-coding backends.
|
|
69
|
+
* Defaults to the built-in server path when nothing has been activated.
|
|
70
|
+
*/
|
|
71
|
+
export const getActiveEngine = () => active ?? { engine: { name: DEFAULT_ENGINE }, capabilities: SERVER_CAPABILITIES };
|
|
72
|
+
/**
|
|
73
|
+
* Resolve the engine from argv + `pgpm.json` and activate its driver plugin.
|
|
74
|
+
* The driver has registered its pool/client factories by the time this resolves,
|
|
75
|
+
* so the unmodified pgpm engine runs against the selected backend.
|
|
76
|
+
*/
|
|
77
|
+
export const activateEngine = async (argv, cwd = process.cwd()) => {
|
|
78
|
+
const config = getEnvOptions({}, cwd);
|
|
79
|
+
const engine = resolveEngine(argv, config);
|
|
80
|
+
const session = await activateDriver(engine.driver, undefined, cwd);
|
|
81
|
+
active = { engine, session, capabilities: session?.capabilities ?? SERVER_CAPABILITIES };
|
|
82
|
+
return active;
|
|
83
|
+
};
|
|
84
|
+
/** Tear down the active driver session and restore the built-in server path. */
|
|
85
|
+
export const deactivateEngine = async () => {
|
|
86
|
+
const session = active?.session;
|
|
87
|
+
active = undefined;
|
|
88
|
+
await session?.teardown();
|
|
89
|
+
};
|
package/esm/utils/index.js
CHANGED
|
@@ -3,6 +3,8 @@ export * from './deployed-changes';
|
|
|
3
3
|
export * from './display';
|
|
4
4
|
export * from './doctor';
|
|
5
5
|
export * from './driver';
|
|
6
|
+
export * from './engine';
|
|
7
|
+
export * from './engine-gating';
|
|
6
8
|
export * from './module-utils';
|
|
7
9
|
export * from './npm-version';
|
|
8
10
|
export * from './package-alias';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pgpm",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.15.0",
|
|
4
4
|
"author": "Constructive <developers@constructive.io>",
|
|
5
5
|
"description": "PostgreSQL Package Manager - Database migration and package management CLI",
|
|
6
6
|
"main": "index.js",
|
|
@@ -46,19 +46,19 @@
|
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@inquirerer/utils": "^3.3.9",
|
|
49
|
-
"@pgpmjs/core": "^7.
|
|
50
|
-
"@pgpmjs/env": "^2.
|
|
51
|
-
"@pgpmjs/export": "^1.12.
|
|
49
|
+
"@pgpmjs/core": "^7.16.0",
|
|
50
|
+
"@pgpmjs/env": "^2.39.0",
|
|
51
|
+
"@pgpmjs/export": "^1.12.3",
|
|
52
52
|
"@pgpmjs/logger": "^2.22.0",
|
|
53
|
-
"@pgpmjs/slice": "^0.10.
|
|
54
|
-
"@pgpmjs/types": "^2.
|
|
53
|
+
"@pgpmjs/slice": "^0.10.2",
|
|
54
|
+
"@pgpmjs/types": "^2.47.0",
|
|
55
55
|
"@pgsql/quotes": "^18.1.0",
|
|
56
56
|
"appstash": "^0.7.0",
|
|
57
57
|
"find-and-require-package-json": "^0.9.1",
|
|
58
58
|
"genomic": "^5.6.2",
|
|
59
59
|
"inquirerer": "^4.9.1",
|
|
60
60
|
"js-yaml": "^4.1.0",
|
|
61
|
-
"pg-cache": "^3.23.
|
|
61
|
+
"pg-cache": "^3.23.2",
|
|
62
62
|
"pg-env": "^1.26.0",
|
|
63
63
|
"pgsql-deparser": "^18.1.1",
|
|
64
64
|
"semver": "^7.8.1",
|
|
@@ -77,5 +77,5 @@
|
|
|
77
77
|
"pg",
|
|
78
78
|
"pgsql"
|
|
79
79
|
],
|
|
80
|
-
"gitHead": "
|
|
80
|
+
"gitHead": "0286d994d98717cb9b28842233d2db6d1e37c48e"
|
|
81
81
|
}
|
package/utils/display.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const usageText = "\n Usage: pgpm <command> [options]\n\n Core Database Operations:\n add Add database changes to plans and create SQL files\n deploy Deploy database changes and migrations\n verify Verify database state and migrations\n revert Revert database changes and migrations\n\n Project Management:\n init Initialize workspace or module\n extension Manage module dependencies\n plan Generate module deployment plans\n package Package module for distribution\n sync-versions Sync .control/Makefile/sql metadata to package.json versions\n export Export database migrations from existing databases\n update Update pgpm to the latest version\n cache Manage cached templates (clean)\n upgrade Upgrade installed pgpm modules to latest versions (alias: up)\n\n Database Administration:\n dump Dump a database to a sql file\n kill Terminate database connections and optionally drop databases\n install Install database modules\n tag Add tags to changes for versioning\n clear Clear database state\n remove Remove database changes\n analyze Analyze database structure\n rename Rename database changes\n admin-users Manage admin users\n tune Tune PostgreSQL for throwaway environments (CI/test)\n\n Testing:\n test-packages Run integration tests on all workspace packages\n\n Migration Tools:\n migrate Migration management subcommands\n init Initialize migration tracking\n status Show migration status\n list List all changes\n deps Show change dependencies\n \n Development Tools:\n docker Manage Docker containers (start/stop/ls, --minio)\n doctor Check local dependencies (node, docker, psql) with install guidance\n env Manage environment variables (--supabase, --minio)\n test-packages Run integration tests on workspace packages\n \n Global Options:\n -h, --help Display this help information\n -v, --version Display version information\n --cwd <directory> Working directory (default: current directory)\n\n Individual Command Help:\n pgpm <command> --help Display detailed help for specific command\n pgpm <command> -h Display detailed help for specific command\n\n Examples:\n pgpm deploy --help Show deploy command options\n pgpm init workspace Initialize new workspace\n pgpm install @pgpm/base32 Install a database module\n ";
|
|
1
|
+
export declare const usageText = "\n Usage: pgpm <command> [options]\n\n Core Database Operations:\n add Add database changes to plans and create SQL files\n deploy Deploy database changes and migrations\n verify Verify database state and migrations\n revert Revert database changes and migrations\n\n Project Management:\n init Initialize workspace or module\n extension Manage module dependencies\n plan Generate module deployment plans\n package Package module for distribution\n sync-versions Sync .control/Makefile/sql metadata to package.json versions\n export Export database migrations from existing databases\n update Update pgpm to the latest version\n cache Manage cached templates (clean)\n upgrade Upgrade installed pgpm modules to latest versions (alias: up)\n\n Database Administration:\n dump Dump a database to a sql file\n kill Terminate database connections and optionally drop databases\n install Install database modules\n tag Add tags to changes for versioning\n clear Clear database state\n remove Remove database changes\n analyze Analyze database structure\n rename Rename database changes\n admin-users Manage admin users\n tune Tune PostgreSQL for throwaway environments (CI/test)\n\n Testing:\n test-packages Run integration tests on all workspace packages\n\n Migration Tools:\n migrate Migration management subcommands\n init Initialize migration tracking\n status Show migration status\n list List all changes\n deps Show change dependencies\n \n Development Tools:\n docker Manage Docker containers (start/stop/ls, --minio)\n doctor Check local dependencies (node, docker, psql) with install guidance\n env Manage environment variables (--supabase, --minio)\n test-packages Run integration tests on workspace packages\n \n Global Options:\n -h, --help Display this help information\n -v, --version Display version information\n --cwd <directory> Working directory (default: current directory)\n --engine <name> Migration backend: pg (default, Postgres server) or\n pglite (in-process WASM Postgres, no server). Also set by\n the \"engine\" key of pgpm.json or PGPM_ENGINE.\n --driver <pkg> Driver plugin package backing the engine (escape hatch)\n --pglite[=dataDir] Sugar for --engine pglite, persisted to <dataDir> if given\n\n Individual Command Help:\n pgpm <command> --help Display detailed help for specific command\n pgpm <command> -h Display detailed help for specific command\n\n Examples:\n pgpm deploy --help Show deploy command options\n pgpm init workspace Initialize new workspace\n pgpm install @pgpm/base32 Install a database module\n ";
|
package/utils/display.js
CHANGED
|
@@ -53,6 +53,11 @@ exports.usageText = `
|
|
|
53
53
|
-h, --help Display this help information
|
|
54
54
|
-v, --version Display version information
|
|
55
55
|
--cwd <directory> Working directory (default: current directory)
|
|
56
|
+
--engine <name> Migration backend: pg (default, Postgres server) or
|
|
57
|
+
pglite (in-process WASM Postgres, no server). Also set by
|
|
58
|
+
the "engine" key of pgpm.json or PGPM_ENGINE.
|
|
59
|
+
--driver <pkg> Driver plugin package backing the engine (escape hatch)
|
|
60
|
+
--pglite[=dataDir] Sugar for --engine pglite, persisted to <dataDir> if given
|
|
56
61
|
|
|
57
62
|
Individual Command Help:
|
|
58
63
|
pgpm <command> --help Display detailed help for specific command
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { PgpmDriverCapabilities } from '@pgpmjs/types';
|
|
2
|
+
import { ResolvedEngine } from './engine';
|
|
3
|
+
/**
|
|
4
|
+
* The reason a command cannot run on the active engine, or undefined when it can.
|
|
5
|
+
*/
|
|
6
|
+
export declare const engineCommandBlocker: (command: string, engine: ResolvedEngine, capabilities: PgpmDriverCapabilities) => string | undefined;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.engineCommandBlocker = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Commands that need a capability the backend may not have. Gating is declared
|
|
6
|
+
* here rather than branching per backend inside each command, so a new driver
|
|
7
|
+
* plugin only has to describe itself through {@link PgpmDriverCapabilities}.
|
|
8
|
+
*/
|
|
9
|
+
const COMMAND_REQUIREMENTS = {
|
|
10
|
+
docker: 'serverLifecycle',
|
|
11
|
+
kill: 'serverLifecycle',
|
|
12
|
+
tune: 'serverLifecycle',
|
|
13
|
+
'admin-users': 'multiConnection',
|
|
14
|
+
dump: 'dump',
|
|
15
|
+
};
|
|
16
|
+
const REQUIREMENT_REASONS = {
|
|
17
|
+
createdb: 'it cannot create databases (the instance is the database)',
|
|
18
|
+
dump: 'it has no pg_dump',
|
|
19
|
+
serverLifecycle: 'it has no server to manage',
|
|
20
|
+
multiConnection: 'it is a single-session backend',
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* The reason a command cannot run on the active engine, or undefined when it can.
|
|
24
|
+
*/
|
|
25
|
+
const engineCommandBlocker = (command, engine, capabilities) => {
|
|
26
|
+
const requirement = COMMAND_REQUIREMENTS[command];
|
|
27
|
+
if (!requirement || capabilities[requirement])
|
|
28
|
+
return undefined;
|
|
29
|
+
return (`pgpm ${command} is not supported by the "${engine.name}" engine — ` +
|
|
30
|
+
`${REQUIREMENT_REASONS[requirement]}.`);
|
|
31
|
+
};
|
|
32
|
+
exports.engineCommandBlocker = engineCommandBlocker;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { PgpmDriverCapabilities, PgpmDriverConfig, PgpmDriverSession, PgpmEngineConfig, PgpmOptions } from '@pgpmjs/types';
|
|
2
|
+
/** Everything a real Postgres server can do — the built-in `pg` engine. */
|
|
3
|
+
export declare const SERVER_CAPABILITIES: PgpmDriverCapabilities;
|
|
4
|
+
/** The engine/driver selectors every command accepts. */
|
|
5
|
+
export interface EngineArgv {
|
|
6
|
+
engine?: string;
|
|
7
|
+
driver?: string;
|
|
8
|
+
pglite?: boolean | string;
|
|
9
|
+
}
|
|
10
|
+
/** The engine a command runs against, plus the driver plugin backing it. */
|
|
11
|
+
export interface ResolvedEngine {
|
|
12
|
+
/** Engine name, for messages: a registered name or a plugin package. */
|
|
13
|
+
name: string;
|
|
14
|
+
/** Driver plugin to activate; undefined = built-in `pg` (server) path. */
|
|
15
|
+
driver?: PgpmDriverConfig;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The engines available by name: the built-ins, overridden/extended by the
|
|
19
|
+
* `engines` block of `pgpm.json` (sqitch's `[engine "name"]` sections).
|
|
20
|
+
*
|
|
21
|
+
* A configured entry is merged over its built-in, so declaring only options
|
|
22
|
+
* (e.g. `engines.pglite.options.dataDir`) keeps the built-in plugin.
|
|
23
|
+
*/
|
|
24
|
+
export declare const engineDefinitions: (config: PgpmOptions) => Record<string, PgpmEngineConfig>;
|
|
25
|
+
/**
|
|
26
|
+
* Resolve which engine a command targets, mirroring sqitch's `core.engine` model:
|
|
27
|
+
* a short engine name selects the backend, and the built-in default is `pg`.
|
|
28
|
+
*
|
|
29
|
+
* Precedence (first match wins):
|
|
30
|
+
* 1. `--driver <package>` — name a driver plugin directly (escape hatch)
|
|
31
|
+
* 2. `--pglite[=dataDir]` — sugar for `--engine pglite`
|
|
32
|
+
* 3. `--engine <name>`
|
|
33
|
+
* 4. the `driver` block of `pgpm.json` — plugin-level configuration
|
|
34
|
+
* 5. the `engine` key of `pgpm.json` / `PGPM_ENGINE`
|
|
35
|
+
* 6. `pg`, the built-in server path
|
|
36
|
+
*/
|
|
37
|
+
export declare const resolveEngine: (argv: EngineArgv, config: PgpmOptions) => ResolvedEngine;
|
|
38
|
+
/** The engine activated for the running command. */
|
|
39
|
+
export interface ActiveEngine {
|
|
40
|
+
engine: ResolvedEngine;
|
|
41
|
+
session?: PgpmDriverSession;
|
|
42
|
+
capabilities: PgpmDriverCapabilities;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The engine activated for the running command. Commands read this to skip
|
|
46
|
+
* server-only steps (e.g. `deploy --createdb`) instead of hard-coding backends.
|
|
47
|
+
* Defaults to the built-in server path when nothing has been activated.
|
|
48
|
+
*/
|
|
49
|
+
export declare const getActiveEngine: () => ActiveEngine;
|
|
50
|
+
/**
|
|
51
|
+
* Resolve the engine from argv + `pgpm.json` and activate its driver plugin.
|
|
52
|
+
* The driver has registered its pool/client factories by the time this resolves,
|
|
53
|
+
* so the unmodified pgpm engine runs against the selected backend.
|
|
54
|
+
*/
|
|
55
|
+
export declare const activateEngine: (argv: EngineArgv, cwd?: string) => Promise<ActiveEngine>;
|
|
56
|
+
/** Tear down the active driver session and restore the built-in server path. */
|
|
57
|
+
export declare const deactivateEngine: () => Promise<void>;
|
package/utils/engine.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deactivateEngine = exports.activateEngine = exports.getActiveEngine = exports.resolveEngine = exports.engineDefinitions = exports.SERVER_CAPABILITIES = void 0;
|
|
4
|
+
const env_1 = require("@pgpmjs/env");
|
|
5
|
+
const types_1 = require("@pgpmjs/types");
|
|
6
|
+
const driver_1 = require("./driver");
|
|
7
|
+
/** Everything a real Postgres server can do — the built-in `pg` engine. */
|
|
8
|
+
exports.SERVER_CAPABILITIES = {
|
|
9
|
+
createdb: true,
|
|
10
|
+
dump: true,
|
|
11
|
+
serverLifecycle: true,
|
|
12
|
+
multiConnection: true,
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* The engines available by name: the built-ins, overridden/extended by the
|
|
16
|
+
* `engines` block of `pgpm.json` (sqitch's `[engine "name"]` sections).
|
|
17
|
+
*
|
|
18
|
+
* A configured entry is merged over its built-in, so declaring only options
|
|
19
|
+
* (e.g. `engines.pglite.options.dataDir`) keeps the built-in plugin.
|
|
20
|
+
*/
|
|
21
|
+
const engineDefinitions = (config) => {
|
|
22
|
+
const definitions = { ...types_1.BUILTIN_ENGINES };
|
|
23
|
+
for (const [name, configured] of Object.entries(config.engines ?? {})) {
|
|
24
|
+
definitions[name] = { ...definitions[name], ...configured };
|
|
25
|
+
}
|
|
26
|
+
return definitions;
|
|
27
|
+
};
|
|
28
|
+
exports.engineDefinitions = engineDefinitions;
|
|
29
|
+
const definitionToDriver = (definition, options) => definition.plugin
|
|
30
|
+
? { plugin: definition.plugin, options: { ...definition.options, ...options } }
|
|
31
|
+
: undefined;
|
|
32
|
+
const lookupEngine = (name, config, options) => {
|
|
33
|
+
const definition = (0, exports.engineDefinitions)(config)[name];
|
|
34
|
+
if (!definition) {
|
|
35
|
+
const known = Object.keys((0, exports.engineDefinitions)(config)).sort().join(', ');
|
|
36
|
+
throw new Error(`Unknown pgpm engine "${name}". Known engines: ${known}.\n` +
|
|
37
|
+
'Declare it in the "engines" block of pgpm.json, or name its plugin with --driver <package>.');
|
|
38
|
+
}
|
|
39
|
+
return { name, driver: definitionToDriver(definition, options) };
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Resolve which engine a command targets, mirroring sqitch's `core.engine` model:
|
|
43
|
+
* a short engine name selects the backend, and the built-in default is `pg`.
|
|
44
|
+
*
|
|
45
|
+
* Precedence (first match wins):
|
|
46
|
+
* 1. `--driver <package>` — name a driver plugin directly (escape hatch)
|
|
47
|
+
* 2. `--pglite[=dataDir]` — sugar for `--engine pglite`
|
|
48
|
+
* 3. `--engine <name>`
|
|
49
|
+
* 4. the `driver` block of `pgpm.json` — plugin-level configuration
|
|
50
|
+
* 5. the `engine` key of `pgpm.json` / `PGPM_ENGINE`
|
|
51
|
+
* 6. `pg`, the built-in server path
|
|
52
|
+
*/
|
|
53
|
+
const resolveEngine = (argv, config) => {
|
|
54
|
+
const override = (0, driver_1.driverOverrideFromArgv)(argv);
|
|
55
|
+
if (override) {
|
|
56
|
+
if (override.plugin === driver_1.PGLITE_DRIVER_PLUGIN && !argv.driver) {
|
|
57
|
+
// `--pglite` is the pglite engine, so it inherits that engine's configured
|
|
58
|
+
// options (e.g. a dataDir declared in pgpm.json) instead of bypassing them.
|
|
59
|
+
return lookupEngine('pglite', config, override.options);
|
|
60
|
+
}
|
|
61
|
+
return { name: override.plugin, driver: override };
|
|
62
|
+
}
|
|
63
|
+
if (argv.engine)
|
|
64
|
+
return lookupEngine(argv.engine, config);
|
|
65
|
+
if (config.driver)
|
|
66
|
+
return { name: config.driver.plugin, driver: config.driver };
|
|
67
|
+
return lookupEngine(config.engine ?? types_1.DEFAULT_ENGINE, config);
|
|
68
|
+
};
|
|
69
|
+
exports.resolveEngine = resolveEngine;
|
|
70
|
+
let active;
|
|
71
|
+
/**
|
|
72
|
+
* The engine activated for the running command. Commands read this to skip
|
|
73
|
+
* server-only steps (e.g. `deploy --createdb`) instead of hard-coding backends.
|
|
74
|
+
* Defaults to the built-in server path when nothing has been activated.
|
|
75
|
+
*/
|
|
76
|
+
const getActiveEngine = () => active ?? { engine: { name: types_1.DEFAULT_ENGINE }, capabilities: exports.SERVER_CAPABILITIES };
|
|
77
|
+
exports.getActiveEngine = getActiveEngine;
|
|
78
|
+
/**
|
|
79
|
+
* Resolve the engine from argv + `pgpm.json` and activate its driver plugin.
|
|
80
|
+
* The driver has registered its pool/client factories by the time this resolves,
|
|
81
|
+
* so the unmodified pgpm engine runs against the selected backend.
|
|
82
|
+
*/
|
|
83
|
+
const activateEngine = async (argv, cwd = process.cwd()) => {
|
|
84
|
+
const config = (0, env_1.getEnvOptions)({}, cwd);
|
|
85
|
+
const engine = (0, exports.resolveEngine)(argv, config);
|
|
86
|
+
const session = await (0, driver_1.activateDriver)(engine.driver, undefined, cwd);
|
|
87
|
+
active = { engine, session, capabilities: session?.capabilities ?? exports.SERVER_CAPABILITIES };
|
|
88
|
+
return active;
|
|
89
|
+
};
|
|
90
|
+
exports.activateEngine = activateEngine;
|
|
91
|
+
/** Tear down the active driver session and restore the built-in server path. */
|
|
92
|
+
const deactivateEngine = async () => {
|
|
93
|
+
const session = active?.session;
|
|
94
|
+
active = undefined;
|
|
95
|
+
await session?.teardown();
|
|
96
|
+
};
|
|
97
|
+
exports.deactivateEngine = deactivateEngine;
|
package/utils/index.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ export * from './deployed-changes';
|
|
|
3
3
|
export * from './display';
|
|
4
4
|
export * from './doctor';
|
|
5
5
|
export * from './driver';
|
|
6
|
+
export * from './engine';
|
|
7
|
+
export * from './engine-gating';
|
|
6
8
|
export * from './module-utils';
|
|
7
9
|
export * from './npm-version';
|
|
8
10
|
export * from './package-alias';
|
package/utils/index.js
CHANGED
|
@@ -19,6 +19,8 @@ __exportStar(require("./deployed-changes"), exports);
|
|
|
19
19
|
__exportStar(require("./display"), exports);
|
|
20
20
|
__exportStar(require("./doctor"), exports);
|
|
21
21
|
__exportStar(require("./driver"), exports);
|
|
22
|
+
__exportStar(require("./engine"), exports);
|
|
23
|
+
__exportStar(require("./engine-gating"), exports);
|
|
22
24
|
__exportStar(require("./module-utils"), exports);
|
|
23
25
|
__exportStar(require("./npm-version"), exports);
|
|
24
26
|
__exportStar(require("./package-alias"), exports);
|