@powerhousedao/ph-clint-cli 0.1.0-dev.25 → 0.1.0-dev.26
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.
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import type { ClintProjectSpec } from '../spec/types.js';
|
|
2
|
+
import type { ProcessRunOptions } from '@powerhousedao/ph-clint';
|
|
3
|
+
/**
|
|
4
|
+
* Signature for the subprocess runner — matches CommandContext.runProcess.
|
|
5
|
+
*/
|
|
6
|
+
type RunProcess = (command: string, opts?: Omit<ProcessRunOptions, 'onOutput'>) => Promise<{
|
|
7
|
+
success: boolean;
|
|
8
|
+
output: string;
|
|
9
|
+
}>;
|
|
2
10
|
export interface PhInitOptions {
|
|
3
11
|
/** Absolute path to the project root. */
|
|
4
12
|
targetDir: string;
|
|
@@ -9,8 +17,8 @@ export interface PhInitOptions {
|
|
|
9
17
|
log?: (msg: string) => void;
|
|
10
18
|
/** Override `ph` binary name (for tests). */
|
|
11
19
|
binName?: string;
|
|
12
|
-
/**
|
|
13
|
-
|
|
20
|
+
/** Subprocess runner — uses CommandContext.runProcess when available. */
|
|
21
|
+
runProcess?: RunProcess;
|
|
14
22
|
/** Explicit Powerhouse version to pin `ph init` to (tag or semver). */
|
|
15
23
|
phVersion?: string;
|
|
16
24
|
}
|
|
@@ -32,7 +40,8 @@ export interface PnpmInstallOptions {
|
|
|
32
40
|
log?: (msg: string) => void;
|
|
33
41
|
/** Override `pnpm` binary name (for tests). */
|
|
34
42
|
binName?: string;
|
|
35
|
-
|
|
43
|
+
/** Subprocess runner — uses CommandContext.runProcess when available. */
|
|
44
|
+
runProcess?: RunProcess;
|
|
36
45
|
}
|
|
37
46
|
export interface PnpmInstallResult {
|
|
38
47
|
ran: string[];
|
|
@@ -40,3 +49,4 @@ export interface PnpmInstallResult {
|
|
|
40
49
|
reason?: string;
|
|
41
50
|
}
|
|
42
51
|
export declare function runPnpmInstall(options: PnpmInstallOptions): Promise<PnpmInstallResult>;
|
|
52
|
+
export {};
|
package/dist/codegen/scaffold.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import fs from 'node:fs/promises';
|
|
9
9
|
import path from 'node:path';
|
|
10
10
|
import { execFileSync } from 'node:child_process';
|
|
11
|
-
import { hasCommandOnPath
|
|
11
|
+
import { hasCommandOnPath } from './exec.js';
|
|
12
12
|
/**
|
|
13
13
|
* Detect the installed `ph` CLI version by parsing `ph --version` output.
|
|
14
14
|
* Returns the version string (e.g. '6.0.0-dev.194') or undefined if
|
|
@@ -49,39 +49,51 @@ export async function runPhInit(options) {
|
|
|
49
49
|
// placed a `.gitkeep` + README.md placeholder there; clear it out so
|
|
50
50
|
// ph init has a blank slate to work with.
|
|
51
51
|
await fs.rm(options.appDir, { recursive: true, force: true });
|
|
52
|
+
const args = ['init', appFolder, ...versionArgs, '--pnpm'];
|
|
52
53
|
log(`Running \`${binName} init ${appFolder}\` (version: ${phVersion ?? 'auto'}) in ${options.targetDir} …`);
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
const run = options.runProcess;
|
|
55
|
+
if (run) {
|
|
56
|
+
const result = await run(`${binName} ${args.join(' ')}`, {
|
|
57
|
+
cwd: options.targetDir,
|
|
58
|
+
timeout: 300_000, // ph init + pnpm install can be slow
|
|
59
|
+
});
|
|
60
|
+
const exitCode = result.success ? 0 : 1;
|
|
61
|
+
if (!result.success) {
|
|
62
|
+
log(`\`${binName} init\` failed. ` +
|
|
63
|
+
'You can re-run it manually after resolving the issue.');
|
|
64
|
+
}
|
|
65
|
+
// Patch scoped name
|
|
66
|
+
await patchScopedName(options, appFolder, log);
|
|
67
|
+
return { ran: true, exitCode };
|
|
68
|
+
}
|
|
69
|
+
// Fallback: direct spawn with stdio inherit (for backward compat / tests without context)
|
|
70
|
+
const { runCommand } = await import('./exec.js');
|
|
71
|
+
const result = await runCommand(binName, args, { cwd: options.targetDir, stdio: 'inherit' });
|
|
59
72
|
if (result.exitCode !== 0) {
|
|
60
73
|
log(`\`${binName} init\` exited with code ${result.exitCode}. ` +
|
|
61
74
|
'You can re-run it manually after resolving the issue.');
|
|
62
75
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if (options.spec.scope)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
catch (err) {
|
|
81
|
-
log(`Warning: could not patch app package name: ${err instanceof Error ? err.message : String(err)}`);
|
|
76
|
+
await patchScopedName(options, appFolder, log);
|
|
77
|
+
return { ran: true, exitCode: result.exitCode };
|
|
78
|
+
}
|
|
79
|
+
async function patchScopedName(options, appFolder, log) {
|
|
80
|
+
if (!options.spec.scope)
|
|
81
|
+
return;
|
|
82
|
+
const appPkgJsonPath = path.join(options.appDir, 'package.json');
|
|
83
|
+
try {
|
|
84
|
+
const raw = await fs.readFile(appPkgJsonPath, 'utf8');
|
|
85
|
+
const pkg = JSON.parse(raw);
|
|
86
|
+
const scopedName = `@${options.spec.scope}/${appFolder}`;
|
|
87
|
+
if (pkg.name !== scopedName) {
|
|
88
|
+
pkg.name = scopedName;
|
|
89
|
+
pkg.publishConfig = { access: 'public' };
|
|
90
|
+
await fs.writeFile(appPkgJsonPath, JSON.stringify(pkg, null, 2) + '\n');
|
|
91
|
+
log(`Patched app package name to ${scopedName}`);
|
|
82
92
|
}
|
|
83
93
|
}
|
|
84
|
-
|
|
94
|
+
catch (err) {
|
|
95
|
+
log(`Warning: could not patch app package name: ${err instanceof Error ? err.message : String(err)}`);
|
|
96
|
+
}
|
|
85
97
|
}
|
|
86
98
|
export async function runPnpmInstall(options) {
|
|
87
99
|
const log = options.log ?? (() => { });
|
|
@@ -94,14 +106,27 @@ export async function runPnpmInstall(options) {
|
|
|
94
106
|
const ran = [];
|
|
95
107
|
for (const dir of options.dirs) {
|
|
96
108
|
log(`Running \`${binName} install\` in ${dir} …`);
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
109
|
+
const run = options.runProcess;
|
|
110
|
+
if (run) {
|
|
111
|
+
const result = await run(`${binName} install`, {
|
|
112
|
+
cwd: dir,
|
|
113
|
+
timeout: 300_000,
|
|
114
|
+
});
|
|
115
|
+
if (!result.success) {
|
|
116
|
+
log(`\`${binName} install\` failed in ${dir}. ` +
|
|
117
|
+
'Retry manually once the underlying issue is resolved.');
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
const { runCommand } = await import('./exec.js');
|
|
122
|
+
const result = await runCommand(binName, ['install'], {
|
|
123
|
+
cwd: dir,
|
|
124
|
+
stdio: 'inherit',
|
|
125
|
+
});
|
|
126
|
+
if (result.exitCode !== 0) {
|
|
127
|
+
log(`\`${binName} install\` exited with code ${result.exitCode} in ${dir}. ` +
|
|
128
|
+
'Retry manually once the underlying issue is resolved.');
|
|
129
|
+
}
|
|
105
130
|
}
|
|
106
131
|
ran.push(dir);
|
|
107
132
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import { spawn } from 'node:child_process';
|
|
3
2
|
import { defineCommand } from '@powerhousedao/ph-clint';
|
|
4
3
|
import { z } from 'zod';
|
|
5
4
|
import { detectLayout } from '@powerhousedao/ph-clint-dev';
|
|
@@ -7,44 +6,28 @@ const inputSchema = z.object({
|
|
|
7
6
|
dir: z.string().optional().describe('Project root directory (default: cwd)'),
|
|
8
7
|
verbose: z.boolean().default(false),
|
|
9
8
|
});
|
|
10
|
-
function execInDir(dir, cmd, verbose) {
|
|
11
|
-
return new Promise((resolve, reject) => {
|
|
12
|
-
const proc = spawn(cmd, {
|
|
13
|
-
cwd: dir,
|
|
14
|
-
shell: true,
|
|
15
|
-
stdio: verbose ? 'inherit' : 'pipe',
|
|
16
|
-
});
|
|
17
|
-
let stderr = '';
|
|
18
|
-
if (!verbose && proc.stderr) {
|
|
19
|
-
proc.stderr.on('data', (data) => {
|
|
20
|
-
stderr += data.toString();
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
proc.on('close', (code) => {
|
|
24
|
-
if (code === 0)
|
|
25
|
-
resolve();
|
|
26
|
-
else
|
|
27
|
-
reject(new Error(`Command "${cmd}" failed in ${dir} (exit ${code})${stderr ? `:\n${stderr}` : ''}`));
|
|
28
|
-
});
|
|
29
|
-
proc.on('error', (err) => reject(err));
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
9
|
export const build = defineCommand({
|
|
33
10
|
id: 'clint-project-build',
|
|
34
11
|
description: 'Build all packages in the project',
|
|
35
12
|
inputSchema,
|
|
36
|
-
execute: async (input, { workdir, stdout }) => {
|
|
13
|
+
execute: async (input, { workdir, stdout, runProcess }) => {
|
|
37
14
|
const dir = path.resolve(input.dir ?? workdir);
|
|
38
15
|
const layout = detectLayout(dir);
|
|
39
16
|
if (layout?.type === 'split') {
|
|
40
17
|
stdout(`Building app package (${layout.app})...\n`);
|
|
41
|
-
await
|
|
18
|
+
const appResult = await runProcess('pnpm build', { cwd: layout.app, timeout: 120_000 });
|
|
19
|
+
if (!appResult.success)
|
|
20
|
+
return { text: `App build failed.` };
|
|
42
21
|
stdout(`Building cli package (${layout.cli})...\n`);
|
|
43
|
-
await
|
|
22
|
+
const cliResult = await runProcess('pnpm build', { cwd: layout.cli, timeout: 120_000 });
|
|
23
|
+
if (!cliResult.success)
|
|
24
|
+
return { text: `CLI build failed.` };
|
|
44
25
|
}
|
|
45
26
|
else {
|
|
46
27
|
stdout(`Building project...\n`);
|
|
47
|
-
await
|
|
28
|
+
const result = await runProcess('pnpm build', { cwd: layout?.cli ?? dir, timeout: 120_000 });
|
|
29
|
+
if (!result.success)
|
|
30
|
+
return { text: `Build failed.` };
|
|
48
31
|
}
|
|
49
32
|
return { text: 'Build complete.' };
|
|
50
33
|
},
|
|
@@ -102,7 +102,7 @@ export const init = defineCommand({
|
|
|
102
102
|
promptForDefaults: true,
|
|
103
103
|
promptOptional: ['description'],
|
|
104
104
|
},
|
|
105
|
-
execute: async (input, { workdir, stdout, reactor: getReactor, folders }) => {
|
|
105
|
+
execute: async (input, { workdir, stdout, reactor: getReactor, folders, runProcess }) => {
|
|
106
106
|
const { name: bareName } = splitPackageName(input.name);
|
|
107
107
|
const targetDir = path.resolve(workdir, input.dir ?? bareName);
|
|
108
108
|
if (!input.force) {
|
|
@@ -151,6 +151,7 @@ export const init = defineCommand({
|
|
|
151
151
|
appDir: result.appDir,
|
|
152
152
|
spec,
|
|
153
153
|
log: (msg) => stdout(msg + '\n'),
|
|
154
|
+
runProcess,
|
|
154
155
|
});
|
|
155
156
|
if (!phResult.ran) {
|
|
156
157
|
stdout(`Note: \`ph init\` did not run — ${phResult.reason ?? 'see above'}.\n`);
|
|
@@ -170,6 +171,7 @@ export const init = defineCommand({
|
|
|
170
171
|
await runPnpmInstall({
|
|
171
172
|
dirs,
|
|
172
173
|
log: (msg) => stdout(msg + '\n'),
|
|
174
|
+
runProcess,
|
|
173
175
|
});
|
|
174
176
|
}
|
|
175
177
|
const next = [];
|
|
@@ -200,7 +200,7 @@ export const specChangeTrigger = createDocumentChangeTrigger({
|
|
|
200
200
|
appDir: result.appDir,
|
|
201
201
|
spec,
|
|
202
202
|
log: (msg) => log?.info(`${TAG} ${msg}`),
|
|
203
|
-
|
|
203
|
+
runProcess: ctx.context.runProcess,
|
|
204
204
|
});
|
|
205
205
|
if (!phResult.ran) {
|
|
206
206
|
log?.warn(`${TAG} ph init skipped: ${phResult.reason ?? 'unknown'}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@powerhousedao/ph-clint-cli",
|
|
3
|
-
"version": "0.1.0-dev.
|
|
3
|
+
"version": "0.1.0-dev.26",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
"@mastra/core": "^1.22.0",
|
|
30
30
|
"@mastra/libsql": "^1.7.4",
|
|
31
31
|
"@mastra/memory": "^1.13.1",
|
|
32
|
-
"@powerhousedao/ph-clint": "^0.1.0-dev.
|
|
33
|
-
"@powerhousedao/ph-clint-app": "^0.1.0-dev.
|
|
34
|
-
"@powerhousedao/ph-clint-dev": "^0.1.0-dev.
|
|
32
|
+
"@powerhousedao/ph-clint": "^0.1.0-dev.26",
|
|
33
|
+
"@powerhousedao/ph-clint-app": "^0.1.0-dev.26",
|
|
34
|
+
"@powerhousedao/ph-clint-dev": "^0.1.0-dev.26",
|
|
35
35
|
"@powerhousedao/reactor": "6.0.0-dev.170",
|
|
36
36
|
"@powerhousedao/reactor-api": "6.0.0-dev.170",
|
|
37
37
|
"@powerhousedao/shared": "6.0.0-dev.170",
|