pgpm 0.2.1 β†’ 0.2.3

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
@@ -14,28 +14,39 @@
14
14
  - πŸš€ **Turnkey Module-First Workspaces** β€” `pgpm init` delivers a ready-to-code Postgres workspace with CI/CD, Docker, end-to-end testing, and modern TS tooling.
15
15
 
16
16
 
17
+ Here’s a version that keeps it **light**, **simple**, and **zero-fluff**, but still feels tight and confident:
18
+
17
19
  ## πŸš€ Quick Start
18
20
 
19
- ### Installation
21
+ ### Install & Setup
20
22
 
21
23
  ```bash
24
+ # Install pgpm globally
22
25
  npm install -g pgpm
26
+
27
+ # Start local Postgres (via Docker) and export env vars
28
+ pgpm docker start
29
+ eval "$(pgpm env)"
23
30
  ```
24
31
 
32
+ > **Tip:** Already running Postgres? Skip the Docker step and just export your PG* vars.
33
+
34
+ ---
35
+
25
36
  ### Create Your First Project
26
37
 
27
38
  ```bash
28
- # 1. Create workspace
39
+ # 1. Create a workspace
29
40
  pgpm init --workspace
30
41
  cd my-app
31
42
 
32
43
  # 2. Create your first module
33
44
  pgpm init
34
45
 
35
- # 3. Add some SQL migrations to sql/ directory
46
+ # 3. Add a database change
36
47
  pgpm add some_change
37
48
 
38
- # 4. Deploy to database
49
+ # 4. Deploy everything
39
50
  pgpm deploy --createdb
40
51
  ```
41
52
 
@@ -46,6 +57,12 @@ pgpm deploy --createdb
46
57
  - `pgpm init` - Initialize a new module
47
58
  - `pgpm init --workspace` - Initialize a new workspace
48
59
 
60
+ ### Development Setup
61
+
62
+ - `pgpm docker start` - Start PostgreSQL container (via Docker)
63
+ - `pgpm docker stop` - Stop PostgreSQL container
64
+ - `pgpm env` - Print PostgreSQL environment variables for shell export
65
+
49
66
  ### Database Operations
50
67
 
51
68
  - `pgpm deploy` - Deploy database changes and migrations
