pgpm 2.0.0 → 2.1.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.
@@ -31,12 +31,14 @@ Options:
31
31
  --repo <repo> Template repo (default: https://github.com/constructive-io/pgpm-boilerplates.git)
32
32
  --from-branch <branch> Branch/tag to use when cloning repo
33
33
  --dir <variant> Template variant directory (e.g., supabase, drizzle)
34
+ --boilerplate Prompt to select from available boilerplates
34
35
 
35
36
  Examples:
36
37
  ${binaryName} init Initialize new module (default)
37
38
  ${binaryName} init workspace Initialize new workspace
38
39
  ${binaryName} init module Initialize new module explicitly
39
40
  ${binaryName} init workspace --dir <variant> Use variant templates
41
+ ${binaryName} init --boilerplate Select from available boilerplates
40
42
  ${binaryName} init --repo owner/repo Use templates from GitHub repository
41
43
  ${binaryName} init --repo owner/repo --from-branch develop Use specific branch
42
44
  `;
@@ -56,8 +58,22 @@ async function handleInit(argv, prompter) {
56
58
  const branch = argv.fromBranch;
57
59
  const dir = argv.dir;
58
60
  const noTty = Boolean(argv.noTty || argv['no-tty'] || process.env.CI === 'true');
59
- // Get fromPath from first positional arg, default to 'module'
60
- const fromPath = argv._?.[0] || 'module';
61
+ const useBoilerplatePrompt = Boolean(argv.boilerplate);
62
+ // Get fromPath from first positional arg
63
+ const positionalFromPath = argv._?.[0];
64
+ // Handle --boilerplate flag: separate path from regular init
65
+ if (useBoilerplatePrompt) {
66
+ return handleBoilerplateInit(argv, prompter, {
67
+ positionalFromPath,
68
+ templateRepo,
69
+ branch,
70
+ dir,
71
+ noTty,
72
+ cwd,
73
+ });
74
+ }
75
+ // Regular init path: default to 'module' if no fromPath provided
76
+ const fromPath = positionalFromPath || 'module';
61
77
  // Inspect the template to get its type
62
78
  const inspection = (0, core_1.inspectTemplate)({
63
79
  fromPath,
@@ -89,6 +105,81 @@ async function handleInit(argv, prompter) {
89
105
  cwd,
90
106
  });
91
107
  }
108
+ async function handleBoilerplateInit(argv, prompter, ctx) {
109
+ let fromPath;
110
+ if (ctx.positionalFromPath) {
111
+ // If a positional fromPath was provided with --boilerplate, use it directly
112
+ fromPath = ctx.positionalFromPath;
113
+ }
114
+ else {
115
+ // No positional arg: prompt user to select from available boilerplates
116
+ if (ctx.noTty) {
117
+ throw new Error('Cannot use --boilerplate without a <fromPath> argument in non-interactive mode. ' +
118
+ 'Please specify a boilerplate explicitly, e.g., `pgpm init workspace --boilerplate`');
119
+ }
120
+ // Inspect without fromPath to get the template directory for scanning
121
+ const initialInspection = (0, core_1.inspectTemplate)({
122
+ templateRepo: ctx.templateRepo,
123
+ branch: ctx.branch,
124
+ dir: ctx.dir,
125
+ toolName: core_1.DEFAULT_TEMPLATE_TOOL_NAME,
126
+ cwd: ctx.cwd,
127
+ });
128
+ // Resolve the base directory for scanning boilerplates:
129
+ // - If --dir is specified, use the resolvedTemplatePath (bypasses .boilerplates.json)
130
+ // - Otherwise, use .boilerplates.json's dir (defaults to repo root if missing)
131
+ const baseDir = ctx.dir
132
+ ? initialInspection.resolvedTemplatePath
133
+ : (0, core_1.resolveBoilerplateBaseDir)(initialInspection.templateDir);
134
+ const boilerplates = (0, core_1.scanBoilerplates)(baseDir);
135
+ if (boilerplates.length === 0) {
136
+ throw new Error(`No boilerplates found in the template repository.\n` +
137
+ `Checked directory: ${baseDir}\n` +
138
+ `Make sure the repository contains boilerplate directories with .boilerplate.json files.`);
139
+ }
140
+ const boilerplateQuestion = [
141
+ {
142
+ name: 'selectedBoilerplate',
143
+ message: 'Select a boilerplate',
144
+ type: 'autocomplete',
145
+ options: boilerplates.map((bp) => bp.name),
146
+ required: true,
147
+ },
148
+ ];
149
+ const boilerplateAnswer = await prompter.prompt(argv, boilerplateQuestion);
150
+ fromPath = boilerplateAnswer.selectedBoilerplate;
151
+ }
152
+ // Inspect the selected template to get its type
153
+ const inspection = (0, core_1.inspectTemplate)({
154
+ fromPath,
155
+ templateRepo: ctx.templateRepo,
156
+ branch: ctx.branch,
157
+ dir: ctx.dir,
158
+ toolName: core_1.DEFAULT_TEMPLATE_TOOL_NAME,
159
+ cwd: ctx.cwd,
160
+ });
161
+ const templateType = inspection.config?.type;
162
+ // Branch based on template type
163
+ if (templateType === 'workspace') {
164
+ return handleWorkspaceInit(argv, prompter, {
165
+ fromPath,
166
+ templateRepo: ctx.templateRepo,
167
+ branch: ctx.branch,
168
+ dir: ctx.dir,
169
+ noTty: ctx.noTty,
170
+ cwd: ctx.cwd,
171
+ });
172
+ }
173
+ // Default to module init (for 'module' type or unknown types)
174
+ return handleModuleInit(argv, prompter, {
175
+ fromPath,
176
+ templateRepo: ctx.templateRepo,
177
+ branch: ctx.branch,
178
+ dir: ctx.dir,
179
+ noTty: ctx.noTty,
180
+ cwd: ctx.cwd,
181
+ });
182
+ }
92
183
  async function handleWorkspaceInit(argv, prompter, ctx) {
93
184
  const workspaceQuestions = [
94
185
  {
@@ -1,6 +1,6 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
- import { DEFAULT_TEMPLATE_REPO, DEFAULT_TEMPLATE_TOOL_NAME, inspectTemplate, PgpmPackage, scaffoldTemplate, sluggify, } from '@pgpmjs/core';
3
+ import { DEFAULT_TEMPLATE_REPO, DEFAULT_TEMPLATE_TOOL_NAME, inspectTemplate, PgpmPackage, resolveBoilerplateBaseDir, scaffoldTemplate, scanBoilerplates, sluggify, } from '@pgpmjs/core';
4
4
  import { errors } from '@pgpmjs/types';
5
5
  import { registerDefaultResolver } from 'inquirerer';
6
6
  const DEFAULT_MOTD = `
@@ -25,12 +25,14 @@ Options:
25
25
  --repo <repo> Template repo (default: https://github.com/constructive-io/pgpm-boilerplates.git)
26
26
  --from-branch <branch> Branch/tag to use when cloning repo
27
27
  --dir <variant> Template variant directory (e.g., supabase, drizzle)
28
+ --boilerplate Prompt to select from available boilerplates
28
29
 
29
30
  Examples:
30
31
  ${binaryName} init Initialize new module (default)
31
32
  ${binaryName} init workspace Initialize new workspace
32
33
  ${binaryName} init module Initialize new module explicitly
33
34
  ${binaryName} init workspace --dir <variant> Use variant templates
35
+ ${binaryName} init --boilerplate Select from available boilerplates
34
36
  ${binaryName} init --repo owner/repo Use templates from GitHub repository
35
37
  ${binaryName} init --repo owner/repo --from-branch develop Use specific branch
36
38
  `;
@@ -49,8 +51,22 @@ async function handleInit(argv, prompter) {
49
51
  const branch = argv.fromBranch;
50
52
  const dir = argv.dir;
51
53
  const noTty = Boolean(argv.noTty || argv['no-tty'] || process.env.CI === 'true');
52
- // Get fromPath from first positional arg, default to 'module'
53
- const fromPath = argv._?.[0] || 'module';
54
+ const useBoilerplatePrompt = Boolean(argv.boilerplate);
55
+ // Get fromPath from first positional arg
56
+ const positionalFromPath = argv._?.[0];
57
+ // Handle --boilerplate flag: separate path from regular init
58
+ if (useBoilerplatePrompt) {
59
+ return handleBoilerplateInit(argv, prompter, {
60
+ positionalFromPath,
61
+ templateRepo,
62
+ branch,
63
+ dir,
64
+ noTty,
65
+ cwd,
66
+ });
67
+ }
68
+ // Regular init path: default to 'module' if no fromPath provided
69
+ const fromPath = positionalFromPath || 'module';
54
70
  // Inspect the template to get its type
55
71
  const inspection = inspectTemplate({
56
72
  fromPath,
@@ -82,6 +98,81 @@ async function handleInit(argv, prompter) {
82
98
  cwd,
83
99
  });
84
100
  }
101
+ async function handleBoilerplateInit(argv, prompter, ctx) {
102
+ let fromPath;
103
+ if (ctx.positionalFromPath) {
104
+ // If a positional fromPath was provided with --boilerplate, use it directly
105
+ fromPath = ctx.positionalFromPath;
106
+ }
107
+ else {
108
+ // No positional arg: prompt user to select from available boilerplates
109
+ if (ctx.noTty) {
110
+ throw new Error('Cannot use --boilerplate without a <fromPath> argument in non-interactive mode. ' +
111
+ 'Please specify a boilerplate explicitly, e.g., `pgpm init workspace --boilerplate`');
112
+ }
113
+ // Inspect without fromPath to get the template directory for scanning
114
+ const initialInspection = inspectTemplate({
115
+ templateRepo: ctx.templateRepo,
116
+ branch: ctx.branch,
117
+ dir: ctx.dir,
118
+ toolName: DEFAULT_TEMPLATE_TOOL_NAME,
119
+ cwd: ctx.cwd,
120
+ });
121
+ // Resolve the base directory for scanning boilerplates:
122
+ // - If --dir is specified, use the resolvedTemplatePath (bypasses .boilerplates.json)
123
+ // - Otherwise, use .boilerplates.json's dir (defaults to repo root if missing)
124
+ const baseDir = ctx.dir
125
+ ? initialInspection.resolvedTemplatePath
126
+ : resolveBoilerplateBaseDir(initialInspection.templateDir);
127
+ const boilerplates = scanBoilerplates(baseDir);
128
+ if (boilerplates.length === 0) {
129
+ throw new Error(`No boilerplates found in the template repository.\n` +
130
+ `Checked directory: ${baseDir}\n` +
131
+ `Make sure the repository contains boilerplate directories with .boilerplate.json files.`);
132
+ }
133
+ const boilerplateQuestion = [
134
+ {
135
+ name: 'selectedBoilerplate',
136
+ message: 'Select a boilerplate',
137
+ type: 'autocomplete',
138
+ options: boilerplates.map((bp) => bp.name),
139
+ required: true,
140
+ },
141
+ ];
142
+ const boilerplateAnswer = await prompter.prompt(argv, boilerplateQuestion);
143
+ fromPath = boilerplateAnswer.selectedBoilerplate;
144
+ }
145
+ // Inspect the selected template to get its type
146
+ const inspection = inspectTemplate({
147
+ fromPath,
148
+ templateRepo: ctx.templateRepo,
149
+ branch: ctx.branch,
150
+ dir: ctx.dir,
151
+ toolName: DEFAULT_TEMPLATE_TOOL_NAME,
152
+ cwd: ctx.cwd,
153
+ });
154
+ const templateType = inspection.config?.type;
155
+ // Branch based on template type
156
+ if (templateType === 'workspace') {
157
+ return handleWorkspaceInit(argv, prompter, {
158
+ fromPath,
159
+ templateRepo: ctx.templateRepo,
160
+ branch: ctx.branch,
161
+ dir: ctx.dir,
162
+ noTty: ctx.noTty,
163
+ cwd: ctx.cwd,
164
+ });
165
+ }
166
+ // Default to module init (for 'module' type or unknown types)
167
+ return handleModuleInit(argv, prompter, {
168
+ fromPath,
169
+ templateRepo: ctx.templateRepo,
170
+ branch: ctx.branch,
171
+ dir: ctx.dir,
172
+ noTty: ctx.noTty,
173
+ cwd: ctx.cwd,
174
+ });
175
+ }
85
176
  async function handleWorkspaceInit(argv, prompter, ctx) {
86
177
  const workspaceQuestions = [
87
178
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pgpm",
3
- "version": "2.0.0",
3
+ "version": "2.1.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",
@@ -45,7 +45,7 @@
45
45
  "ts-node": "^10.9.2"
46
46
  },
47
47
  "dependencies": {
48
- "@pgpmjs/core": "^4.0.0",
48
+ "@pgpmjs/core": "^4.0.1",
49
49
  "@pgpmjs/env": "^2.8.8",
50
50
  "@pgpmjs/logger": "^1.3.5",
51
51
  "@pgpmjs/types": "^2.12.6",
@@ -73,5 +73,5 @@
73
73
  "pg",
74
74
  "pgsql"
75
75
  ],
76
- "gitHead": "b1d773f5215ad5ea1dca82b33b550728fdcd1ec0"
76
+ "gitHead": "b4dd6e24bd84d79f3057d8555b850481b7d4e19a"
77
77
  }