pgpm 4.11.1 → 4.12.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.
@@ -7,29 +7,55 @@ Docker Command:
7
7
 
8
8
  pgpm docker <subcommand> [OPTIONS]
9
9
 
10
- Manage PostgreSQL Docker containers for local development.
10
+ Manage Docker containers for local development.
11
+ PostgreSQL is always started by default. Additional services can be
12
+ included with the --include flag.
11
13
 
12
14
  Subcommands:
13
- start Start PostgreSQL container
14
- stop Stop PostgreSQL container
15
+ start Start containers
16
+ stop Stop containers
17
+ ls List available services and their status
15
18
 
16
- Options:
17
- --help, -h Show this help message
19
+ PostgreSQL Options:
18
20
  --name <name> Container name (default: postgres)
19
21
  --image <image> Docker image (default: constructiveio/postgres-plus:18)
20
22
  --port <port> Host port mapping (default: 5432)
21
23
  --user <user> PostgreSQL user (default: postgres)
22
24
  --password <pass> PostgreSQL password (default: password)
23
25
  --shm-size <size> Shared memory size for container (default: 2g)
24
- --recreate Remove and recreate container on start
26
+
27
+ General Options:
28
+ --help, -h Show this help message
29
+ --recreate Remove and recreate containers on start
30
+ --include <svc> Include additional service (can be repeated)
31
+
32
+ Available Additional Services:
33
+ minio MinIO S3-compatible object storage (port 9000)
25
34
 
26
35
  Examples:
27
- pgpm docker start Start default PostgreSQL container
36
+ pgpm docker start Start PostgreSQL only
37
+ pgpm docker start --include minio Start PostgreSQL + MinIO
28
38
  pgpm docker start --port 5433 Start on custom port
29
39
  pgpm docker start --shm-size 4g Start with 4GB shared memory
