pgpm 2.5.0 → 2.6.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/README.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # **pgpm — a Postgres Package Manager**
2
2
 
3
+ <p align="center" width="100%">
4
+ <img height="250" src="https://raw.githubusercontent.com/constructive-io/constructive/refs/heads/main/assets/outline-logo.svg" />
5
+ </p>
6
+
7
+ <p align="center" width="100%">
8
+ <a href="https://github.com/constructive-io/constructive/actions/workflows/run-tests.yaml">
9
+ <img height="20" src="https://github.com/constructive-io/constructive/actions/workflows/run-tests.yaml/badge.svg" />
10
+ </a>
11
+ <a href="https://github.com/constructive-io/constructive/blob/main/LICENSE"><img height="20" src="https://img.shields.io/badge/license-MIT-blue.svg"/></a>
12
+ <a href="https://www.npmjs.com/package/pgpm"><img height="20" src="https://img.shields.io/github/package-json/v/constructive-io/constructive?filename=pgpm%2Fcli%2Fpackage.json"/></a>
13
+ </p>
14
+
3
15
  **A modern CLI for modular PostgreSQL development.**
4
16
 
5
17
  `pgpm` is a focused command-line tool for PostgreSQL database migrations and package management. It provides the core functionality for managing database schemas, migrations, and module dependencies.
@@ -446,9 +458,14 @@ Common issues and solutions for pgpm, PostgreSQL, and testing.
446
458
 
447
459
  ## Related Constructive Tooling
448
460
 