@@ -0,0 +1,3 @@
1
+ import { CLIOptions, Inquirerer } from 'inquirerer';
2
+ declare const _default: (argv: Partial<Record<string, any>>, _prompter: Inquirerer, _options: CLIOptions) => Promise<void>;
3
+ export default _default;
@@ -0,0 +1,194 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const child_process_1 = require("child_process");
4
+ const utils_1 = require("../utils");
5
+ const dockerUsageText = `
6
+ Docker Command:
7
+
8
+ pgpm docker <subcommand> [OPTIONS]
9
+
10
+ Manage PostgreSQL Docker containers for local development.
11
+
12
+ Subcommands:
13
+ start Start PostgreSQL container
14
+ stop Stop PostgreSQL container
15
+
16
+ Options:
17
+ --help, -h Show this help message
18
+ --name <name> Container name (default: postgres)
19
+ --image <image> Docker image (default: pyramation/pgvector:13.3-alpine)
20
+ --port <port> Host port mapping (default: 5432)
21
+ --user <user> PostgreSQL user (default: postgres)
22
+ --password <pass> PostgreSQL password (default: password)
23
+ --recreate Remove and recreate container on start
24
+
25
+ Examples:
26
+ pgpm docker start Start default PostgreSQL container
27
+ pgpm docker start --port 5433 Start on custom port
28
+ pgpm docker start --recreate Remove and recreate container
29
+ pgpm docker stop Stop PostgreSQL container
30
+ `;
31
+ function run(command, args, options = {}) {
32
+ return new Promise((resolve, reject) => {
33
+ const stdio = options.stdio || 'pipe';
34
+ const child = (0, child_process_1.spawn)(command, args, { stdio });
35
+ let stdout = '';
36
+ let stderr = '';
37
+ if (stdio === 'pipe') {
38
+ child.stdout?.on('data', (data) => {
39
+ stdout += data.toString();
40
+ });
41
+ child.stderr?.on('data', (data) => {
42
+ stderr += data.toString();
43
+ });
44
+ }
45
+ child.on('error', (error) => {
46
+ reject(error);
47
+ });
48
+ child.on('close', (code) => {
49
+ resolve({
50
+ code: code ?? 0,
51
+ stdout: stdout.trim(),
52
+ stderr: stderr.trim()
53
+ });
54
+ });
55
+ });
56
+ }
57
+ async function checkDockerAvailable() {
58
+ try {
59
+ const result = await run('docker', ['--version']);
60
+ return result.code === 0;
61
+ }
62
+ catch (error) {
63
+ return false;
64
+ }
65
+ }
66
+ async function isContainerRunning(name) {
67
+ try {
68
+ const result = await run('docker', ['inspect', '-f', '{{.State.Running}}', name]);
69
+ if (result.code === 0) {
70
+ return result.stdout.trim() === 'true';
71
+ }
72
+ return null;
73
+ }
74
+ catch (error) {
75
+ return null;
76
+ }
77
+ }
78
+ async function containerExists(name) {
79
+ try {
80
+ const result = await run('docker', ['inspect', name]);
81
+ return result.code === 0;
82
+ }
83
+ catch (error) {
84
+ return false;
85
+ }
86
+ }
87
+ async function startContainer(options) {
88
+ const { name, image, port, user, password, recreate } = options;
89
+ const dockerAvailable = await checkDockerAvailable();
90
+ if (!dockerAvailable) {
91
+ await (0, utils_1.cliExitWithError)('Docker is not installed or not available in PATH. Please install Docker first.');
92
+ return;
93
+ }
94
+ const exists = await containerExists(name);
95
+ const running = await isContainerRunning(name);
96
+ if (running === true) {
97
+ console.log(`βœ… Container "${name}" is already running`);
98
+ return;
99
+ }
100
+ if (recreate && exists) {
101
+ console.log(`πŸ—‘οΈ Removing existing container "${name}"...`);
102
+ const removeResult = await run('docker', ['rm', '-f', name], { stdio: 'inherit' });
103
+ if (removeResult.code !== 0) {
104
+ await (0, utils_1.cliExitWithError)(`Failed to remove container "${name}"`);
105
+ return;
106
+ }
107
+ }
108
+ if (exists && running === false) {
109
+ console.log(`πŸ”„ Starting existing container "${name}"...`);
110
+ const startResult = await run('docker', ['start', name], { stdio: 'inherit' });
111
+ if (startResult.code === 0) {
112
+ console.log(`βœ… Container "${name}" started successfully`);
113
+ }
114
+ else {
115
+ await (0, utils_1.cliExitWithError)(`Failed to start container "${name}"`);
116
+ }
117
+ return;
118
+ }
119
+ console.log(`πŸš€ Creating and starting new container "${name}"...`);
120
+ const runArgs = [
121
+ 'run',
122
+ '-d',
123
+ '--name', name,
124
+ '-e', `POSTGRES_USER=${user}`,
125
+ '-e', `POSTGRES_PASSWORD=${password}`,
126
+ '-p', `${port}:5432`,
127
+ image
128
+ ];
129
+ const runResult = await run('docker', runArgs, { stdio: 'inherit' });
130
+ if (runResult.code === 0) {
131
+ console.log(`βœ… Container "${name}" created and started successfully`);
132
+ console.log(`πŸ“Œ PostgreSQL is available at localhost:${port}`);
133
+ console.log(`πŸ‘€ User: ${user}`);
134
+ console.log(`πŸ”‘ Password: ${password}`);
135
+ }
136
+ else {
137
+ await (0, utils_1.cliExitWithError)(`Failed to create container "${name}". Check if port ${port} is already in use.`);
138
+ }
139
+ }
140
+ async function stopContainer(name) {
141
+ const dockerAvailable = await checkDockerAvailable();
142
+ if (!dockerAvailable) {
143
+ await (0, utils_1.cliExitWithError)('Docker is not installed or not available in PATH. Please install Docker first.');
144
+ return;
145
+ }
146
+ const exists = await containerExists(name);
147
+ if (!exists) {
148
+ console.log(`ℹ️ Container "${name}" not found`);
149
+ return;
150
+ }
151
+ const running = await isContainerRunning(name);
152
+ if (running === false) {
153
+ console.log(`ℹ️ Container "${name}" is already stopped`);
154
+ return;
155
+ }
156
+ console.log(`πŸ›‘ Stopping container "${name}"...`);
157
+ const stopResult = await run('docker', ['stop', name], { stdio: 'inherit' });
158
+ if (stopResult.code === 0) {
159
+ console.log(`βœ… Container "${name}" stopped successfully`);
160
+ }
161
+ else {
162
+ await (0, utils_1.cliExitWithError)(`Failed to stop container "${name}"`);
163
+ }
164
+ }
165
+ exports.default = async (argv, _prompter, _options) => {
166
+ if (argv.help || argv.h) {
167
+ console.log(dockerUsageText);
168
+ process.exit(0);
169
+ }
170
+ const { first: subcommand, newArgv } = (0, utils_1.extractFirst)(argv);
171
+ const args = newArgv;
172
+ if (!subcommand) {
173
+ console.log(dockerUsageText);
174
+ await (0, utils_1.cliExitWithError)('No subcommand provided. Use "start" or "stop".');
175
+ return;
176
+ }
177
+ const name = args.name || 'postgres';
178
+ const image = args.image || 'pyramation/pgvector:13.3-alpine';
179
+ const port = typeof args.port === 'number' ? args.port : 5432;
180
+ const user = args.user || 'postgres';
181
+ const password = args.password || 'password';
182
+ const recreate = args.recreate === true;
183
+ switch (subcommand) {
184
+ case 'start':
185
+ await startContainer({ name, image, port, user, password, recreate });
186
+ break;
187
+ case 'stop':
188
+ await stopContainer(name);
189
+ break;
190
+ default:
191
+ console.log(dockerUsageText);
192
+ await (0, utils_1.cliExitWithError)(`Unknown subcommand: ${subcommand}. Use "start" or "stop".`);
193
+ }
194
+ };
package/commands.js CHANGED
@@ -10,6 +10,7 @@ const admin_users_1 = __importDefault(require("./commands/admin-users"));
10
10
  const analyze_1 = __importDefault(require("./commands/analyze"));