30
- pgpm docker start --recreate Remove and recreate container
31
- pgpm docker stop Stop PostgreSQL container
40
+ pgpm docker start --recreate Remove and recreate containers
41
+ pgpm docker start --recreate --include minio Recreate PostgreSQL + MinIO
42
+ pgpm docker stop Stop PostgreSQL
43
+ pgpm docker stop --include minio Stop PostgreSQL + MinIO
44
+ pgpm docker ls List services and status
32
45
  `;
46
+ const ADDITIONAL_SERVICES = {
47
+ minio: {
48
+ name: 'minio',
49
+ image: 'minio/minio',
50
+ ports: [{ host: 9000, container: 9000 }],
51
+ env: {
52
+ MINIO_ACCESS_KEY: 'minioadmin',
53
+ MINIO_SECRET_KEY: 'minioadmin',
54
+ },
55
+ command: ['server', '/data'],
56
+ volumes: [{ name: 'minio-data', containerPath: '/data' }],
57
+ },
58
+ };
33
59
  function run(command, args, options = {}) {
34
60
  return new Promise((resolve, reject) => {
35
61
  const stdio = options.stdio || 'pipe';
@@ -165,6 +191,118 @@ async function stopContainer(name) {
165
191
  await (0, inquirerer_1.cliExitWithError)(`Failed to stop container "${name}"`);
166
192
  }
167
193
  }
194
+ async function startService(service, recreate) {
195
+ const { name, image, ports, env: serviceEnv, command } = service;
196
+ const exists = await containerExists(name);
197
+ const running = await isContainerRunning(name);
198
+ if (running === true) {
199
+ console.log(`✅ Container "${name}" is already running`);
200
+ return;
201
+ }
202
+ if (recreate && exists) {
203
+ console.log(`🗑️ Removing existing container "${name}"...`);
204
+ const removeResult = await run('docker', ['rm', '-f', name], { stdio: 'inherit' });
205
+ if (removeResult.code !== 0) {
206
+ await (0, inquirerer_1.cliExitWithError)(`Failed to remove container "${name}"`);
207
+ return;
208
+ }
209
+ }
210
+ if (exists && running === false) {
211
+ console.log(`🔄 Starting existing container "${name}"...`);
212
+ const startResult = await run('docker', ['start', name], { stdio: 'inherit' });
213
+ if (startResult.code === 0) {
214
+ console.log(`✅ Container "${name}" started successfully`);
215
+ }
216
+ else {
217
+ await (0, inquirerer_1.cliExitWithError)(`Failed to start container "${name}"`);
218
+ }
219
+ return;
220
+ }
221
+ console.log(`🚀 Creating and starting new container "${name}"...`);
222
+ const runArgs = [
223
+ 'run',
224
+ '-d',
225
+ '--name', name,
226
+ ];
227
+ for (const [key, value] of Object.entries(serviceEnv)) {
228
+ runArgs.push('-e', `${key}=${value}`);
229
+ }
230
+ for (const portMapping of ports) {
231
+ runArgs.push('-p', `${portMapping.host}:${portMapping.container}`);
232
+ }
233
+ if (service.volumes) {
234
+ for (const vol of service.volumes) {
235
+ runArgs.push('-v', `${vol.name}:${vol.containerPath}`);
236
+ }
237
+ }
238
+ runArgs.push(image);
239
+ if (command) {
240
+ runArgs.push(...command);
241
+ }
242
+ const runResult = await run('docker', runArgs, { stdio: 'inherit' });
243
+ if (runResult.code === 0) {
244
+ console.log(`✅ Container "${name}" created and started successfully`);
245
+ const portInfo = ports.map(p => `localhost:${p.host}`).join(', ');
246
+ console.log(`📌 ${name} is available at ${portInfo}`);
247
+ }
248
+ else {
249
+ const portInfo = ports.map(p => String(p.host)).join(', ');
250
+ await (0, inquirerer_1.cliExitWithError)(`Failed to create container "${name}". Check if port ${portInfo} is already in use.`);
251
+ }
252
+ }
253
+ async function stopService(service) {
254
+ await stopContainer(service.name);
255
+ }
256
+ function parseInclude(args) {
257
+ const include = args.include;
258
+ if (!include)
259
+ return [];
260
+ if (Array.isArray(include))
261
+ return include;
262
+ if (typeof include === 'string')
263
+ return [include];
264
+ return [];
265
+ }
266
+ function resolveIncludedServices(includeNames) {
267
+ const services = [];
268
+ for (const name of includeNames) {
269
+ const service = ADDITIONAL_SERVICES[name];
270
+ if (!service) {
271
+ console.warn(`⚠️ Unknown service: "${name}". Available: ${Object.keys(ADDITIONAL_SERVICES).join(', ')}`);
272
+ }
273
+ else {
274
+ services.push(service);
275
+ }
276
+ }
277
+ return services;
278
+ }
279
+ async function listServices() {
280
+ const dockerAvailable = await checkDockerAvailable();
281
+ console.log('\nAvailable services:\n');
282
+ console.log(' Primary:');
283
+ if (dockerAvailable) {
284
+ const pgRunning = await isContainerRunning('postgres');
285
+ const pgStatus = pgRunning === true ? '\x1b[32mrunning\x1b[0m' : pgRunning === false ? '\x1b[33mstopped\x1b[0m' : '\x1b[90mnot created\x1b[0m';
286
+ console.log(` postgres constructiveio/postgres-plus:18 ${pgStatus}`);
287
+ }
288
+ else {
289
+ console.log(' postgres constructiveio/postgres-plus:18 \x1b[90m(docker not available)\x1b[0m');
290
+ }
291
+ console.log('\n Additional (use --include <name>):');
292
+ for (const [key, service] of Object.entries(ADDITIONAL_SERVICES)) {
293
+ if (dockerAvailable) {
294
+ const running = await isContainerRunning(service.name);
295
+ const status = running === true ? '\x1b[32mrunning\x1b[0m' : running === false ? '\x1b[33mstopped\x1b[0m' : '\x1b[90mnot created\x1b[0m';
296
+ const portInfo = service.ports.map(p => String(p.host)).join(', ');
297
+ console.log(` ${key.padEnd(12)}${service.image.padEnd(36)}${status} port ${portInfo}`);
298
+ }
299
+ else {
300
+ const portInfo = service.ports.map(p => String(p.host)).join(', ');
301
+ console.log(` ${key.padEnd(12)}${service.image.padEnd(36)}\x1b[90m(docker not available)\x1b[0m port ${portInfo}`);
302
+ }
303
+ }
304
+ console.log('');
305
+ }
168
306
  exports.default = async (argv, _prompter, _options) => {
169
307
  if (argv.help || argv.h) {
170
308
  console.log(dockerUsageText);
@@ -174,7 +312,7 @@ exports.default = async (argv, _prompter, _options) => {
174
312
  const args = newArgv;
175
313
  if (!subcommand) {
176
314
  console.log(dockerUsageText);
177
- await (0, inquirerer_1.cliExitWithError)('No subcommand provided. Use "start" or "stop".');
315
+ await (0, inquirerer_1.cliExitWithError)('No subcommand provided. Use "start", "stop", or "ls".');
178
316
  return;
179
317
  }
180
318
  const name = args.name || 'postgres';
@@ -184,15 +322,26 @@ exports.default = async (argv, _prompter, _options) => {
184
322
  const password = args.password || 'password';
185
323
  const shmSize = args['shm-size'] || args.shmSize || '2g';
186
324
  const recreate = args.recreate === true;
325
+ const includeNames = parseInclude(args);
326
+ const includedServices = resolveIncludedServices(includeNames);
187
327
  switch (subcommand) {
188
328
  case 'start':
189
329
  await startContainer({ name, image, port, user, password, shmSize, recreate });
330
+ for (const service of includedServices) {
331
+ await startService(service, recreate);
332
+ }
190
333
  break;
191
334
  case 'stop':
192
335
  await stopContainer(name);
336
+ for (const service of includedServices) {
337
+ await stopService(service);
338
+ }
339
+ break;
340
+ case 'ls':
341
+ await listServices();
193
342
  break;
194
343
  default:
195
344
  console.log(dockerUsageText);
196
- await (0, inquirerer_1.cliExitWithError)(`Unknown subcommand: ${subcommand}. Use "start" or "stop".`);
345
+ await (0, inquirerer_1.cliExitWithError)(`Unknown subcommand: ${subcommand}. Use "start", "stop", or "ls".`);
197
346
  }
198
347
  };
@@ -5,29 +5,55 @@ Docker Command:
5
5
 
6
6
  pgpm docker <subcommand> [OPTIONS]
7
7
 
8
- Manage PostgreSQL Docker containers for local development.
8
+ Manage Docker containers for local development.
9
+ PostgreSQL is always started by default. Additional services can be
10
+ included with the --include flag.
9
11
 
10
12
  Subcommands:
11
- start Start PostgreSQL container
12
- stop Stop PostgreSQL container
13
+ start Start containers
14
+ stop Stop containers
15
+ ls List available services and their status
13
16
 
14
- Options:
15
- --help, -h Show this help message
17
+ PostgreSQL Options:
16
18
  --name <name> Container name (default: postgres)
17
19
  --image <image> Docker image (default: constructiveio/postgres-plus:18)
18
20
  --port <port> Host port mapping (default: 5432)
19
21
  --user <user> PostgreSQL user (default: postgres)
20
22
  --password <pass> PostgreSQL password (default: password)
21
23
  --shm-size <size> Shared memory size for container (default: 2g)
22
- --recreate Remove and recreate container on start
24
+
25
+ General Options:
26
+ --help, -h Show this help message
27
+ --recreate Remove and recreate containers on start
28
+ --include <svc> Include additional service (can be repeated)
29
+
30
+ Available Additional Services:
31
+ minio MinIO S3-compatible object storage (port 9000)
23
32
 
24
33
  Examples:
25
- pgpm docker start Start default PostgreSQL container
34
+ pgpm docker start Start PostgreSQL only
35
+ pgpm docker start --include minio Start PostgreSQL + MinIO
26
36
  pgpm docker start --port 5433 Start on custom port
27
37
  pgpm docker start --shm-size 4g Start with 4GB shared memory
28
- pgpm docker start --recreate Remove and recreate container
29
- pgpm docker stop Stop PostgreSQL container
38
+ pgpm docker start --recreate Remove and recreate containers
39
+ pgpm docker start --recreate --include minio Recreate PostgreSQL + MinIO
40
+ pgpm docker stop Stop PostgreSQL
41
+ pgpm docker stop --include minio Stop PostgreSQL + MinIO
42
+ pgpm docker ls List services and status
30
43
  `;
44
+ const ADDITIONAL_SERVICES = {
45
+ minio: {
46
+ name: 'minio',
47
+ image: 'minio/minio',
48
+ ports: [{ host: 9000, container: 9000 }],
49
+ env: {
50
+ MINIO_ACCESS_KEY: 'minioadmin',
51
+ MINIO_SECRET_KEY: 'minioadmin',
52
+ },
53
+ command: ['server', '/data'],
54
+ volumes: [{ name: 'minio-data', containerPath: '/data' }],
55
+ },
56
+ };
31
57
  function run(command, args, options = {}) {
32
58
  return new Promise((resolve, reject) => {
33
59
  const stdio = options.stdio || 'pipe';
@@ -163,6 +189,118 @@ async function stopContainer(name) {
163
189
  await cliExitWithError(`Failed to stop container "${name}"`);
164
190
  }
165
191
  }
192
+ async function startService(service, recreate) {
193
+ const { name, image, ports, env: serviceEnv, command } = service;
194
+ const exists = await containerExists(name);
195
+ const running = await isContainerRunning(name);
196
+ if (running === true) {
197
+ console.log(`✅ Container "${name}" is already running`);
198
+ return;
199
+ }
200
+ if (recreate && exists) {
201
+ console.log(`🗑️ Removing existing container "${name}"...`);
202
+ const removeResult = await run('docker', ['rm', '-f', name], { stdio: 'inherit' });
203
+ if (removeResult.code !== 0) {
204
+ await cliExitWithError(`Failed to remove container "${name}"`);
205
+ return;
206
+ }
207
+ }
208
+ if (exists && running === false) {
209
+ console.log(`🔄 Starting existing container "${name}"...`);
210
+ const startResult = await run('docker', ['start', name], { stdio: 'inherit' });
211
+ if (startResult.code === 0) {
212
+ console.log(`✅ Container "${name}" started successfully`);
213
+ }
214
+ else {
215
+ await cliExitWithError(`Failed to start container "${name}"`);
216
+ }
217
+ return;
218
+ }
219
+ console.log(`🚀 Creating and starting new container "${name}"...`);
220
+ const runArgs = [
221
+ 'run',
222
+ '-d',
223
+ '--name', name,
224
+ ];
225
+ for (const [key, value] of Object.entries(serviceEnv)) {
226
+ runArgs.push('-e', `${key}=${value}`);
227
+ }
228
+ for (const portMapping of ports) {
229
+ runArgs.push('-p', `${portMapping.host}:${portMapping.container}`);
230
+ }
231
+ if (service.volumes) {
232
+ for (const vol of service.volumes) {
233
+ runArgs.push('-v', `${vol.name}:${vol.containerPath}`);
234
+ }
235
+ }
236
+ runArgs.push(image);
237
+ if (command) {
238
+ runArgs.push(...command);
239
+ }
240
+ const runResult = await run('docker', runArgs, { stdio: 'inherit' });
241
+ if (runResult.code === 0) {
242
+ console.log(`✅ Container "${name}" created and started successfully`);
243
+ const portInfo = ports.map(p => `localhost:${p.host}`).join(', ');
244
+ console.log(`📌 ${name} is available at ${portInfo}`);
245
+ }
246
+ else {
247
+ const portInfo = ports.map(p => String(p.host)).join(', ');
248
+ await cliExitWithError(`Failed to create container "${name}". Check if port ${portInfo} is already in use.`);
249
+ }
250
+ }
251
+ async function stopService(service) {
252
+ await stopContainer(service.name);
253
+ }
254
+ function parseInclude(args) {
255
+ const include = args.include;
256
+ if (!include)
257
+ return [];
258
+ if (Array.isArray(include))
259
+ return include;
260
+ if (typeof include === 'string')
261
+ return [include];
262
+ return [];
263
+ }
264
+ function resolveIncludedServices(includeNames) {
265
+ const services = [];
266
+ for (const name of includeNames) {
267
+ const service = ADDITIONAL_SERVICES[name];
268
+ if (!service) {
269
+ console.warn(`⚠️ Unknown service: "${name}". Available: ${Object.keys(ADDITIONAL_SERVICES).join(', ')}`);
270
+ }
271
+ else {
272
+ services.push(service);
273
+ }
274
+ }
275
+ return services;
276
+ }
277
+ async function listServices() {
278
+ const dockerAvailable = await checkDockerAvailable();
279
+ console.log('\nAvailable services:\n');
280
+ console.log(' Primary:');
281
+ if (dockerAvailable) {
282
+ const pgRunning = await isContainerRunning('postgres');
283
+ const pgStatus = pgRunning === true ? '\x1b[32mrunning\x1b[0m' : pgRunning === false ? '\x1b[33mstopped\x1b[0m' : '\x1b[90mnot created\x1b[0m';
284
+ console.log(` postgres constructiveio/postgres-plus:18 ${pgStatus}`);
285
+ }
286
+ else {
287
+ console.log(' postgres constructiveio/postgres-plus:18 \x1b[90m(docker not available)\x1b[0m');
288
+ }
289
+ console.log('\n Additional (use --include <name>):');
290
+ for (const [key, service] of Object.entries(ADDITIONAL_SERVICES)) {
291
+ if (dockerAvailable) {
292
+ const running = await isContainerRunning(service.name);
293
+ const status = running === true ? '\x1b[32mrunning\x1b[0m' : running === false ? '\x1b[33mstopped\x1b[0m' : '\x1b[90mnot created\x1b[0m';
294
+ const portInfo = service.ports.map(p => String(p.host)).join(', ');
295
+ console.log(` ${key.padEnd(12)}${service.image.padEnd(36)}${status} port ${portInfo}`);
296
+ }
297
+ else {
298
+ const portInfo = service.ports.map(p => String(p.host)).join(', ');
299
+ console.log(` ${key.padEnd(12)}${service.image.padEnd(36)}\x1b[90m(docker not available)\x1b[0m port ${portInfo}`);
300
+ }
301
+ }
302
+ console.log('');
303
+ }
166
304
  export default async (argv, _prompter, _options) => {
167
305
  if (argv.help || argv.h) {
168
306
  console.log(dockerUsageText);
@@ -172,7 +310,7 @@ export default async (argv, _prompter, _options) => {
172
310
  const args = newArgv;
173
311
  if (!subcommand) {
174
312
  console.log(dockerUsageText);
175
- await cliExitWithError('No subcommand provided. Use "start" or "stop".');
313
+ await cliExitWithError('No subcommand provided. Use "start", "stop", or "ls".');
176
314
  return;
177
315
  }
178
316
  const name = args.name || 'postgres';
@@ -182,15 +320,26 @@ export default async (argv, _prompter, _options) => {
182
320
  const password = args.password || 'password';
183
321
  const shmSize = args['shm-size'] || args.shmSize || '2g';
184
322
  const recreate = args.recreate === true;
323
+ const includeNames = parseInclude(args);
324
+ const includedServices = resolveIncludedServices(includeNames);
185
325
  switch (subcommand) {
186
326
  case 'start':
187
327
  await startContainer({ name, image, port, user, password, shmSize, recreate });
328
+ for (const service of includedServices) {
329
+ await startService(service, recreate);
330
+ }
188
331
  break;
189
332
  case 'stop':
190
333
  await stopContainer(name);
334
+ for (const service of includedServices) {
335
+ await stopService(service);
336
+ }
337
+ break;
338
+ case 'ls':
339
+ await listServices();
191
340
  break;
192
341
  default:
193
342
  console.log(dockerUsageText);
194
- await cliExitWithError(`Unknown subcommand: ${subcommand}. Use "start" or "stop".`);
343
+ await cliExitWithError(`Unknown subcommand: ${subcommand}. Use "start", "stop", or "ls".`);
195
344
  }
196
345
  };
@@ -39,7 +39,7 @@ export const usageText = `
39
39
  deps Show change dependencies
40
40
 
41
41
  Development Tools:
42
- docker Manage PostgreSQL Docker containers (start/stop)
42
+ docker Manage Docker containers (start/stop/ls, --include for additional services)
43
43
  env Manage PostgreSQL environment variables
44
44
  test-packages Run integration tests on workspace packages
45
45
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pgpm",
3
- "version": "4.11.1",
3
+ "version": "4.12.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",
@@ -76,5 +76,5 @@
76
76
  "pg",
77
77
  "pgsql"
78
78
  ],
79
- "gitHead": "79cd3e66871804a22c672c7ca2fa5e2105d4b368"
79
+ "gitHead": "2bedc6e29e8d2bfd1edd97d151696deb6b278a7a"
80
80
  }
@@ -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 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\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 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\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, --include for additional services)\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
@@ -42,7 +42,7 @@ exports.usageText = `
42
42
  deps Show change dependencies
43
43
 
44
44
  Development Tools:
45
- docker Manage PostgreSQL Docker containers (start/stop)
45
+ docker Manage Docker containers (start/stop/ls, --include for additional services)
46
46
  env Manage PostgreSQL environment variables
47
47
  test-packages Run integration tests on workspace packages
48
48