pgpm 5.15.4 → 5.16.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.
@@ -0,0 +1,3 @@
1
+ import { CLIOptions, Inquirerer } from 'inquirerer';
2
+ declare const _default: (argv: Partial<Record<string, any>>, _prompter: Inquirerer, _options: CLIOptions) => Promise<Partial<Record<string, any>>>;
3
+ export default _default;
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@pgpmjs/core");
4
+ const fs_1 = require("fs");
5
+ const os_1 = require("os");
6
+ const path_1 = require("path");
7
+ const materializeUsageText = `
8
+ Materialize Command:
9
+
10
+ pgpm materialize <target> [OPTIONS]
11
+
12
+ Transpile an apply-proxy module (pgpm.apply.json) once and write the result
13
+ as a plain, deployable PGPM module (deploy/revert/verify + pgpm.plan +
14
+ .control, with the transforms baked into the SQL). The output has no
15
+ pgpm.apply.json and deploys like any hand-written module.
16
+
17
+ The proxy stays in the repo as the recipe; the materialized module is its
18
+ committed build artifact. Re-run when the source or provider binding changes.
19
+
20
+ Arguments:
21
+ target Name of the apply-proxy module in the workspace.
22
+
23
+ Options:
24
+ --help, -h Show this help message
25
+ --output <dir> Output directory (default: <workspace>/materialized/<name>)
26
+ --overwrite Replace an existing output directory
27
+ --check Re-materialize to a temp dir and diff against --output;
28
+ exit non-zero on any difference (drift gate for CI)
29
+ --cwd <directory> Working directory (default: current directory)
30
+
31
+ Examples:
32
+ pgpm materialize vendor-app-ported
33
+ pgpm materialize vendor-app-ported --output extensions/vendor-app-ported --overwrite
34
+ pgpm materialize vendor-app-ported --check
35
+ `;
36
+ /** Recursively list files in a directory as workspace-relative POSIX paths. */
37
+ function listFiles(dir) {
38
+ const out = [];
39
+ const walk = (current) => {
40
+ for (const entry of (0, fs_1.readdirSync)(current, { withFileTypes: true })) {
41
+ const full = (0, path_1.join)(current, entry.name);
42
+ if (entry.isDirectory())
43
+ walk(full);
44
+ else
45
+ out.push((0, path_1.relative)(dir, full).replace(/\\/g, '/'));
46
+ }
47
+ };
48
+ walk(dir);
49
+ return out.sort();
50
+ }
51
+ /** Byte-level diff between two materialized module directories. */
52
+ function diffDirs(expectedDir, actualDir) {
53
+ const expected = new Set(listFiles(expectedDir));
54
+ const actual = new Set(listFiles(actualDir));
55
+ const diffs = [];
56
+ for (const file of actual) {
57
+ if (!expected.has(file))
58
+ diffs.push(`missing from output: ${file}`);
59
+ }
60
+ for (const file of expected) {
61
+ if (!actual.has(file)) {
62
+ diffs.push(`stale in output: ${file}`);
63
+ continue;
64
+ }
65
+ const a = (0, fs_1.readFileSync)((0, path_1.join)(expectedDir, file));
66
+ const b = (0, fs_1.readFileSync)((0, path_1.join)(actualDir, file));
67
+ if (!a.equals(b))
68
+ diffs.push(`content differs: ${file}`);
69
+ }
70
+ return diffs.sort();
71
+ }
72
+ exports.default = async (argv, _prompter, _options) => {
73
+ if (argv.help || argv.h) {
74
+ console.log(materializeUsageText);
75
+ process.exit(0);
76
+ }
77
+ const cwd = argv.cwd ?? process.cwd();
78
+ const target = argv._?.[0] ?? argv.target;
79
+ if (!target) {
80
+ console.error('Error: a target apply-proxy module name is required.');
81
+ console.log(materializeUsageText);
82
+ process.exit(1);
83
+ }
84
+ const project = new core_1.PgpmPackage(cwd);
85
+ project.ensureWorkspace();
86
+ const workspacePath = project.workspacePath;
87
+ const moduleMap = project.getModuleMap();
88
+ const check = Boolean(argv.check);
89
+ const overwrite = Boolean(argv.overwrite);
90
+ const outDir = argv.output
91
+ ? (0, path_1.resolve)(cwd, argv.output)
92
+ : (0, path_1.resolve)(workspacePath, 'materialized', String(target));
93
+ if (check) {
94
+ if (!(0, fs_1.existsSync)(outDir)) {
95
+ console.error(`Error: --check requires an existing output at ${outDir}. Run \`pgpm materialize ${target}\` first.`);
96
+ process.exit(1);
97
+ }
98
+ const tmp = (0, fs_1.mkdtempSync)((0, path_1.join)((0, os_1.tmpdir)(), `pgpm-materialize-check-`));
99
+ try {
100
+ const { spec } = await (0, core_1.materializeWorkspaceTarget)({ workspacePath, moduleMap, target, outDir: tmp });
101
+ const diffs = diffDirs(outDir, tmp);
102
+ if (diffs.length > 0) {
103
+ console.error(`Drift: materialized "${target}" (from "${spec.source.module}") differs from ${outDir}:`);
104
+ for (const d of diffs)
105
+ console.error(` - ${d}`);
106
+ console.error(`\nRe-run \`pgpm materialize ${target} --overwrite\` and commit the result.`);
107
+ process.exit(1);
108
+ }
109
+ console.log(`✔ ${target} is up to date with ${outDir} (byte-identical).`);
110
+ }
111
+ finally {
112
+ (0, fs_1.rmSync)(tmp, { recursive: true, force: true });
113
+ }
114
+ return argv;
115
+ }
116
+ if ((0, fs_1.existsSync)(outDir) && !overwrite) {
117
+ console.error(`Error: ${outDir} already exists. Pass --overwrite to replace it.`);
118
+ process.exit(1);
119
+ }
120
+ if ((0, fs_1.existsSync)(outDir))
121
+ (0, fs_1.rmSync)(outDir, { recursive: true, force: true });
122
+ const { bundle, spec } = await (0, core_1.materializeWorkspaceTarget)({ workspacePath, moduleMap, target, outDir });
123
+ console.log(`✔ Materialized "${target}" from "${spec.source.module}"`);
124
+ console.log(` Output: ${outDir}`);
125
+ console.log(` Changes: ${bundle.changes.length}`);
126
+ console.log(` Digest: ${bundle.manifest.digest}`);
127
+ console.log(`\nDeploy it as a plain module (no pgpm.apply.json needed).`);
128
+ return argv;
129
+ };
package/commands.js CHANGED
@@ -22,6 +22,7 @@ const extension_1 = __importDefault(require("./commands/extension"));
22
22
  const init_1 = __importDefault(require("./commands/init"));
