@boopkit/cli 0.1.1 → 0.1.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/dist/capability-versions.json +17 -0
- package/dist/commands/init.js +91 -20
- package/dist/lib/capability.d.ts +4 -2
- package/dist/lib/capability.js +30 -25
- package/dist/lib/scaffold.d.ts +6 -2
- package/dist/lib/scaffold.js +35 -6
- package/package.json +2 -2
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"@boopkit/cap-api": "0.1.0",
|
|
3
|
+
"@boopkit/cap-cloud-storage": "0.1.0",
|
|
4
|
+
"@boopkit/cap-coding": "0.1.0",
|
|
5
|
+
"@boopkit/cap-database": "0.1.0",
|
|
6
|
+
"@boopkit/cap-email": "0.1.0",
|
|
7
|
+
"@boopkit/cap-hello": "0.1.0",
|
|
8
|
+
"@boopkit/cap-noticeboard": "0.1.0",
|
|
9
|
+
"@boopkit/cap-product-design": "0.1.0",
|
|
10
|
+
"@boopkit/cap-project-mgmt": "0.1.0",
|
|
11
|
+
"@boopkit/cap-services": "0.1.0",
|
|
12
|
+
"@boopkit/cap-skills": "0.1.0",
|
|
13
|
+
"@boopkit/cap-testing": "0.1.0",
|
|
14
|
+
"@boopkit/cap-users": "0.1.0",
|
|
15
|
+
"@boopkit/cap-web": "0.1.0",
|
|
16
|
+
"@boopkit/logger": "0.1.0"
|
|
17
|
+
}
|
package/dist/commands/init.js
CHANGED
|
@@ -85,11 +85,19 @@ function runInit(name, options) {
|
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
// --- Pre-flight: detect script conflicts before writing anything ---
|
|
88
|
+
// When running from npm (not the monorepo), capabilities can't be resolved
|
|
89
|
+
// until after npm install. Defer conflict check to after install in that case.
|
|
88
90
|
const capabilityNames = profile.defaultCapabilities;
|
|
89
91
|
const preflightScripts = {};
|
|
92
|
+
let preflight = true;
|
|
90
93
|
for (const capName of capabilityNames) {
|
|
91
94
|
const cap = (0, capability_1.getCapability)(capName);
|
|
92
|
-
if (!cap
|
|
95
|
+
if (!cap) {
|
|
96
|
+
// Can't resolve capabilities yet — will install first, then check
|
|
97
|
+
preflight = false;
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
if (!cap.scripts)
|
|
93
101
|
continue;
|
|
94
102
|
for (const scriptName of Object.keys(cap.scripts)) {
|
|
95
103
|
if (scriptName in preflightScripts) {
|
|
@@ -102,15 +110,19 @@ function runInit(name, options) {
|
|
|
102
110
|
}
|
|
103
111
|
// --- Create directory ---
|
|
104
112
|
fs.mkdirSync(targetDir, { recursive: true });
|
|
105
|
-
// --- Collect hooks from capabilities ---
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
113
|
+
// --- Collect hooks from capabilities (deferred if not resolvable yet) ---
|
|
114
|
+
let hookVars = (0, scaffold_1.collectHooks)([]);
|
|
115
|
+
const canResolveLocally = capabilityNames.every(n => (0, capability_1.getCapability)(n) !== null);
|
|
116
|
+
if (canResolveLocally) {
|
|
117
|
+
const hookEntries = [];
|
|
118
|
+
for (const capName of capabilityNames) {
|
|
119
|
+
const cap = (0, capability_1.getCapability)(capName);
|
|
120
|
+
if (cap?.hooks) {
|
|
121
|
+
hookEntries.push({ name: capName, hooks: cap.hooks });
|
|
122
|
+
}
|
|
111
123
|
}
|
|
124
|
+
hookVars = (0, scaffold_1.collectHooks)(hookEntries);
|
|
112
125
|
}
|
|
113
|
-
const hookVars = (0, scaffold_1.collectHooks)(hookEntries);
|
|
114
126
|
// --- Scaffold kernel ---
|
|
115
127
|
const variables = {
|
|
116
128
|
projectName: name,
|
|
@@ -130,6 +142,65 @@ function runInit(name, options) {
|
|
|
130
142
|
capabilities: [],
|
|
131
143
|
createdAt: new Date().toISOString(),
|
|
132
144
|
});
|
|
145
|
+
// --- Add capability package deps and install before resolving ---
|
|
146
|
+
// When running from npm (not the monorepo), capability packages aren't in
|
|
147
|
+
// the CLI's node_modules. We add them to the project's package.json first,
|
|
148
|
+
// run npm install, then resolve from the project's node_modules.
|
|
149
|
+
const capDeps = {};
|
|
150
|
+
for (const capName of capabilityNames) {
|
|
151
|
+
const pkgName = `@boopkit/cap-${capName}`;
|
|
152
|
+
capDeps[pkgName] = (0, scaffold_1.getBoopkitVersion)(pkgName);
|
|
153
|
+
}
|
|
154
|
+
(0, scaffold_1.mergePackageJson)(targetDir, undefined, undefined, capDeps, { skipBackup: true });
|
|
155
|
+
// Run npm install early so capability packages are available for resolution
|
|
156
|
+
if (shouldInstall) {
|
|
157
|
+
try {
|
|
158
|
+
console.log('\nInstalling dependencies...');
|
|
159
|
+
(0, child_process_1.execSync)('npm install', { cwd: targetDir, stdio: 'inherit' });
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
console.error('Warning: npm install failed. You can run it manually later.');
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// Search paths for capability resolution: project dir first, then CLI root
|
|
166
|
+
const capSearchPaths = [targetDir];
|
|
167
|
+
// If hooks couldn't be collected before kernel scaffold (remote install),
|
|
168
|
+
// collect them now and re-scaffold kernel templates that use hook variables.
|
|
169
|
+
if (!canResolveLocally) {
|
|
170
|
+
const hookEntries = [];
|
|
171
|
+
for (const capName of capabilityNames) {
|
|
172
|
+
const cap = (0, capability_1.getCapability)(capName, capSearchPaths);
|
|
173
|
+
if (cap?.hooks) {
|
|
174
|
+
hookEntries.push({ name: capName, hooks: cap.hooks });
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
hookVars = (0, scaffold_1.collectHooks)(hookEntries);
|
|
178
|
+
// Re-scaffold kernel with correct hook variables
|
|
179
|
+
variables.hookImports = hookVars.hookImports;
|
|
180
|
+
variables.hookInit = hookVars.hookInit;
|
|
181
|
+
variables.hookPreRoutes = hookVars.hookPreRoutes;
|
|
182
|
+
variables.hookPostRoutes = hookVars.hookPostRoutes;
|
|
183
|
+
(0, scaffold_1.scaffoldKernel)(targetDir, variables, true);
|
|
184
|
+
}
|
|
185
|
+
// Post-install conflict check (when preflight was deferred)
|
|
186
|
+
if (!preflight) {
|
|
187
|
+
const postScripts = {};
|
|
188
|
+
for (const capName of capabilityNames) {
|
|
189
|
+
const cap = (0, capability_1.getCapability)(capName, capSearchPaths);
|
|
190
|
+
if (!cap?.scripts)
|
|
191
|
+
continue;
|
|
192
|
+
for (const scriptName of Object.keys(cap.scripts)) {
|
|
193
|
+
if (scriptName in postScripts) {
|
|
194
|
+
console.error(`Error: Script "${scriptName}" conflicts between capabilities "${postScripts[scriptName]}" and "${capName}".`);
|
|
195
|
+
// Already created the directory, but the project is incomplete — warn user
|
|
196
|
+
console.error('The project directory has been partially created and may need cleanup.');
|
|
197
|
+
process.exitCode = 1;
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
postScripts[scriptName] = capName;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
133
204
|
// --- Resolve and install capabilities ---
|
|
134
205
|
const installedCapabilities = [];
|
|
135
206
|
const allScripts = {};
|
|
@@ -137,13 +208,13 @@ function runInit(name, options) {
|
|
|
137
208
|
const capabilityFiles = [];
|
|
138
209
|
const cssCapMap = {};
|
|
139
210
|
for (const capName of capabilityNames) {
|
|
140
|
-
const cap = (0, capability_1.getCapability)(capName);
|
|
211
|
+
const cap = (0, capability_1.getCapability)(capName, capSearchPaths);
|
|
141
212
|
if (!cap) {
|
|
142
213
|
console.error(`Warning: Capability "${capName}" not found, skipping.`);
|
|
143
214
|
continue;
|
|
144
215
|
}
|
|
145
216
|
// Copy capability files (skills, scaffolded files, etc.)
|
|
146
|
-
const copied = (0, scaffold_1.copyCapabilityFiles)(targetDir, capName);
|
|
217
|
+
const copied = (0, scaffold_1.copyCapabilityFiles)(targetDir, capName, capSearchPaths);
|
|
147
218
|
capabilityFiles.push(...copied);
|
|
148
219
|
// Track CSS partials for annotation
|
|
149
220
|
for (const f of copied) {
|
|
@@ -194,7 +265,7 @@ function runInit(name, options) {
|
|
|
194
265
|
const capabilityConfig = {};
|
|
195
266
|
const envEntries = [];
|
|
196
267
|
for (const capName of installedCapabilities) {
|
|
197
|
-
const cap = (0, capability_1.getCapability)(capName);
|
|
268
|
+
const cap = (0, capability_1.getCapability)(capName, capSearchPaths);
|
|
198
269
|
if (cap?.env && cap.env.length > 0) {
|
|
199
270
|
const envConfig = {};
|
|
200
271
|
for (const e of cap.env) {
|
|
@@ -239,7 +310,7 @@ function runInit(name, options) {
|
|
|
239
310
|
const typeOrder = ['application', 'development', 'operations', 'demo'];
|
|
240
311
|
const grouped = new Map();
|
|
241
312
|
for (const capName of installedCapabilities) {
|
|
242
|
-
const cap = (0, capability_1.getCapability)(capName);
|
|
313
|
+
const cap = (0, capability_1.getCapability)(capName, capSearchPaths);
|
|
243
314
|
const key = cap?.type ?? 'other';
|
|
244
315
|
if (!grouped.has(key))
|
|
245
316
|
grouped.set(key, []);
|
|
@@ -253,15 +324,8 @@ function runInit(name, options) {
|
|
|
253
324
|
const label = typeLabels[type] ?? type;
|
|
254
325
|
console.log(` ${label}: ${caps.join(', ')}`);
|
|
255
326
|
}
|
|
256
|
-
// ---
|
|
327
|
+
// --- Post-install setup (CSS build, Prisma generate) ---
|
|
257
328
|
if (shouldInstall) {
|
|
258
|
-
try {
|
|
259
|
-
console.log('\nInstalling dependencies...');
|
|
260
|
-
(0, child_process_1.execSync)('npm install', { cwd: targetDir, stdio: 'inherit' });
|
|
261
|
-
}
|
|
262
|
-
catch {
|
|
263
|
-
console.error('Warning: npm install failed. You can run it manually later.');
|
|
264
|
-
}
|
|
265
329
|
// Build CSS if tailwind:build script exists
|
|
266
330
|
const pkgPath = path.join(targetDir, 'package.json');
|
|
267
331
|
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
@@ -284,6 +348,13 @@ function runInit(name, options) {
|
|
|
284
348
|
console.error('Warning: Prisma generate failed. Run `npm run db:generate` manually.');
|
|
285
349
|
}
|
|
286
350
|
}
|
|
351
|
+
// Re-run npm install to pick up any new deps added by capability scaffolding
|
|
352
|
+
try {
|
|
353
|
+
(0, child_process_1.execSync)('npm install', { cwd: targetDir, stdio: 'inherit' });
|
|
354
|
+
}
|
|
355
|
+
catch {
|
|
356
|
+
// Already warned earlier if npm install has issues
|
|
357
|
+
}
|
|
287
358
|
}
|
|
288
359
|
console.log(`\nNext steps:`);
|
|
289
360
|
console.log(` cd ${name}`);
|
package/dist/lib/capability.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { CapabilityMetadata } from './config';
|
|
2
2
|
/**
|
|
3
3
|
* Resolve the directory of an installed @boopkit/cap-{name} package.
|
|
4
|
+
* Searches in the provided paths first, then falls back to boopRoot.
|
|
4
5
|
* Returns null if not found.
|
|
5
6
|
*/
|
|
6
|
-
export declare function getPackageDir(name: string): string | null;
|
|
7
|
+
export declare function getPackageDir(name: string, searchPaths?: string[]): string | null;
|
|
7
8
|
/**
|
|
8
9
|
* List all capabilities by scanning package directory and capabilities/ source tree (test fixtures only).
|
|
9
10
|
* Package resolution takes priority. Returns metadata for each valid capability.
|
|
@@ -12,6 +13,7 @@ export declare function listCapabilities(): CapabilityMetadata[];
|
|
|
12
13
|
/**
|
|
13
14
|
* Get a single capability's metadata by name.
|
|
14
15
|
* Tries package resolution first, falls back to source tree.
|
|
16
|
+
* Pass searchPaths to resolve from a project's node_modules (e.g. during init).
|
|
15
17
|
* Returns null if not found in either location.
|
|
16
18
|
*/
|
|
17
|
-
export declare function getCapability(name: string): CapabilityMetadata | null;
|
|
19
|
+
export declare function getCapability(name: string, searchPaths?: string[]): CapabilityMetadata | null;
|
package/dist/lib/capability.js
CHANGED
|
@@ -41,29 +41,31 @@ const path = __importStar(require("path"));
|
|
|
41
41
|
const config_1 = require("./config");
|
|
42
42
|
/**
|
|
43
43
|
* Resolve the directory of an installed @boopkit/cap-{name} package.
|
|
44
|
+
* Searches in the provided paths first, then falls back to boopRoot.
|
|
44
45
|
* Returns null if not found.
|
|
45
46
|
*/
|
|
46
|
-
function getPackageDir(name) {
|
|
47
|
+
function getPackageDir(name, searchPaths) {
|
|
47
48
|
const pkgName = `@boopkit/cap-${name}`;
|
|
49
|
+
const paths = [...(searchPaths ?? []), (0, config_1.getBoopRoot)()];
|
|
48
50
|
try {
|
|
49
51
|
const pkgJsonPath = require.resolve(`${pkgName}/package.json`, {
|
|
50
|
-
paths
|
|
52
|
+
paths,
|
|
51
53
|
});
|
|
52
54
|
return path.dirname(pkgJsonPath);
|
|
53
55
|
}
|
|
54
56
|
catch {
|
|
55
57
|
// Fall back to scanning for a package whose capability.json has this name
|
|
56
|
-
return findPackageDirByCapabilityName(name);
|
|
58
|
+
return findPackageDirByCapabilityName(name, paths);
|
|
57
59
|
}
|
|
58
60
|
}
|
|
59
61
|
/**
|
|
60
62
|
* Read capability metadata from a package's capability.json.
|
|
61
63
|
* Returns null if the package is not found or has no capability.json.
|
|
62
64
|
*/
|
|
63
|
-
function getCapabilityFromPackage(name) {
|
|
65
|
+
function getCapabilityFromPackage(name, searchPaths) {
|
|
64
66
|
// getPackageDir already falls back to findPackageDirByCapabilityName on
|
|
65
67
|
// require.resolve failure, so no secondary scan needed here.
|
|
66
|
-
const pkgDir = getPackageDir(name);
|
|
68
|
+
const pkgDir = getPackageDir(name, searchPaths);
|
|
67
69
|
if (!pkgDir)
|
|
68
70
|
return null;
|
|
69
71
|
const capJsonPath = path.join(pkgDir, 'capability.json');
|
|
@@ -84,25 +86,27 @@ function getCapabilityFromPackage(name) {
|
|
|
84
86
|
* has the given capability name. Handles mismatches between capability name
|
|
85
87
|
* and package name (e.g. "users-and-accounts" → @boopkit/cap-users).
|
|
86
88
|
*/
|
|
87
|
-
function findPackageDirByCapabilityName(name) {
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const entries = fs.readdirSync(nodeModulesBoopkit, { withFileTypes: true });
|
|
92
|
-
for (const entry of entries) {
|
|
93
|
-
if ((!entry.isDirectory() && !entry.isSymbolicLink()) || !entry.name.startsWith('cap-'))
|
|
94
|
-
continue;
|
|
95
|
-
const dir = path.join(nodeModulesBoopkit, entry.name);
|
|
96
|
-
const capJsonPath = path.join(dir, 'capability.json');
|
|
97
|
-
if (!fs.existsSync(capJsonPath))
|
|
98
|
-
continue;
|
|
99
|
-
try {
|
|
100
|
-
const capJson = JSON.parse(fs.readFileSync(capJsonPath, 'utf-8'));
|
|
101
|
-
if (capJson.name === name)
|
|
102
|
-
return dir;
|
|
103
|
-
}
|
|
104
|
-
catch {
|
|
89
|
+
function findPackageDirByCapabilityName(name, searchPaths) {
|
|
90
|
+
for (const basePath of searchPaths) {
|
|
91
|
+
const nodeModulesBoopkit = path.join(basePath, 'node_modules', '@boopkit');
|
|
92
|
+
if (!fs.existsSync(nodeModulesBoopkit))
|
|
105
93
|
continue;
|
|
94
|
+
const entries = fs.readdirSync(nodeModulesBoopkit, { withFileTypes: true });
|
|
95
|
+
for (const entry of entries) {
|
|
96
|
+
if ((!entry.isDirectory() && !entry.isSymbolicLink()) || !entry.name.startsWith('cap-'))
|
|
97
|
+
continue;
|
|
98
|
+
const dir = path.join(nodeModulesBoopkit, entry.name);
|
|
99
|
+
const capJsonPath = path.join(dir, 'capability.json');
|
|
100
|
+
if (!fs.existsSync(capJsonPath))
|
|
101
|
+
continue;
|
|
102
|
+
try {
|
|
103
|
+
const capJson = JSON.parse(fs.readFileSync(capJsonPath, 'utf-8'));
|
|
104
|
+
if (capJson.name === name)
|
|
105
|
+
return dir;
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
106
110
|
}
|
|
107
111
|
}
|
|
108
112
|
return null;
|
|
@@ -149,11 +153,12 @@ function listCapabilities() {
|
|
|
149
153
|
/**
|
|
150
154
|
* Get a single capability's metadata by name.
|
|
151
155
|
* Tries package resolution first, falls back to source tree.
|
|
156
|
+
* Pass searchPaths to resolve from a project's node_modules (e.g. during init).
|
|
152
157
|
* Returns null if not found in either location.
|
|
153
158
|
*/
|
|
154
|
-
function getCapability(name) {
|
|
159
|
+
function getCapability(name, searchPaths) {
|
|
155
160
|
// Try package first
|
|
156
|
-
const fromPackage = getCapabilityFromPackage(name);
|
|
161
|
+
const fromPackage = getCapabilityFromPackage(name, searchPaths);
|
|
157
162
|
if (fromPackage)
|
|
158
163
|
return fromPackage;
|
|
159
164
|
// Fall back to source tree
|
package/dist/lib/scaffold.d.ts
CHANGED
|
@@ -35,7 +35,7 @@ export declare function hashFile(filePath: string): string;
|
|
|
35
35
|
* Tries package resolution first (scaffold/ and skills/ dirs), falls back to source tree.
|
|
36
36
|
* Returns list of copied file paths relative to targetDir, and file hashes.
|
|
37
37
|
*/
|
|
38
|
-
export declare function copyCapabilityFiles(targetDir: string, capabilityName: string): string[];
|
|
38
|
+
export declare function copyCapabilityFiles(targetDir: string, capabilityName: string, searchPaths?: string[]): string[];
|
|
39
39
|
/**
|
|
40
40
|
* Merge dependencies into an existing package.json.
|
|
41
41
|
* Does not overwrite existing dependency versions.
|
|
@@ -45,7 +45,11 @@ export declare function copyCapabilityFiles(targetDir: string, capabilityName: s
|
|
|
45
45
|
*/
|
|
46
46
|
/**
|
|
47
47
|
* Read the version from a @boopkit/ package's package.json and return ^version.
|
|
48
|
-
*
|
|
48
|
+
* Fallback chain:
|
|
49
|
+
* 1. Monorepo packages/ dir (development)
|
|
50
|
+
* 2. require.resolve from CLI's node_modules
|
|
51
|
+
* 3. dist/capability-versions.json (baked at build time for npm installs)
|
|
52
|
+
* 4. '*' (last resort)
|
|
49
53
|
*/
|
|
50
54
|
export declare function getBoopkitVersion(packageName: string): string;
|
|
51
55
|
export declare function mergePackageJson(targetDir: string, dependencies?: string[], devDependencies?: string[], packages?: Record<string, string>, options?: {
|
package/dist/lib/scaffold.js
CHANGED
|
@@ -125,8 +125,8 @@ function hashFile(filePath) {
|
|
|
125
125
|
* Tries package resolution first (scaffold/ and skills/ dirs), falls back to source tree.
|
|
126
126
|
* Returns list of copied file paths relative to targetDir, and file hashes.
|
|
127
127
|
*/
|
|
128
|
-
function copyCapabilityFiles(targetDir, capabilityName) {
|
|
129
|
-
const pkgDir = (0, capability_1.getPackageDir)(capabilityName);
|
|
128
|
+
function copyCapabilityFiles(targetDir, capabilityName, searchPaths) {
|
|
129
|
+
const pkgDir = (0, capability_1.getPackageDir)(capabilityName, searchPaths);
|
|
130
130
|
if (pkgDir) {
|
|
131
131
|
// Read package.json for boopkit config
|
|
132
132
|
const pkgJsonPath = path.join(pkgDir, 'package.json');
|
|
@@ -276,18 +276,47 @@ function scaffoldCapabilityFiles(targetDir, filesDir) {
|
|
|
276
276
|
*/
|
|
277
277
|
/**
|
|
278
278
|
* Read the version from a @boopkit/ package's package.json and return ^version.
|
|
279
|
-
*
|
|
279
|
+
* Fallback chain:
|
|
280
|
+
* 1. Monorepo packages/ dir (development)
|
|
281
|
+
* 2. require.resolve from CLI's node_modules
|
|
282
|
+
* 3. dist/capability-versions.json (baked at build time for npm installs)
|
|
283
|
+
* 4. '*' (last resort)
|
|
280
284
|
*/
|
|
281
285
|
function getBoopkitVersion(packageName) {
|
|
282
286
|
const pkgName = packageName.replace(/^@boopkit\//, '');
|
|
283
|
-
|
|
287
|
+
// Try monorepo packages/ directory first (development)
|
|
288
|
+
const monorepoPkgJsonPath = path.join((0, config_1.getBoopRoot)(), 'packages', pkgName, 'package.json');
|
|
284
289
|
try {
|
|
285
|
-
const pkg = JSON.parse(fs.readFileSync(
|
|
290
|
+
const pkg = JSON.parse(fs.readFileSync(monorepoPkgJsonPath, 'utf-8'));
|
|
286
291
|
return `^${pkg.version}`;
|
|
287
292
|
}
|
|
288
293
|
catch {
|
|
289
|
-
|
|
294
|
+
// Not in monorepo — try require.resolve (published CLI install)
|
|
290
295
|
}
|
|
296
|
+
// Try resolving the installed package
|
|
297
|
+
try {
|
|
298
|
+
const resolvedPath = require.resolve(`${packageName}/package.json`, {
|
|
299
|
+
paths: [(0, config_1.getBoopRoot)()],
|
|
300
|
+
});
|
|
301
|
+
const pkg = JSON.parse(fs.readFileSync(resolvedPath, 'utf-8'));
|
|
302
|
+
return `^${pkg.version}`;
|
|
303
|
+
}
|
|
304
|
+
catch {
|
|
305
|
+
// Not found via require.resolve
|
|
306
|
+
}
|
|
307
|
+
// Try build-time version manifest (baked into dist/ at publish time)
|
|
308
|
+
try {
|
|
309
|
+
const manifestPath = path.join((0, config_1.getBoopRoot)(), 'dist', 'capability-versions.json');
|
|
310
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
|
|
311
|
+
const fullName = packageName.startsWith('@') ? packageName : `@boopkit/${pkgName}`;
|
|
312
|
+
if (manifest[fullName]) {
|
|
313
|
+
return `^${manifest[fullName]}`;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
catch {
|
|
317
|
+
// No manifest available
|
|
318
|
+
}
|
|
319
|
+
return '*';
|
|
291
320
|
}
|
|
292
321
|
function parseDep(dep) {
|
|
293
322
|
// Handle scoped packages: @scope/name@version
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@boopkit/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "CLI tool to scaffold new projects from boop profiles and capabilities",
|
|
5
5
|
"main": "dist/cli.js",
|
|
6
6
|
"workspaces": [
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"access": "public"
|
|
19
19
|
},
|
|
20
20
|
"scripts": {
|
|
21
|
-
"build": "tsc",
|
|
21
|
+
"build": "tsc && node tools/generate-version-manifest.js",
|
|
22
22
|
"dev": "tsx src/cli.ts",
|
|
23
23
|
"start": "node dist/cli.js",
|
|
24
24
|
"test": "jest"
|