11
11
  const clear_1 = __importDefault(require("./commands/clear"));
12
12
  const deploy_1 = __importDefault(require("./commands/deploy"));
13
+ const docker_1 = __importDefault(require("./commands/docker"));
13
14
  const env_1 = __importDefault(require("./commands/env"));
14
15
  const export_1 = __importDefault(require("./commands/export"));
15
16
  const extension_1 = __importDefault(require("./commands/extension"));
@@ -44,6 +45,7 @@ const createPgpmCommandMap = (skipPgTeardown = false) => {
44
45
  'admin-users': pgt(admin_users_1.default),
45
46
  clear: pgt(clear_1.default),
46
47
  deploy: pgt(deploy_1.default),
48
+ docker: docker_1.default,
47
49
  env: env_1.default,
48
50
  verify: pgt(verify_1.default),
49
51
  revert: pgt(revert_1.default),
@@ -0,0 +1,192 @@
1
+ import { spawn } from 'child_process';
2
+ import { cliExitWithError, extractFirst } from '../utils';
3
+ const dockerUsageText = `
4
+ Docker Command:
5
+
6
+ pgpm docker <subcommand> [OPTIONS]
7
+
8
+ Manage PostgreSQL Docker containers for local development.
9
+
10
+ Subcommands:
11
+ start Start PostgreSQL container
12
+ stop Stop PostgreSQL container
13
+
14
+ Options:
15
+ --help, -h Show this help message
16
+ --name <name> Container name (default: postgres)
17
+ --image <image> Docker image (default: pyramation/pgvector:13.3-alpine)
18
+ --port <port> Host port mapping (default: 5432)
19
+ --user <user> PostgreSQL user (default: postgres)
20
+ --password <pass> PostgreSQL password (default: password)
21
+ --recreate Remove and recreate container on start
22
+
23
+ Examples:
24
+ pgpm docker start Start default PostgreSQL container
25
+ pgpm docker start --port 5433 Start on custom port
26
+ pgpm docker start --recreate Remove and recreate container
27
+ pgpm docker stop Stop PostgreSQL container
28
+ `;
29
+ function run(command, args, options = {}) {
30
+ return new Promise((resolve, reject) => {
31
+ const stdio = options.stdio || 'pipe';
32
+ const child = spawn(command, args, { stdio });
33
+ let stdout = '';
34
+ let stderr = '';
35
+ if (stdio === 'pipe') {
36
+ child.stdout?.on('data', (data) => {
37
+ stdout += data.toString();
38
+ });
39
+ child.stderr?.on('data', (data) => {
40
+ stderr += data.toString();
41
+ });
42
+ }
43
+ child.on('error', (error) => {
44
+ reject(error);
45
+ });
46
+ child.on('close', (code) => {
47
+ resolve({
48
+ code: code ?? 0,
49
+ stdout: stdout.trim(),
50
+ stderr: stderr.trim()
51
+ });
52
+ });
53
+ });
54
+ }
55
+ async function checkDockerAvailable() {
56
+ try {
57
+ const result = await run('docker', ['--version']);
58
+ return result.code === 0;
59
+ }
60
+ catch (error) {
61
+ return false;
62
+ }
63
+ }
64
+ async function isContainerRunning(name) {
65
+ try {
66
+ const result = await run('docker', ['inspect', '-f', '{{.State.Running}}', name]);
67
+ if (result.code === 0) {
68
+ return result.stdout.trim() === 'true';
69
+ }
70
+ return null;
71
+ }
72
+ catch (error) {
73
+ return null;
74
+ }
75
+ }
76
+ async function containerExists(name) {
77
+ try {
78
+ const result = await run('docker', ['inspect', name]);
79
+ return result.code === 0;
80
+ }
81
+ catch (error) {
82
+ return false;
83
+ }
84
+ }
85
+ async function startContainer(options) {
86
+ const { name, image, port, user, password, recreate } = options;
87
+ const dockerAvailable = await checkDockerAvailable();
88
+ if (!dockerAvailable) {
89
+ await cliExitWithError('Docker is not installed or not available in PATH. Please install Docker first.');
90
+ return;
91
+ }
92
+ const exists = await containerExists(name);
93
+ const running = await isContainerRunning(name);
94
+ if (running === true) {
95
+ console.log(`βœ… Container "${name}" is already running`);
96
+ return;
97
+ }
98
+ if (recreate && exists) {
99
+ console.log(`πŸ—‘οΈ Removing existing container "${name}"...`);
100
+ const removeResult = await run('docker', ['rm', '-f', name], { stdio: 'inherit' });
101
+ if (removeResult.code !== 0) {
102
+ await cliExitWithError(`Failed to remove container "${name}"`);
103
+ return;
104
+ }
105
+ }
106
+ if (exists && running === false) {
107
+ console.log(`πŸ”„ Starting existing container "${name}"...`);
108
+ const startResult = await run('docker', ['start', name], { stdio: 'inherit' });
109
+ if (startResult.code === 0) {
110
+ console.log(`βœ… Container "${name}" started successfully`);
111
+ }
112
+ else {
113
+ await cliExitWithError(`Failed to start container "${name}"`);
114
+ }
115
+ return;
116
+ }
117
+ console.log(`πŸš€ Creating and starting new container "${name}"...`);
118
+ const runArgs = [
119
+ 'run',
120
+ '-d',
121
+ '--name', name,
122
+ '-e', `POSTGRES_USER=${user}`,
123
+ '-e', `POSTGRES_PASSWORD=${password}`,
124
+ '-p', `${port}:5432`,
125
+ image
126
+ ];
127
+ const runResult = await run('docker', runArgs, { stdio: 'inherit' });
128
+ if (runResult.code === 0) {
129
+ console.log(`βœ… Container "${name}" created and started successfully`);
130
+ console.log(`πŸ“Œ PostgreSQL is available at localhost:${port}`);
131
+ console.log(`πŸ‘€ User: ${user}`);
132
+ console.log(`πŸ”‘ Password: ${password}`);
133
+ }
134
+ else {
135
+ await cliExitWithError(`Failed to create container "${name}". Check if port ${port} is already in use.`);
136
+ }
137
+ }
138
+ async function stopContainer(name) {
139
+ const dockerAvailable = await checkDockerAvailable();
140
+ if (!dockerAvailable) {
141
+ await cliExitWithError('Docker is not installed or not available in PATH. Please install Docker first.');
142
+ return;
143
+ }
144
+ const exists = await containerExists(name);
145
+ if (!exists) {
146
+ console.log(`ℹ️ Container "${name}" not found`);
147
+ return;
148
+ }
149
+ const running = await isContainerRunning(name);
150
+ if (running === false) {
151
+ console.log(`ℹ️ Container "${name}" is already stopped`);
152
+ return;
153
+ }
154
+ console.log(`πŸ›‘ Stopping container "${name}"...`);
155
+ const stopResult = await run('docker', ['stop', name], { stdio: 'inherit' });
156
+ if (stopResult.code === 0) {
157
+ console.log(`βœ… Container "${name}" stopped successfully`);
158
+ }
159
+ else {
160
+ await cliExitWithError(`Failed to stop container "${name}"`);
161
+ }
162
+ }
163
+ export default async (argv, _prompter, _options) => {
164
+ if (argv.help || argv.h) {
165
+ console.log(dockerUsageText);
166
+ process.exit(0);
167
+ }
168
+ const { first: subcommand, newArgv } = extractFirst(argv);
169
+ const args = newArgv;
170
+ if (!subcommand) {
171
+ console.log(dockerUsageText);
172
+ await cliExitWithError('No subcommand provided. Use "start" or "stop".');
173
+ return;
174
+ }
175
+ const name = args.name || 'postgres';
176
+ const image = args.image || 'pyramation/pgvector:13.3-alpine';
177
+ const port = typeof args.port === 'number' ? args.port : 5432;
178
+ const user = args.user || 'postgres';
179
+ const password = args.password || 'password';
180
+ const recreate = args.recreate === true;
181
+ switch (subcommand) {
182
+ case 'start':
183
+ await startContainer({ name, image, port, user, password, recreate });
184
+ break;
185
+ case 'stop':
186
+ await stopContainer(name);
187
+ break;
188
+ default:
189
+ console.log(dockerUsageText);
190
+ await cliExitWithError(`Unknown subcommand: ${subcommand}. Use "start" or "stop".`);
191
+ }
192
+ };
package/esm/commands.js CHANGED
@@ -4,6 +4,7 @@ import adminUsers from './commands/admin-users';
4
4
  import analyze from './commands/analyze';
5
5
  import clear from './commands/clear';
6
6
  import deploy from './commands/deploy';
7
+ import docker from './commands/docker';
7
8
  import env from './commands/env';
8
9
  import _export from './commands/export';
9
10
  import extension from './commands/extension';
@@ -38,6 +39,7 @@ export const createPgpmCommandMap = (skipPgTeardown = false) => {
38
39
  'admin-users': pgt(adminUsers),
39
40
  clear: pgt(clear),
40
41
  deploy: pgt(deploy),
42
+ docker,
41
43
  env,
42
44
  verify: pgt(verify),
43
45
  revert: pgt(revert),
package/esm/index.js CHANGED
@@ -9,6 +9,7 @@ export { default as adminUsers } from './commands/admin-users';
9
9
  export { default as analyze } from './commands/analyze';
10
10
  export { default as clear } from './commands/clear';
11
11
  export { default as deploy } from './commands/deploy';
12
+ export { default as docker } from './commands/docker';
12
13
  export { default as env } from './commands/env';
13
14
  export { default as _export } from './commands/export';
14
15
  export { default as extension } from './commands/extension';
package/index.d.ts CHANGED
@@ -7,6 +7,7 @@ export { default as adminUsers } from './commands/admin-users';
7
7
  export { default as analyze } from './commands/analyze';
8
8
  export { default as clear } from './commands/clear';
9
9
  export { default as deploy } from './commands/deploy';
10
+ export { default as docker } from './commands/docker';
10
11
  export { default as env } from './commands/env';
11
12
  export { default as _export } from './commands/export';
12
13
  export { default as extension } from './commands/extension';
package/index.js CHANGED
@@ -18,7 +18,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
18
18
  return (mod && mod.__esModule) ? mod : { "default": mod };
19
19
  };
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.options = exports.verify = exports.tag = exports.revert = exports.renameCmd = exports.remove = exports.plan = exports._package = exports.migrate = exports.kill = exports.install = exports.extension = exports._export = exports.env = exports.deploy = exports.clear = exports.analyze = exports.adminUsers = exports.add = exports.createPgpmCommandMap = void 0;
21
+ exports.options = exports.verify = exports.tag = exports.revert = exports.renameCmd = exports.remove = exports.plan = exports._package = exports.migrate = exports.kill = exports.install = exports.extension = exports._export = exports.env = exports.docker = exports.deploy = exports.clear = exports.analyze = exports.adminUsers = exports.add = exports.createPgpmCommandMap = void 0;
22
22
  const fs_1 = require("fs");
23
23
  const inquirerer_1 = require("inquirerer");
24
24
  const path_1 = require("path");
@@ -34,6 +34,8 @@ var clear_1 = require("./commands/clear");
34
34
  Object.defineProperty(exports, "clear", { enumerable: true, get: function () { return __importDefault(clear_1).default; } });
35
35
  var deploy_1 = require("./commands/deploy");
36
36
  Object.defineProperty(exports, "deploy", { enumerable: true, get: function () { return __importDefault(deploy_1).default; } });
37
+ var docker_1 = require("./commands/docker");
38
+ Object.defineProperty(exports, "docker", { enumerable: true, get: function () { return __importDefault(docker_1).default; } });
37
39
  var env_1 = require("./commands/env");
38
40
  Object.defineProperty(exports, "env", { enumerable: true, get: function () { return __importDefault(env_1).default; } });
39
41
  var export_1 = require("./commands/export");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pgpm",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "author": "Dan Lynch <pyramation@gmail.com>",
5
5
  "description": "PostgreSQL Package Manager - Database migration and package management CLI",
6
6
  "main": "index.js",
@@ -70,5 +70,5 @@
70
70
  "pg",
71
71
  "pgsql"
72
72
  ],
73
- "gitHead": "2bc45c48444fc9c2cce9f082cf33d533915bb048"
73
+ "gitHead": "6fc8eb0f1fdf69575f7198708121e4f43134c965"
74
74
  }