23
23
  const install_1 = __importDefault(require("./commands/install"));
24
24
  const kill_1 = __importDefault(require("./commands/kill"));
25
+ const materialize_1 = __importDefault(require("./commands/materialize"));
25
26
  const migrate_1 = __importDefault(require("./commands/migrate"));
26
27
  const package_1 = __importDefault(require("./commands/package"));
27
28
  const plan_1 = __importDefault(require("./commands/plan"));
@@ -54,6 +55,7 @@ const ENGINE_EXEMPT_COMMANDS = new Set([
54
55
  'init',
55
56
  'install',
56
57
  'package',
58
+ 'materialize',
57
59
  'plan',
58
60
  'remove',
59
61
  'rename',
@@ -97,6 +99,7 @@ const createPgpmCommandMap = (skipPgTeardown = false) => {
97
99
  kill: pgt(kill_1.default),
98
100
  install: pgt(install_1.default),
99
101
  migrate: pgt(migrate_1.default),
102
+ materialize: materialize_1.default,
100
103
  analyze: pgt(analyze_1.default),
101
104
  rename: pgt(rename_1.default),
102
105
  slice: slice_1.default,
@@ -0,0 +1,127 @@
1
+ import { materializeWorkspaceTarget, PgpmPackage } from '@pgpmjs/core';
2
+ import { existsSync, mkdtempSync, readdirSync, readFileSync, rmSync } from 'fs';
3
+ import { tmpdir } from 'os';
4
+ import { join, relative, resolve } from 'path';
5
+ const materializeUsageText = `
6
+ Materialize Command:
7
+
8
+ pgpm materialize <target> [OPTIONS]
9
+
10
+ Transpile an apply-proxy module (pgpm.apply.json) once and write the result
11
+ as a plain, deployable PGPM module (deploy/revert/verify + pgpm.plan +
12
+ .control, with the transforms baked into the SQL). The output has no
13
+ pgpm.apply.json and deploys like any hand-written module.
14
+
15
+ The proxy stays in the repo as the recipe; the materialized module is its
16
+ committed build artifact. Re-run when the source or provider binding changes.
17
+
18
+ Arguments:
19
+ target Name of the apply-proxy module in the workspace.
20
+
21
+ Options:
22
+ --help, -h Show this help message
23
+ --output <dir> Output directory (default: <workspace>/materialized/<name>)
24
+ --overwrite Replace an existing output directory
25
+ --check Re-materialize to a temp dir and diff against --output;
26
+ exit non-zero on any difference (drift gate for CI)
27
+ --cwd <directory> Working directory (default: current directory)
28
+
29
+ Examples:
30
+ pgpm materialize vendor-app-ported
31
+ pgpm materialize vendor-app-ported --output extensions/vendor-app-ported --overwrite
32
+ pgpm materialize vendor-app-ported --check
33
+ `;
34
+ /** Recursively list files in a directory as workspace-relative POSIX paths. */
35
+ function listFiles(dir) {
36
+ const out = [];
37
+ const walk = (current) => {
38
+ for (const entry of readdirSync(current, { withFileTypes: true })) {
39
+ const full = join(current, entry.name);
40
+ if (entry.isDirectory())
41
+ walk(full);
42
+ else
43
+ out.push(relative(dir, full).replace(/\\/g, '/'));
44
+ }
45
+ };
46
+ walk(dir);
47
+ return out.sort();
48
+ }
49
+ /** Byte-level diff between two materialized module directories. */
50
+ function diffDirs(expectedDir, actualDir) {
51
+ const expected = new Set(listFiles(expectedDir));
52
+ const actual = new Set(listFiles(actualDir));
53
+ const diffs = [];
54
+ for (const file of actual) {
55
+ if (!expected.has(file))
56
+ diffs.push(`missing from output: ${file}`);
57
+ }
58
+ for (const file of expected) {
59
+ if (!actual.has(file)) {
60
+ diffs.push(`stale in output: ${file}`);
61
+ continue;
62
+ }
63
+ const a = readFileSync(join(expectedDir, file));
64
+ const b = readFileSync(join(actualDir, file));
65
+ if (!a.equals(b))
66
+ diffs.push(`content differs: ${file}`);
67
+ }
68
+ return diffs.sort();
69
+ }
70
+ export default async (argv, _prompter, _options) => {
71
+ if (argv.help || argv.h) {
72
+ console.log(materializeUsageText);
73
+ process.exit(0);
74
+ }
75
+ const cwd = argv.cwd ?? process.cwd();
76
+ const target = argv._?.[0] ?? argv.target;
77
+ if (!target) {
78
+ console.error('Error: a target apply-proxy module name is required.');
79
+ console.log(materializeUsageText);
80
+ process.exit(1);
81
+ }
82
+ const project = new PgpmPackage(cwd);
83
+ project.ensureWorkspace();
84
+ const workspacePath = project.workspacePath;
85
+ const moduleMap = project.getModuleMap();
86
+ const check = Boolean(argv.check);
87
+ const overwrite = Boolean(argv.overwrite);
88
+ const outDir = argv.output
89
+ ? resolve(cwd, argv.output)
90
+ : resolve(workspacePath, 'materialized', String(target));
91
+ if (check) {
92
+ if (!existsSync(outDir)) {
93
+ console.error(`Error: --check requires an existing output at ${outDir}. Run \`pgpm materialize ${target}\` first.`);
94
+ process.exit(1);
95
+ }
96
+ const tmp = mkdtempSync(join(tmpdir(), `pgpm-materialize-check-`));
97
+ try {
98
+ const { spec } = await materializeWorkspaceTarget({ workspacePath, moduleMap, target, outDir: tmp });
99
+ const diffs = diffDirs(outDir, tmp);
100
+ if (diffs.length > 0) {
101
+ console.error(`Drift: materialized "${target}" (from "${spec.source.module}") differs from ${outDir}:`);
102
+ for (const d of diffs)
103
+ console.error(` - ${d}`);
104
+ console.error(`\nRe-run \`pgpm materialize ${target} --overwrite\` and commit the result.`);
105
+ process.exit(1);
106
+ }
107
+ console.log(`✔ ${target} is up to date with ${outDir} (byte-identical).`);
108
+ }
109
+ finally {
110
+ rmSync(tmp, { recursive: true, force: true });
111
+ }
112
+ return argv;
113
+ }
114
+ if (existsSync(outDir) && !overwrite) {
115
+ console.error(`Error: ${outDir} already exists. Pass --overwrite to replace it.`);
116
+ process.exit(1);
117
+ }
118
+ if (existsSync(outDir))
119
+ rmSync(outDir, { recursive: true, force: true });
120
+ const { bundle, spec } = await materializeWorkspaceTarget({ workspacePath, moduleMap, target, outDir });
121
+ console.log(`✔ Materialized "${target}" from "${spec.source.module}"`);
122
+ console.log(` Output: ${outDir}`);
123
+ console.log(` Changes: ${bundle.changes.length}`);
124
+ console.log(` Digest: ${bundle.manifest.digest}`);
125
+ console.log(`\nDeploy it as a plain module (no pgpm.apply.json needed).`);
126
+ return argv;
127
+ };
package/esm/commands.js CHANGED
@@ -16,6 +16,7 @@ import extension from './commands/extension';
16
16
  import init from './commands/init';
17
17
  import install from './commands/install';
18
18
  import kill from './commands/kill';
19
+ import materialize from './commands/materialize';
19
20
  import migrate from './commands/migrate';
20
21
  import _package from './commands/package';
21
22
  import plan from './commands/plan';
@@ -48,6 +49,7 @@ const ENGINE_EXEMPT_COMMANDS = new Set([
48
49
  'init',
49
50
  'install',
50
51
  'package',
52
+ 'materialize',
51
53
  'plan',
52
54
  'remove',
53
55
  'rename',
@@ -91,6 +93,7 @@ export const createPgpmCommandMap = (skipPgTeardown = false) => {
91
93
  kill: pgt(kill),
92
94
  install: pgt(install),
93
95
  migrate: pgt(migrate),
96
+ materialize,
94
97
  analyze: pgt(analyze),
95
98
  rename: pgt(renameCmd),
96
99
  slice,
@@ -12,6 +12,7 @@ export const usageText = `
12
12
  extension Manage module dependencies
13
13
  plan Generate module deployment plans
14
14
  package Package module for distribution
15
+ materialize Transpile an apply proxy into a plain, committed module
15
16
  sync-versions Sync .control/Makefile/sql metadata to package.json versions
16
17
  export Export database migrations from existing databases
17
18
  update Update pgpm to the latest version
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pgpm",
3
- "version": "5.15.4",
3
+ "version": "5.16.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.18.0",
50
- "@pgpmjs/env": "^2.39.2",
51
- "@pgpmjs/export": "^1.12.7",
49
+ "@pgpmjs/core": "^7.19.0",
50
+ "@pgpmjs/env": "^2.39.3",
51
+ "@pgpmjs/export": "^1.12.9",
52
52
  "@pgpmjs/logger": "^2.22.1",
53
- "@pgpmjs/slice": "^0.12.0",
54
- "@pgpmjs/types": "^2.48.1",
53
+ "@pgpmjs/slice": "^0.12.1",
54
+ "@pgpmjs/types": "^2.48.2",
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.4",
61
+ "pg-cache": "^3.23.5",
62
62
  "pg-env": "^1.26.1",
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": "04b34ce4b5efcebfd8e49d64d196e651288d97f3"
80
+ "gitHead": "947334d361e9f4c48d451f1c7312b2d705ea154e"
81
81
  }
@@ -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 --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 ";
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 materialize Transpile an apply proxy into a plain, committed module\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
@@ -15,6 +15,7 @@ exports.usageText = `
15
15
  extension Manage module dependencies
16
16
  plan Generate module deployment plans
17
17
  package Package module for distribution
18
+ materialize Transpile an apply proxy into a plain, committed module
18
19
  sync-versions Sync .control/Makefile/sql metadata to package.json versions
19
20
  export Export database migrations from existing databases
20
21
  update Update pgpm to the latest version