pgpm 4.26.4 → 4.28.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
@@ -455,6 +455,20 @@ Most commands support these global options:
455
455
  - `--version, -v` - Show version information
456
456
  - `--cwd <dir>` - Set working directory
457
457
 
458
+ ## AI Agent Skills
459
+
460
+ Install the pgpm skill for AI coding agents (Devin, Claude Code, Cursor, Copilot):
461
+
462
+ ```bash
463
+ npx skills add https://github.com/constructive-io/constructive --skill pgpm
464
+ ```
465
+
466
+ For the full Constructive platform skills (security, blueprints, codegen, billing, etc.):
467
+
468
+ ```bash
469
+ npx skills add constructive-io/constructive-skills
470
+ ```
471
+
458
472
  ---
459
473
 
460
474
  ## Education and Tutorials
@@ -507,6 +521,17 @@ Common issues and solutions for pgpm, PostgreSQL, and testing.
507
521
 
508
522
  * [constructive-skills](https://github.com/constructive-io/constructive-skills): **📖 Platform documentation and AI agent skills** — feature catalog, blueprint reference, SDK guides (i18n, billing, limits, events, uploads, security, entities, search, AI), and deployment guides.
509
523
 
524
+ Install skills for AI coding agents:
525
+
526
+ ```bash
527
+ # All platform skills (security, blueprints, codegen, billing, etc.)
528
+ npx skills add constructive-io/constructive-skills
529
+
530
+ # Individual repo skills (pgpm, testing, CLI, search, etc.)
531
+ npx skills add https://github.com/constructive-io/constructive --skill pgpm
532
+ npx skills add https://github.com/constructive-io/constructive --skill constructive-testing
533
+ ```
534
+
510
535
  ## Credits
511
536
 
512
537
  **🛠 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).**
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.createInitUsageText = void 0;
7
+ const child_process_1 = require("child_process");
7
8
  const fs_1 = __importDefault(require("fs"));
8
9
  const path_1 = __importDefault(require("path"));
9
10
  const core_1 = require("@pgpmjs/core");
@@ -35,6 +36,7 @@ Options:
35
36
  --template, -t <path> Full template path (e.g., pnpm/module) - combines dir and fromPath
36
37
  --boilerplate Prompt to select from available boilerplates
37
38
  --create-workspace, -w Create a workspace first, then create the module inside it
39
+ --use-skills Use npx skills CLI for skill installation (slower, writes skills-lock.json)
38
40
 
39
41
  Examples:
40
42
  ${binaryName} init Initialize new module (default)
@@ -64,6 +66,7 @@ async function handleInit(argv, prompter) {
64
66
  const noTty = Boolean(argv.noTty || argv['no-tty'] || argv.tty === false || process.env.CI === 'true');
65
67
  const useBoilerplatePrompt = Boolean(argv.boilerplate);
66
68
  const createWorkspace = Boolean(argv.createWorkspace || argv['create-workspace'] || argv.w);
69
+ const useNpxSkills = Boolean(argv.useSkills || argv['use-skills']);
67
70
  // Get fromPath from first positional arg
68
71
  const positionalFromPath = argv._?.[0];
69
72
  // Handle --template flag: parses "dir/fromPath" format and extracts both components
@@ -92,6 +95,7 @@ async function handleInit(argv, prompter) {
92
95
  dir,
93
96
  noTty,
94
97
  cwd,
98
+ useNpxSkills,
95
99
  });
96
100
  }
97
101
  // Regular init path: --template takes precedence, then positional arg, then default to 'module'
@@ -117,6 +121,7 @@ async function handleInit(argv, prompter) {
117
121
  dir,
118
122
  noTty,
119
123
  cwd,
124
+ useNpxSkills,
120
125
  });
121
126
  }
122
127
  // Default to module init (for 'module' type, 'generic' type, or unknown types)
@@ -129,6 +134,7 @@ async function handleInit(argv, prompter) {
129
134
  cwd,
130
135
  requiresWorkspace: inspection.config?.requiresWorkspace,
131
136
  createWorkspace,
137
+ useNpxSkills,
132
138
  }, wasExplicitModuleRequest);