461
+ ### 📦 Package Management
462
+
463
+ * [pgpm](https://github.com/constructive-io/constructive/tree/main/pgpm/pgpm): **🖥️ PostgreSQL Package Manager** for modular Postgres development. Works with database workspaces, scaffolding, migrations, seeding, and installing database packages.
464
+
449
465
  ### 🧪 Testing
450
466
 
451
467
  * [pgsql-test](https://github.com/constructive-io/constructive/tree/main/postgres/pgsql-test): **📊 Isolated testing environments** with per-test transaction rollbacks—ideal for integration tests, complex migrations, and RLS simulation.
468
+ * [pgsql-seed](https://github.com/constructive-io/constructive/tree/main/postgres/pgsql-seed): **🌱 PostgreSQL seeding utilities** for CSV, JSON, SQL data loading, and pgpm deployment.
452
469
  * [supabase-test](https://github.com/constructive-io/constructive/tree/main/postgres/supabase-test): **🧪 Supabase-native test harness** preconfigured for the local Supabase stack—per-test rollbacks, JWT/role context helpers, and CI/GitHub Actions ready.
453
470
  * [graphile-test](https://github.com/constructive-io/constructive/tree/main/graphile/graphile-test): **🔐 Authentication mocking** for Graphile-focused test helpers and emulating row-level security contexts.
454
471
  * [pg-query-context](https://github.com/constructive-io/constructive/tree/main/postgres/pg-query-context): **🔒 Session context injection** to add session-local context (e.g., `SET LOCAL`) into queries—ideal for setting `role`, `jwt.claims`, and other session settings.
@@ -462,28 +479,6 @@ Common issues and solutions for pgpm, PostgreSQL, and testing.
462
479
  * [@pgsql/types](https://www.npmjs.com/package/@pgsql/types): **📝 Type definitions** for PostgreSQL AST nodes in TypeScript.
463
480
  * [@pgsql/utils](https://www.npmjs.com/package/@pgsql/utils): **🛠️ AST utilities** for constructing and transforming PostgreSQL syntax trees.
464
481
 
465
- ### 🚀 API & Dev Tools
466
-
467
- * [@constructive-io/graphql-server](https://github.com/constructive-io/constructive/tree/main/graphql/server): **⚡ Express-based API server** powered by PostGraphile to expose a secure, scalable GraphQL API over your Postgres database.
468
- * [@constructive-io/graphql-explorer](https://github.com/constructive-io/constructive/tree/main/graphql/explorer): **🔎 Visual API explorer** with GraphiQL for browsing across all databases and schemas—useful for debugging, documentation, and API prototyping.
469
-
470
- ### 🔁 Streaming & Uploads
471
-
472
- * [etag-hash](https://github.com/constructive-io/constructive/tree/main/streaming/etag-hash): **🏷️ S3-compatible ETags** created by streaming and hashing file uploads in chunks.
473
- * [etag-stream](https://github.com/constructive-io/constructive/tree/main/streaming/etag-stream): **🔄 ETag computation** via Node stream transformer during upload or transfer.
474
- * [uuid-hash](https://github.com/constructive-io/constructive/tree/main/streaming/uuid-hash): **🆔 Deterministic UUIDs** generated from hashed content, great for deduplication and asset referencing.
475
- * [uuid-stream](https://github.com/constructive-io/constructive/tree/main/streaming/uuid-stream): **🌊 Streaming UUID generation** based on piped file content—ideal for upload pipelines.
476
- * [@constructive-io/s3-streamer](https://github.com/constructive-io/constructive/tree/main/streaming/s3-streamer): **📤 Direct S3 streaming** for large files with support for metadata injection and content validation.
477
- * [@constructive-io/upload-names](https://github.com/constructive-io/constructive/tree/main/streaming/upload-names): **📂 Collision-resistant filenames** utility for structured and unique file names for uploads.
478
-
479
- ### 🧰 CLI & Codegen
480
-
481
- * [pgpm](https://github.com/constructive-io/constructive/tree/main/pgpm/pgpm): **🖥️ PostgreSQL Package Manager** for modular Postgres development. Works with database workspaces, scaffolding, migrations, seeding, and installing database packages.
482
- * [@constructive-io/cli](https://github.com/constructive-io/constructive/tree/main/packages/cli): **🖥️ Command-line toolkit** for managing Constructive projects—supports database scaffolding, migrations, seeding, code generation, and automation.
483
- * [@constructive-io/graphql-codegen](https://github.com/constructive-io/constructive/tree/main/graphql/codegen): **✨ GraphQL code generation** (types, operations, SDK) from schema/endpoint introspection.
484
- * [@constructive-io/query-builder](https://github.com/constructive-io/constructive/tree/main/packages/query-builder): **🏗️ SQL constructor** providing a robust TypeScript-based query builder for dynamic generation of `SELECT`, `INSERT`, `UPDATE`, `DELETE`, and stored procedure calls—supports advanced SQL features like `JOIN`, `GROUP BY`, and schema-qualified queries.
485
- * [@constructive-io/graphql-query](https://github.com/constructive-io/constructive/tree/main/graphql/query): **🧩 Fluent GraphQL builder** for PostGraphile schemas. ⚡ Schema-aware via introspection, 🧩 composable and ergonomic for building deeply nested queries.
486
-
487
482
  ## Credits
488
483
 
489
484
  **🛠 Built by the [Constructive](https://constructive.io) team — creators of modular Postgres tooling for secure, composable backends. If you like our work, contribute on [GitHub](https://github.com/constructive-io).**
@@ -1,23 +1,29 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_1 = require("@pgpmjs/core");
4
+ const logger_1 = require("@pgpmjs/logger");
5
+ const logger = new logger_1.Logger('pgpm');
4
6
  const installUsageText = `
5
7
  Install Command:
6
8
 
7
- pgpm install <package>...
9
+ pgpm install [package]...
8
10
 
9
11
  Install pgpm modules into current module.
10
12
 
13
+ When called without arguments, installs any missing modules that are
14
+ listed in the module's .control file but not yet installed in the workspace.
15
+
11
16
  Arguments:
12
- package One or more package names to install
17
+ package One or more package names to install (optional)
13
18
 
14
19
  Options:
15
20
  --help, -h Show this help message
16
21
  --cwd <directory> Working directory (default: current directory)
17
22
 
18
23
  Examples:
24
+ pgpm install Install missing modules from .control file
19
25
  pgpm install @pgpm/base32 Install single package
20
- pgpm install @pgpm/base32 @pgpm/utils Install multiple packages
26
+ pgpm install @pgpm/base32 @pgpm/utils Install multiple packages
21
27
  `;
22
28
  exports.default = async (argv, prompter, _options) => {
23
29
  // Show usage if explicitly requested
@@ -30,8 +36,19 @@ exports.default = async (argv, prompter, _options) => {
30
36
  if (!project.isInModule()) {
31
37
  throw new Error('You must run this command inside a PGPM module.');
32
38
  }
39
+ // If no packages specified, install missing modules from .control file
33
40
  if (argv._.length === 0) {
34
- throw new Error('You must provide a package name to install, e.g. `@pgpm/base32`');
41
+ const requiredExtensions = project.getRequiredModules();
42
+ const installedModules = project.getWorkspaceInstalledModules();
43
+ const missingModules = (0, core_1.getMissingInstallableModules)(requiredExtensions, installedModules);
44
+ if (missingModules.length === 0) {
45
+ logger.success('All modules are already installed.');
46
+ return;
47
+ }
48
+ const missingNames = missingModules.map(m => m.npmName);
49
+ logger.info(`Installing missing modules: ${missingNames.join(', ')}`);
50
+ await project.installModules(...missingNames);
51
+ return;
35
52
  }
36
53
  await project.installModules(...argv._);
37
54
  };
@@ -2,29 +2,32 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_1 = require("@pgpmjs/core");
4
4
  const logger_1 = require("@pgpmjs/logger");
5
+ const inquirerer_1 = require("inquirerer");
5
6
  const npm_version_1 = require("../utils/npm-version");
6
- const log = new logger_1.Logger('upgrade-modules');
7
- const upgradeModulesUsageText = `
8
- Upgrade Modules Command:
7
+ const log = new logger_1.Logger('upgrade');
8
+ const upgradeUsageText = `
9
+ Upgrade Command:
9
10
 
10
- pgpm upgrade-modules [OPTIONS]
11
+ pgpm upgrade [PACKAGE...] [OPTIONS]
11
12
 
12
13
  Upgrade installed pgpm modules to their latest versions from npm.
14
+ When used without arguments, upgrades all modules.
13
15
 
14
16
  Options:
15
17
  --help, -h Show this help message
16
18
  --cwd <directory> Working directory (default: current directory)
17
- --all Upgrade all modules without prompting
19
+ -i, --interactive Show outdated modules and select which ones to upgrade
18
20
  --dry-run Show what would be upgraded without making changes
19
- --modules <names> Comma-separated list of specific modules to upgrade
20
21
  --workspace Upgrade modules across all packages in the workspace
21
22
 
22
23
  Examples:
23
- pgpm upgrade-modules Interactive selection of modules to upgrade
24
- pgpm upgrade-modules --all Upgrade all installed modules
25
- pgpm upgrade-modules --dry-run Preview available upgrades
26
- pgpm upgrade-modules --modules @pgpm/base32,@pgpm/faker Upgrade specific modules
27
- pgpm upgrade-modules --workspace --all Upgrade all modules across the entire workspace
24
+ pgpm upgrade Upgrade all installed modules
25
+ pgpm upgrade -i Interactive selection of modules to upgrade
26
+ pgpm upgrade @pgpm/base32 Upgrade specific module
27
+ pgpm upgrade @pgpm/base32 @pgpm/uuid Upgrade multiple specific modules
28
+ pgpm upgrade --dry-run Preview available upgrades
29
+ pgpm upgrade --workspace Upgrade all modules across the entire workspace
30
+ pgpm up Alias for upgrade
28
31
  `;
29
32
  async function fetchModuleVersions(installedVersions) {
30
33
  const moduleNames = Object.keys(installedVersions);
@@ -41,7 +44,7 @@ async function fetchModuleVersions(installedVersions) {
41
44
  }
42
45
  return results;
43
46
  }
44
- async function upgradeModulesForProject(project, argv, prompter, dryRun, upgradeAll, specificModules, moduleName) {
47
+ async function upgradeModulesForProject(project, argv, prompter, dryRun, interactive, specificModules, moduleName) {
45
48
  const { installed, installedVersions } = project.getInstalledModules();
46
49
  if (installed.length === 0) {
47
50
  if (moduleName) {
@@ -53,9 +56,12 @@ async function upgradeModulesForProject(project, argv, prompter, dryRun, upgrade
53
56
  return false;
54
57
  }
55
58
  const prefix = moduleName ? `[${moduleName}] ` : '';
56
- log.info(`${prefix}Found ${installed.length} installed module(s). Checking for updates...`);
59
+ // Use spinner while checking for updates
60
+ const spinner = (0, inquirerer_1.createSpinner)(`${prefix}Checking ${installed.length} installed module(s) for updates...`);
61
+ spinner.start();
57
62
  const moduleVersions = await fetchModuleVersions(installedVersions);
58
63
  const modulesWithUpdates = moduleVersions.filter(m => m.hasUpdate);
64
+ spinner.succeed(`${prefix}Found ${modulesWithUpdates.length} module(s) with updates available`);
59
65
  if (modulesWithUpdates.length === 0) {
60
66
  log.success(`${prefix}All modules are already up to date.`);
61
67
  return false;
@@ -70,10 +76,8 @@ async function upgradeModulesForProject(project, argv, prompter, dryRun, upgrade
70
76
  return true;
71
77
  }
72
78
  let modulesToUpgrade;
73
- if (upgradeAll) {
74
- modulesToUpgrade = modulesWithUpdates.map(m => m.name);
75
- }
76
- else if (specificModules) {
79
+ if (specificModules && specificModules.length > 0) {
80
+ // Specific modules provided as positional arguments
77
81
  modulesToUpgrade = modulesWithUpdates
78
82
  .filter(m => specificModules.includes(m.name))
79
83
  .map(m => m.name);
@@ -82,32 +86,24 @@ async function upgradeModulesForProject(project, argv, prompter, dryRun, upgrade
82
86
  return false;
83
87
  }
84
88
  }
85
- else {
86
- const options = modulesWithUpdates.map(mod => ({
89
+ else if (interactive) {
90
+ // Interactive mode: use pnpm-style upgrade UI
91
+ const packages = modulesWithUpdates.map(mod => ({
87
92
  name: mod.name,
88
- value: mod.name,
89
- message: `${mod.name} (${mod.currentVersion} -> ${mod.latestVersion})`
93
+ current: mod.currentVersion,
94
+ latest: mod.latestVersion,
95
+ type: 'dependencies'
90
96
  }));
91
- const questions = [
92
- {
93
- name: 'selectedModules',
94
- message: `${prefix}Select modules to upgrade:`,
95
- type: 'checkbox',
96
- options: options.map(o => o.message),
97
- default: options.map(o => o.message)
98
- }
99
- ];
100
- const answers = await prompter.prompt(argv, questions);
101
- const selectedOptions = answers.selectedModules
102
- .filter(opt => opt.selected)
103
- .map(opt => opt.name);
104
- modulesToUpgrade = modulesWithUpdates
105
- .filter(mod => selectedOptions.includes(`${mod.name} (${mod.currentVersion} -> ${mod.latestVersion})`))
106
- .map(m => m.name);
107
- if (modulesToUpgrade.length === 0) {
97
+ const result = await (0, inquirerer_1.upgradePrompt)(packages, 10);
98
+ if (result.updates.length === 0) {
108
99
  log.info(`${prefix}No modules selected for upgrade.`);
109
100
  return false;
110
101
  }
102
+ modulesToUpgrade = result.updates.map(u => u.name);
103
+ }
104
+ else {
105
+ // Default behavior: upgrade all modules with updates (like pnpm upgrade)
106
+ modulesToUpgrade = modulesWithUpdates.map(m => m.name);
111
107
  }
112
108
  log.info(`\n${prefix}Upgrading ${modulesToUpgrade.length} module(s)...`);
113
109
  await project.upgradeModules({ modules: modulesToUpgrade });
@@ -116,15 +112,16 @@ async function upgradeModulesForProject(project, argv, prompter, dryRun, upgrade
116
112
  }
117
113
  exports.default = async (argv, prompter, _options) => {
118
114
  if (argv.help || argv.h) {
119
- console.log(upgradeModulesUsageText);
115
+ console.log(upgradeUsageText);
120
116
  process.exit(0);
121
117
  }
122
118
  const { cwd = process.cwd() } = argv;
123
119
  const dryRun = Boolean(argv['dry-run']);
124
- const upgradeAll = Boolean(argv.all);
120
+ const interactive = Boolean(argv.i || argv.interactive);
125
121
  const workspaceMode = Boolean(argv.workspace);
126
- const specificModules = argv.modules
127
- ? String(argv.modules).split(',').map(m => m.trim())
122
+ // Get specific modules from positional arguments (argv._)
123
+ const specificModules = argv._ && argv._.length > 0
124
+ ? argv._.map((m) => String(m).trim())
128
125
  : undefined;
129
126
  const project = new core_1.PgpmPackage(cwd);
130
127
  if (workspaceMode) {
@@ -140,7 +137,7 @@ exports.default = async (argv, prompter, _options) => {
140
137
  let anyUpgraded = false;
141
138
  for (const moduleProject of modules) {
142
139
  const moduleName = moduleProject.getModuleName();
143
- const upgraded = await upgradeModulesForProject(moduleProject, argv, prompter, dryRun, upgradeAll, specificModules, moduleName);
140
+ const upgraded = await upgradeModulesForProject(moduleProject, argv, prompter, dryRun, interactive, specificModules, moduleName);
144
141
  if (upgraded) {
145
142
  anyUpgraded = true;
146
143
  }
@@ -154,6 +151,6 @@ exports.default = async (argv, prompter, _options) => {
154
151
  if (!project.isInModule()) {
155
152
  throw new Error('You must run this command inside a PGPM module. Use --workspace to upgrade all modules in the workspace.');
156
153
  }
157
- await upgradeModulesForProject(project, argv, prompter, dryRun, upgradeAll, specificModules);
154
+ await upgradeModulesForProject(project, argv, prompter, dryRun, interactive, specificModules);
158
155
  }
159
156
  };
package/commands.js CHANGED
@@ -24,7 +24,7 @@ const migrate_1 = __importDefault(require("./commands/migrate"));
24
24
  const package_1 = __importDefault(require("./commands/package"));
25
25
  const plan_1 = __importDefault(require("./commands/plan"));
26
26
  const update_1 = __importDefault(require("./commands/update"));
27
- const upgrade_modules_1 = __importDefault(require("./commands/upgrade-modules"));
27
+ const upgrade_1 = __importDefault(require("./commands/upgrade"));
28
28
  const remove_1 = __importDefault(require("./commands/remove"));
29
29
  const rename_1 = __importDefault(require("./commands/rename"));
30
30
  const revert_1 = __importDefault(require("./commands/revert"));
@@ -66,7 +66,8 @@ const createPgpmCommandMap = (skipPgTeardown = false) => {
66
66
  analyze: pgt(analyze_1.default),
67
67
  rename: pgt(rename_1.default),
68
68
  'test-packages': pgt(test_packages_1.default),
69
- 'upgrade-modules': pgt(upgrade_modules_1.default),
69
+ upgrade: pgt(upgrade_1.default),
70
+ up: pgt(upgrade_1.default),
70
71
  cache: cache_1.default,
71
72
  update: update_1.default
72
73
  };
@@ -1,21 +1,27 @@
1
- import { PgpmPackage } from '@pgpmjs/core';
1
+ import { getMissingInstallableModules, PgpmPackage } from '@pgpmjs/core';
2
+ import { Logger } from '@pgpmjs/logger';
3
+ const logger = new Logger('pgpm');
2
4
  const installUsageText = `
3
5
  Install Command:
4
6
 
5
- pgpm install <package>...
7
+ pgpm install [package]...
6
8
 
7
9
  Install pgpm modules into current module.
8
10
 
11
+ When called without arguments, installs any missing modules that are
12
+ listed in the module's .control file but not yet installed in the workspace.
13
+
9
14
  Arguments:
10
- package One or more package names to install
15
+ package One or more package names to install (optional)
11
16
 
12
17
  Options:
13
18
  --help, -h Show this help message
14
19
  --cwd <directory> Working directory (default: current directory)
15
20
 
16
21
  Examples:
22
+ pgpm install Install missing modules from .control file
17
23
  pgpm install @pgpm/base32 Install single package
18
- pgpm install @pgpm/base32 @pgpm/utils Install multiple packages
24
+ pgpm install @pgpm/base32 @pgpm/utils Install multiple packages
19
25
  `;
20
26
  export default async (argv, prompter, _options) => {
21
27
  // Show usage if explicitly requested
@@ -28,8 +34,19 @@ export default async (argv, prompter, _options) => {
28
34
  if (!project.isInModule()) {
29
35
  throw new Error('You must run this command inside a PGPM module.');
30
36
  }
37
+ // If no packages specified, install missing modules from .control file
31
38
  if (argv._.length === 0) {
32
- throw new Error('You must provide a package name to install, e.g. `@pgpm/base32`');
39
+ const requiredExtensions = project.getRequiredModules();
40
+ const installedModules = project.getWorkspaceInstalledModules();
41
+ const missingModules = getMissingInstallableModules(requiredExtensions, installedModules);
42
+ if (missingModules.length === 0) {
43
+ logger.success('All modules are already installed.');
44
+ return;
45
+ }
46
+ const missingNames = missingModules.map(m => m.npmName);
47
+ logger.info(`Installing missing modules: ${missingNames.join(', ')}`);
48
+ await project.installModules(...missingNames);
49
+ return;
33
50
  }
34
51
  await project.installModules(...argv._);
35
52
  };
@@ -1,28 +1,31 @@
1
1
  import { PgpmPackage } from '@pgpmjs/core';
2
2
  import { Logger } from '@pgpmjs/logger';
3
+ import { upgradePrompt, createSpinner } from 'inquirerer';
3
4
  import { fetchLatestVersion } from '../utils/npm-version';
4
- const log = new Logger('upgrade-modules');
5
- const upgradeModulesUsageText = `
6
- Upgrade Modules Command:
5
+ const log = new Logger('upgrade');
6
+ const upgradeUsageText = `
7
+ Upgrade Command:
7
8
 
8
- pgpm upgrade-modules [OPTIONS]
9
+ pgpm upgrade [PACKAGE...] [OPTIONS]
9
10
 
10
11
  Upgrade installed pgpm modules to their latest versions from npm.
12
+ When used without arguments, upgrades all modules.
11
13
 
12
14
  Options:
13
15
  --help, -h Show this help message
14
16
  --cwd <directory> Working directory (default: current directory)
15
- --all Upgrade all modules without prompting
17
+ -i, --interactive Show outdated modules and select which ones to upgrade
16
18
  --dry-run Show what would be upgraded without making changes
17
- --modules <names> Comma-separated list of specific modules to upgrade
18
19
  --workspace Upgrade modules across all packages in the workspace
19
20
 
20
21
  Examples:
21
- pgpm upgrade-modules Interactive selection of modules to upgrade
22
- pgpm upgrade-modules --all Upgrade all installed modules
23
- pgpm upgrade-modules --dry-run Preview available upgrades
24
- pgpm upgrade-modules --modules @pgpm/base32,@pgpm/faker Upgrade specific modules
25
- pgpm upgrade-modules --workspace --all Upgrade all modules across the entire workspace
22
+ pgpm upgrade Upgrade all installed modules
23
+ pgpm upgrade -i Interactive selection of modules to upgrade
24
+ pgpm upgrade @pgpm/base32 Upgrade specific module
25
+ pgpm upgrade @pgpm/base32 @pgpm/uuid Upgrade multiple specific modules
26
+ pgpm upgrade --dry-run Preview available upgrades
27
+ pgpm upgrade --workspace Upgrade all modules across the entire workspace
28
+ pgpm up Alias for upgrade
26
29
  `;
27
30
  async function fetchModuleVersions(installedVersions) {
28
31
  const moduleNames = Object.keys(installedVersions);
@@ -39,7 +42,7 @@ async function fetchModuleVersions(installedVersions) {
39
42
  }
40
43
  return results;
41
44
  }
42
- async function upgradeModulesForProject(project, argv, prompter, dryRun, upgradeAll, specificModules, moduleName) {
45
+ async function upgradeModulesForProject(project, argv, prompter, dryRun, interactive, specificModules, moduleName) {
43
46
  const { installed, installedVersions } = project.getInstalledModules();
44
47
  if (installed.length === 0) {
45
48
  if (moduleName) {
@@ -51,9 +54,12 @@ async function upgradeModulesForProject(project, argv, prompter, dryRun, upgrade
51
54
  return false;
52
55
  }
53
56
  const prefix = moduleName ? `[${moduleName}] ` : '';
54
- log.info(`${prefix}Found ${installed.length} installed module(s). Checking for updates...`);
57
+ // Use spinner while checking for updates
58
+ const spinner = createSpinner(`${prefix}Checking ${installed.length} installed module(s) for updates...`);
59
+ spinner.start();
55
60
  const moduleVersions = await fetchModuleVersions(installedVersions);
56
61
  const modulesWithUpdates = moduleVersions.filter(m => m.hasUpdate);
62
+ spinner.succeed(`${prefix}Found ${modulesWithUpdates.length} module(s) with updates available`);
57
63
  if (modulesWithUpdates.length === 0) {
58
64
  log.success(`${prefix}All modules are already up to date.`);
59
65
  return false;
@@ -68,10 +74,8 @@ async function upgradeModulesForProject(project, argv, prompter, dryRun, upgrade
68
74
  return true;
69
75
  }
70
76
  let modulesToUpgrade;
71
- if (upgradeAll) {
72
- modulesToUpgrade = modulesWithUpdates.map(m => m.name);
73
- }
74
- else if (specificModules) {
77
+ if (specificModules && specificModules.length > 0) {
78
+ // Specific modules provided as positional arguments
75
79
  modulesToUpgrade = modulesWithUpdates
76
80
  .filter(m => specificModules.includes(m.name))
77
81
  .map(m => m.name);
@@ -80,32 +84,24 @@ async function upgradeModulesForProject(project, argv, prompter, dryRun, upgrade
80
84
  return false;
81
85
  }
82
86
  }
83
- else {
84
- const options = modulesWithUpdates.map(mod => ({
87
+ else if (interactive) {
88
+ // Interactive mode: use pnpm-style upgrade UI
89
+ const packages = modulesWithUpdates.map(mod => ({
85
90
  name: mod.name,
86
- value: mod.name,
87
- message: `${mod.name} (${mod.currentVersion} -> ${mod.latestVersion})`
91
+ current: mod.currentVersion,
92
+ latest: mod.latestVersion,
93
+ type: 'dependencies'
88
94
  }));
89
- const questions = [
90
- {
91
- name: 'selectedModules',
92
- message: `${prefix}Select modules to upgrade:`,
93
- type: 'checkbox',
94
- options: options.map(o => o.message),
95
- default: options.map(o => o.message)
96
- }
97
- ];
98
- const answers = await prompter.prompt(argv, questions);
99
- const selectedOptions = answers.selectedModules
100
- .filter(opt => opt.selected)
101
- .map(opt => opt.name);
102
- modulesToUpgrade = modulesWithUpdates
103
- .filter(mod => selectedOptions.includes(`${mod.name} (${mod.currentVersion} -> ${mod.latestVersion})`))
104
- .map(m => m.name);
105
- if (modulesToUpgrade.length === 0) {
95
+ const result = await upgradePrompt(packages, 10);
96
+ if (result.updates.length === 0) {
106
97
  log.info(`${prefix}No modules selected for upgrade.`);
107
98
  return false;
108
99
  }
100
+ modulesToUpgrade = result.updates.map(u => u.name);
101
+ }
102
+ else {
103
+ // Default behavior: upgrade all modules with updates (like pnpm upgrade)
104
+ modulesToUpgrade = modulesWithUpdates.map(m => m.name);
109
105
  }
110
106
  log.info(`\n${prefix}Upgrading ${modulesToUpgrade.length} module(s)...`);
111
107
  await project.upgradeModules({ modules: modulesToUpgrade });
@@ -114,15 +110,16 @@ async function upgradeModulesForProject(project, argv, prompter, dryRun, upgrade
114
110
  }
115
111
  export default async (argv, prompter, _options) => {
116
112
  if (argv.help || argv.h) {
117
- console.log(upgradeModulesUsageText);
113
+ console.log(upgradeUsageText);
118
114
  process.exit(0);
119
115
  }
120
116
  const { cwd = process.cwd() } = argv;
121
117
  const dryRun = Boolean(argv['dry-run']);
122
- const upgradeAll = Boolean(argv.all);
118
+ const interactive = Boolean(argv.i || argv.interactive);
123
119
  const workspaceMode = Boolean(argv.workspace);
124
- const specificModules = argv.modules
125
- ? String(argv.modules).split(',').map(m => m.trim())
120
+ // Get specific modules from positional arguments (argv._)
121
+ const specificModules = argv._ && argv._.length > 0
122
+ ? argv._.map((m) => String(m).trim())
126
123
  : undefined;
127
124
  const project = new PgpmPackage(cwd);
128
125
  if (workspaceMode) {
@@ -138,7 +135,7 @@ export default async (argv, prompter, _options) => {
138
135
  let anyUpgraded = false;
139
136
  for (const moduleProject of modules) {
140
137
  const moduleName = moduleProject.getModuleName();
141
- const upgraded = await upgradeModulesForProject(moduleProject, argv, prompter, dryRun, upgradeAll, specificModules, moduleName);
138
+ const upgraded = await upgradeModulesForProject(moduleProject, argv, prompter, dryRun, interactive, specificModules, moduleName);
142
139
  if (upgraded) {
143
140
  anyUpgraded = true;
144
141
  }
@@ -152,6 +149,6 @@ export default async (argv, prompter, _options) => {
152
149
  if (!project.isInModule()) {
153
150
  throw new Error('You must run this command inside a PGPM module. Use --workspace to upgrade all modules in the workspace.');
154
151
  }
155
- await upgradeModulesForProject(project, argv, prompter, dryRun, upgradeAll, specificModules);
152
+ await upgradeModulesForProject(project, argv, prompter, dryRun, interactive, specificModules);
156
153
  }
157
154
  };
package/esm/commands.js CHANGED
@@ -18,7 +18,7 @@ import migrate from './commands/migrate';
18
18
  import _package from './commands/package';
19
19
  import plan from './commands/plan';
20
20
  import updateCmd from './commands/update';
21
- import upgradeModules from './commands/upgrade-modules';
21
+ import upgrade from './commands/upgrade';
22
22
  import remove from './commands/remove';
23
23
  import renameCmd from './commands/rename';
24
24
  import revert from './commands/revert';
@@ -60,7 +60,8 @@ export const createPgpmCommandMap = (skipPgTeardown = false) => {
60
60
  analyze: pgt(analyze),
61
61
  rename: pgt(renameCmd),
62
62
  'test-packages': pgt(testPackages),
63
- 'upgrade-modules': pgt(upgradeModules),
63
+ upgrade: pgt(upgrade),
64
+ up: pgt(upgrade),
64
65
  cache,
65
66
  update: updateCmd
66
67
  };
@@ -15,7 +15,7 @@ export const usageText = `
15
15
  export Export database migrations from existing databases
16
16
  update Update pgpm to the latest version
17
17
  cache Manage cached templates (clean)
18
- upgrade-modules Upgrade installed pgpm modules to latest versions
18
+ upgrade Upgrade installed pgpm modules to latest versions (alias: up)
19
19
 
20
20
  Database Administration:
21
21
  kill Terminate database connections and optionally drop databases
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pgpm",
3
- "version": "2.5.0",
3
+ "version": "2.6.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",
@@ -33,13 +33,13 @@
33
33
  "test:watch": "jest --watch"
34
34
  },
35
35
  "devDependencies": {
36
+ "@inquirerer/test": "^1.2.0",
36
37
  "@types/js-yaml": "^4.0.9",
37
38
  "@types/minimist": "^1.2.5",
38
39
  "@types/node": "^20.12.7",
39
40
  "@types/pg": "^8.16.0",
40
41
  "@types/semver": "^7.5.8",
41
42
  "@types/shelljs": "^0.8.16",
42
- "clean-ansi": "0.1.5",
43
43
  "glob": "^13.0.0",
44
44
  "makage": "^0.1.9",
45
45
  "pg": "^8.16.3",
@@ -47,14 +47,14 @@
47
47
  },
48
48
  "dependencies": {
49
49
  "@inquirerer/utils": "^3.1.1",
50
- "@pgpmjs/core": "^4.3.0",
50
+ "@pgpmjs/core": "^4.5.0",
51
51
  "@pgpmjs/env": "^2.8.11",
52
52
  "@pgpmjs/logger": "^1.3.5",
53
53
  "@pgpmjs/types": "^2.12.8",
54
54
  "appstash": "^0.2.6",
55
55
  "find-and-require-package-json": "^0.8.2",
56
- "genomic": "^5.0.2",
57
- "inquirerer": "^4.1.1",
56
+ "genomic": "^5.2.0",
57
+ "inquirerer": "^4.2.0",
58
58
  "js-yaml": "^4.1.0",
59
59
  "minimist": "^1.2.8",
60
60
  "pg-cache": "^1.6.11",
@@ -75,5 +75,5 @@
75
75
  "pg",
76
76
  "pgsql"
77
77
  ],
78
- "gitHead": "7ac931c063d48e281349b748ba2eb9c9f47ffb06"
78
+ "gitHead": "09721f934b339bd8c55d2e633abaded6d20b0f65"
79
79
  }
@@ -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 export Export database migrations from existing databases\n update Update pgpm to the latest version\n cache Manage cached templates (clean)\n upgrade-modules Upgrade installed pgpm modules to latest versions\n\n Database Administration:\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\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 PostgreSQL Docker containers (start/stop)\n env Manage PostgreSQL environment variables\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 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 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\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 PostgreSQL Docker containers (start/stop)\n env Manage PostgreSQL environment variables\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 ";
package/utils/display.js CHANGED
@@ -18,7 +18,7 @@ exports.usageText = `
18
18
  export Export database migrations from existing databases
19
19
  update Update pgpm to the latest version
20
20
  cache Manage cached templates (clean)
21
- upgrade-modules Upgrade installed pgpm modules to latest versions
21
+ upgrade Upgrade installed pgpm modules to latest versions (alias: up)
22
22
 
23
23
  Database Administration:
24
24
  kill Terminate database connections and optionally drop databases
File without changes