133
139
  }
134
140
  async function handleBoilerplateInit(argv, prompter, ctx) {
@@ -194,6 +200,7 @@ async function handleBoilerplateInit(argv, prompter, ctx) {
194
200
  dir: ctx.dir,
195
201
  noTty: ctx.noTty,
196
202
  cwd: ctx.cwd,
203
+ useNpxSkills: ctx.useNpxSkills,
197
204
  });
198
205
  }
199
206
  // Default to module init (for 'module' type, 'generic' type, or unknown types)
@@ -206,8 +213,68 @@ async function handleBoilerplateInit(argv, prompter, ctx) {
206
213
  noTty: ctx.noTty,
207
214
  cwd: ctx.cwd,
208
215
  requiresWorkspace: inspection.config?.requiresWorkspace,
216
+ useNpxSkills: ctx.useNpxSkills,
209
217
  }, true);
210
218
  }
219
+ function installSkills(skills, cwd, useNpxSkills) {
220
+ if (process.env.PGPM_SKIP_SKILL_INSTALL)
221
+ return;
222
+ if (useNpxSkills) {
223
+ installSkillsViaNpx(skills, cwd);
224
+ }
225
+ else {
226
+ installSkillsBuiltin(skills, cwd);
227
+ }
228
+ }
229
+ function installSkillsBuiltin(skills, cwd) {
230
+ const installer = new core_1.SkillInstaller({ toolName: core_1.DEFAULT_TEMPLATE_TOOL_NAME });
231
+ const result = installer.install(skills, cwd);
232
+ if (result.installed.length > 0) {
233
+ for (const name of result.installed) {
234
+ process.stdout.write(` installed ${name}\n`);
235
+ }
236
+ }
237
+ if (result.failed.length > 0) {
238
+ process.stdout.write('\n⚠️ Some skills could not be installed automatically.\n');
239
+ process.stdout.write('Run the following commands manually:\n\n');
240
+ for (const f of result.failed) {
241
+ const source = f.source.includes('://')
242
+ ? f.source
243
+ : `https://github.com/${f.source}`;
244
+ process.stdout.write(` npx skills add ${source} --skill ${f.skill}\n`);
245
+ }
246
+ process.stdout.write('\n');
247
+ }
248
+ }
249
+ function installSkillsViaNpx(skills, cwd) {
250
+ const failed = [];
251
+ for (const entry of skills) {
252
+ const source = entry.source.includes('://')
253
+ ? entry.source
254
+ : `https://github.com/${entry.source}`;
255
+ for (const skill of entry.skills) {
256
+ const cmd = `npx --yes skills add ${source} --skill ${skill} --yes`;
257
+ try {
258
+ (0, child_process_1.execSync)(cmd, {
259
+ cwd,
260
+ stdio: ['pipe', 'inherit', 'inherit'],
261
+ timeout: 120_000,
262
+ });
263
+ }
264
+ catch {
265
+ failed.push(` npx skills add ${source} --skill ${skill}`);
266
+ }
267
+ }
268
+ }
269
+ if (failed.length > 0) {
270
+ process.stdout.write('\n⚠️ Some skills could not be installed automatically.\n');
271
+ process.stdout.write('Run the following commands manually:\n\n');
272
+ for (const cmd of failed) {
273
+ process.stdout.write(`${cmd}\n`);
274
+ }
275
+ process.stdout.write('\n');
276
+ }
277
+ }
211
278
  async function handleWorkspaceInit(argv, prompter, ctx) {
212
279
  const workspaceQuestions = [
213
280
  {
@@ -254,6 +321,18 @@ async function handleWorkspaceInit(argv, prompter, ctx) {
254
321
  if (!motd.endsWith('\n')) {
255
322
  process.stdout.write('\n');
256
323
  }
324
+ // Install skills declared in .boilerplate.json
325
+ const templateInfo = (0, core_1.inspectTemplate)({
326
+ fromPath: ctx.fromPath,
327
+ templateRepo: ctx.templateRepo,
328
+ branch: ctx.branch,
329
+ dir: ctx.dir,
330
+ cwd: ctx.cwd,
331
+ });
332
+ if (templateInfo.config?.skills?.length) {
333
+ process.stdout.write('\n📦 Installing skills...\n\n');
334
+ installSkills(templateInfo.config.skills, targetPath, Boolean(ctx.useNpxSkills));
335
+ }
257
336
  const relPath = path_1.default.relative(process.cwd(), targetPath);
258
337
  process.stdout.write(`\n✨ Enjoy!\n\ncd ./${relPath}\n`);
259
338
  return { ...argv, ...answers, cwd: targetPath };
@@ -502,6 +581,19 @@ async function handleModuleInit(argv, prompter, ctx, wasExplicitModuleRequest =
502
581
  if (!motd.endsWith('\n')) {
503
582
  process.stdout.write('\n');
504
583
  }
584
+ // Install skills declared in .boilerplate.json
585
+ const moduleTemplateInfo = (0, core_1.inspectTemplate)({
586
+ fromPath: ctx.fromPath,
587
+ templateRepo: ctx.templateRepo,
588
+ branch: ctx.branch,
589
+ dir: ctx.dir,
590
+ cwd: ctx.cwd,
591
+ });
592
+ if (moduleTemplateInfo.config?.skills?.length) {
593
+ const skillsCwd = project.workspacePath || modulePath;
594
+ process.stdout.write('\n📦 Installing skills...\n\n');
595
+ installSkills(moduleTemplateInfo.config.skills, skillsCwd, Boolean(ctx.useNpxSkills));
596
+ }
505
597
  const relPath = path_1.default.relative(process.cwd(), modulePath);
506
598
  process.stdout.write(`\n✨ Enjoy!\n\ncd ./${relPath}\n`);
507
599
  return { ...argv, ...answers };
@@ -1,6 +1,7 @@
1
+ import { execSync } from 'child_process';
1
2
  import fs from 'fs';
2
3
  import path from 'path';
3
- import { DEFAULT_TEMPLATE_REPO, DEFAULT_TEMPLATE_TOOL_NAME, inspectTemplate, PgpmPackage, resolveBoilerplateBaseDir, scaffoldTemplate, scanBoilerplates, sluggify, } from '@pgpmjs/core';
4
+ import { DEFAULT_TEMPLATE_REPO, DEFAULT_TEMPLATE_TOOL_NAME, inspectTemplate, PgpmPackage, resolveBoilerplateBaseDir, scaffoldTemplate, scanBoilerplates, SkillInstaller, sluggify, } from '@pgpmjs/core';
4
5
  import { resolveWorkspaceByType } from '@pgpmjs/env';
5
6
  import { errors } from '@pgpmjs/types';
6
7
  import { registerDefaultResolver } from 'inquirerer';
@@ -29,6 +30,7 @@ Options:
29
30
  --template, -t <path> Full template path (e.g., pnpm/module) - combines dir and fromPath
30
31
  --boilerplate Prompt to select from available boilerplates
31
32
  --create-workspace, -w Create a workspace first, then create the module inside it
33
+ --use-skills Use npx skills CLI for skill installation (slower, writes skills-lock.json)
32
34
 
33
35
  Examples:
34
36
  ${binaryName} init Initialize new module (default)
@@ -57,6 +59,7 @@ async function handleInit(argv, prompter) {
57
59
  const noTty = Boolean(argv.noTty || argv['no-tty'] || argv.tty === false || process.env.CI === 'true');
58
60
  const useBoilerplatePrompt = Boolean(argv.boilerplate);
59
61
  const createWorkspace = Boolean(argv.createWorkspace || argv['create-workspace'] || argv.w);
62
+ const useNpxSkills = Boolean(argv.useSkills || argv['use-skills']);
60
63
  // Get fromPath from first positional arg
61
64
  const positionalFromPath = argv._?.[0];
62
65
  // Handle --template flag: parses "dir/fromPath" format and extracts both components
@@ -85,6 +88,7 @@ async function handleInit(argv, prompter) {
85
88
  dir,
86
89
  noTty,
87
90
  cwd,
91
+ useNpxSkills,
88
92
  });
89
93
  }
90
94
  // Regular init path: --template takes precedence, then positional arg, then default to 'module'
@@ -110,6 +114,7 @@ async function handleInit(argv, prompter) {
110
114
  dir,
111
115
  noTty,
112
116
  cwd,
117
+ useNpxSkills,
113
118
  });
114
119
  }
115
120
  // Default to module init (for 'module' type, 'generic' type, or unknown types)
@@ -122,6 +127,7 @@ async function handleInit(argv, prompter) {
122
127
  cwd,
123
128
  requiresWorkspace: inspection.config?.requiresWorkspace,
124
129
  createWorkspace,
130
+ useNpxSkills,
125
131
  }, wasExplicitModuleRequest);
126
132
  }
127
133
  async function handleBoilerplateInit(argv, prompter, ctx) {
@@ -187,6 +193,7 @@ async function handleBoilerplateInit(argv, prompter, ctx) {
187
193
  dir: ctx.dir,
188
194
  noTty: ctx.noTty,
189
195
  cwd: ctx.cwd,
196
+ useNpxSkills: ctx.useNpxSkills,
190
197
  });
191
198
  }
192
199
  // Default to module init (for 'module' type, 'generic' type, or unknown types)
@@ -199,8 +206,68 @@ async function handleBoilerplateInit(argv, prompter, ctx) {
199
206
  noTty: ctx.noTty,
200
207
  cwd: ctx.cwd,
201
208
  requiresWorkspace: inspection.config?.requiresWorkspace,
209
+ useNpxSkills: ctx.useNpxSkills,
202
210
  }, true);
203
211
  }
212
+ function installSkills(skills, cwd, useNpxSkills) {
213
+ if (process.env.PGPM_SKIP_SKILL_INSTALL)
214
+ return;
215
+ if (useNpxSkills) {
216
+ installSkillsViaNpx(skills, cwd);
217
+ }
218
+ else {
219
+ installSkillsBuiltin(skills, cwd);
220
+ }
221
+ }
222
+ function installSkillsBuiltin(skills, cwd) {
223
+ const installer = new SkillInstaller({ toolName: DEFAULT_TEMPLATE_TOOL_NAME });
224
+ const result = installer.install(skills, cwd);
225
+ if (result.installed.length > 0) {
226
+ for (const name of result.installed) {
227
+ process.stdout.write(` installed ${name}\n`);
228
+ }
229
+ }
230
+ if (result.failed.length > 0) {
231
+ process.stdout.write('\n⚠️ Some skills could not be installed automatically.\n');
232
+ process.stdout.write('Run the following commands manually:\n\n');
233
+ for (const f of result.failed) {
234
+ const source = f.source.includes('://')
235
+ ? f.source
236
+ : `https://github.com/${f.source}`;
237
+ process.stdout.write(` npx skills add ${source} --skill ${f.skill}\n`);
238
+ }
239
+ process.stdout.write('\n');
240
+ }
241
+ }
242
+ function installSkillsViaNpx(skills, cwd) {
243
+ const failed = [];
244
+ for (const entry of skills) {
245
+ const source = entry.source.includes('://')
246
+ ? entry.source
247
+ : `https://github.com/${entry.source}`;
248
+ for (const skill of entry.skills) {
249
+ const cmd = `npx --yes skills add ${source} --skill ${skill} --yes`;
250
+ try {
251
+ execSync(cmd, {
252
+ cwd,
253
+ stdio: ['pipe', 'inherit', 'inherit'],
254
+ timeout: 120_000,
255
+ });
256
+ }
257
+ catch {
258
+ failed.push(` npx skills add ${source} --skill ${skill}`);
259
+ }
260
+ }
261
+ }
262
+ if (failed.length > 0) {
263
+ process.stdout.write('\n⚠️ Some skills could not be installed automatically.\n');
264
+ process.stdout.write('Run the following commands manually:\n\n');
265
+ for (const cmd of failed) {
266
+ process.stdout.write(`${cmd}\n`);
267
+ }
268
+ process.stdout.write('\n');
269
+ }
270
+ }
204
271
  async function handleWorkspaceInit(argv, prompter, ctx) {
205
272
  const workspaceQuestions = [
206
273
  {
@@ -247,6 +314,18 @@ async function handleWorkspaceInit(argv, prompter, ctx) {
247
314
  if (!motd.endsWith('\n')) {
248
315
  process.stdout.write('\n');
249
316
  }
317
+ // Install skills declared in .boilerplate.json
318
+ const templateInfo = inspectTemplate({
319
+ fromPath: ctx.fromPath,
320
+ templateRepo: ctx.templateRepo,
321
+ branch: ctx.branch,
322
+ dir: ctx.dir,
323
+ cwd: ctx.cwd,
324
+ });
325
+ if (templateInfo.config?.skills?.length) {
326
+ process.stdout.write('\n📦 Installing skills...\n\n');
327
+ installSkills(templateInfo.config.skills, targetPath, Boolean(ctx.useNpxSkills));
328
+ }
250
329
  const relPath = path.relative(process.cwd(), targetPath);
251
330
  process.stdout.write(`\n✨ Enjoy!\n\ncd ./${relPath}\n`);
252
331
  return { ...argv, ...answers, cwd: targetPath };
@@ -495,6 +574,19 @@ async function handleModuleInit(argv, prompter, ctx, wasExplicitModuleRequest =
495
574
  if (!motd.endsWith('\n')) {
496
575
  process.stdout.write('\n');
497
576
  }
577
+ // Install skills declared in .boilerplate.json
578
+ const moduleTemplateInfo = inspectTemplate({
579
+ fromPath: ctx.fromPath,
580
+ templateRepo: ctx.templateRepo,
581
+ branch: ctx.branch,
582
+ dir: ctx.dir,
583
+ cwd: ctx.cwd,
584
+ });
585
+ if (moduleTemplateInfo.config?.skills?.length) {
586
+ const skillsCwd = project.workspacePath || modulePath;
587
+ process.stdout.write('\n📦 Installing skills...\n\n');
588
+ installSkills(moduleTemplateInfo.config.skills, skillsCwd, Boolean(ctx.useNpxSkills));
589
+ }
498
590
  const relPath = path.relative(process.cwd(), modulePath);
499
591
  process.stdout.write(`\n✨ Enjoy!\n\ncd ./${relPath}\n`);
500
592
  return { ...argv, ...answers };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pgpm",
3
- "version": "4.26.4",
3
+ "version": "4.28.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,15 +46,15 @@
46
46
  },
47
47
  "dependencies": {
48
48
  "@inquirerer/utils": "^3.3.7",
49
- "@pgpmjs/core": "^6.22.1",
49
+ "@pgpmjs/core": "^6.24.0",
50
50
  "@pgpmjs/env": "^2.25.0",
51
- "@pgpmjs/export": "^0.21.1",
51
+ "@pgpmjs/export": "^0.21.3",
52
52
  "@pgpmjs/logger": "^2.12.0",
53
53
  "@pgpmjs/types": "^2.29.0",
54
54
  "@pgsql/quotes": "^17.1.0",
55
55
  "appstash": "^0.7.0",
56
56
  "find-and-require-package-json": "^0.9.1",
57
- "genomic": "^5.4.0",
57
+ "genomic": "^5.6.0",
58
58
  "inquirerer": "^4.8.1",
59
59
  "js-yaml": "^4.1.0",
60
60
  "pg-cache": "^3.12.0",
@@ -76,5 +76,5 @@
76
76
  "pg",
77
77
  "pgsql"
78
78
  ],
79
- "gitHead": "d6a34a51d5e889443c2345c80ccfcea050875bda"
79
+ "gitHead": "659c7776183c8dc497e640c384e8d1af45965065"
80
80
  }