ph-cmd 6.0.0-dev.6 → 6.0.0-dev.7
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/build/cli.js +1495 -0
- package/package.json +8 -8
- package/dist/scripts/generate-commands-md.d.ts +0 -2
- package/dist/scripts/generate-commands-md.d.ts.map +0 -1
- package/dist/scripts/generate-commands-md.js +0 -72
- package/dist/scripts/generate-commands-md.js.map +0 -1
- package/dist/scripts/generate-version.d.ts +0 -2
- package/dist/scripts/generate-version.d.ts.map +0 -1
- package/dist/scripts/generate-version.js +0 -13
- package/dist/scripts/generate-version.js.map +0 -1
- package/dist/src/cli.d.ts +0 -3
- package/dist/src/cli.d.ts.map +0 -1
- package/dist/src/cli.js +0 -120
- package/dist/src/cli.js.map +0 -1
- package/dist/src/commands/__tests__/update.test.d.ts +0 -2
- package/dist/src/commands/__tests__/update.test.d.ts.map +0 -1
- package/dist/src/commands/__tests__/update.test.js +0 -157
- package/dist/src/commands/__tests__/update.test.js.map +0 -1
- package/dist/src/commands/__tests__/use.test.d.ts +0 -2
- package/dist/src/commands/__tests__/use.test.d.ts.map +0 -1
- package/dist/src/commands/__tests__/use.test.js +0 -496
- package/dist/src/commands/__tests__/use.test.js.map +0 -1
- package/dist/src/commands/checkout.d.ts +0 -9
- package/dist/src/commands/checkout.d.ts.map +0 -1
- package/dist/src/commands/checkout.js +0 -37
- package/dist/src/commands/checkout.js.map +0 -1
- package/dist/src/commands/forward.d.ts +0 -7
- package/dist/src/commands/forward.d.ts.map +0 -1
- package/dist/src/commands/forward.js +0 -45
- package/dist/src/commands/forward.js.map +0 -1
- package/dist/src/commands/help.d.ts +0 -7
- package/dist/src/commands/help.d.ts.map +0 -1
- package/dist/src/commands/help.js +0 -14
- package/dist/src/commands/help.js.map +0 -1
- package/dist/src/commands/index.d.ts +0 -9
- package/dist/src/commands/index.d.ts.map +0 -1
- package/dist/src/commands/index.js +0 -15
- package/dist/src/commands/index.js.map +0 -1
- package/dist/src/commands/init.d.ts +0 -2
- package/dist/src/commands/init.d.ts.map +0 -1
- package/dist/src/commands/init.js +0 -165
- package/dist/src/commands/init.js.map +0 -1
- package/dist/src/commands/setup-globals.d.ts +0 -20
- package/dist/src/commands/setup-globals.d.ts.map +0 -1
- package/dist/src/commands/setup-globals.js +0 -24
- package/dist/src/commands/setup-globals.js.map +0 -1
- package/dist/src/commands/update.d.ts +0 -2
- package/dist/src/commands/update.d.ts.map +0 -1
- package/dist/src/commands/update.js +0 -95
- package/dist/src/commands/update.js.map +0 -1
- package/dist/src/commands/update.old.d.ts +0 -13
- package/dist/src/commands/update.old.d.ts.map +0 -1
- package/dist/src/commands/update.old.js +0 -105
- package/dist/src/commands/update.old.js.map +0 -1
- package/dist/src/commands/use-local.d.ts +0 -2
- package/dist/src/commands/use-local.d.ts.map +0 -1
- package/dist/src/commands/use-local.js +0 -115
- package/dist/src/commands/use-local.js.map +0 -1
- package/dist/src/commands/use.d.ts +0 -2
- package/dist/src/commands/use.d.ts.map +0 -1
- package/dist/src/commands/use.js +0 -117
- package/dist/src/commands/use.js.map +0 -1
- package/dist/src/commands/use.old.d.ts +0 -55
- package/dist/src/commands/use.old.d.ts.map +0 -1
- package/dist/src/commands/use.old.js +0 -219
- package/dist/src/commands/use.old.js.map +0 -1
- package/dist/src/commands/version.d.ts +0 -5
- package/dist/src/commands/version.d.ts.map +0 -1
- package/dist/src/commands/version.js +0 -42
- package/dist/src/commands/version.js.map +0 -1
- package/dist/src/help.d.ts +0 -25
- package/dist/src/help.d.ts.map +0 -1
- package/dist/src/help.js +0 -230
- package/dist/src/help.js.map +0 -1
- package/dist/src/index.d.ts +0 -3
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js +0 -3
- package/dist/src/index.js.map +0 -1
- package/dist/src/types.d.ts +0 -2
- package/dist/src/types.d.ts.map +0 -1
- package/dist/src/types.js +0 -2
- package/dist/src/types.js.map +0 -1
- package/dist/src/utils/constants.d.ts +0 -59
- package/dist/src/utils/constants.d.ts.map +0 -1
- package/dist/src/utils/constants.js +0 -102
- package/dist/src/utils/constants.js.map +0 -1
- package/dist/src/utils/dependencies.d.ts +0 -4
- package/dist/src/utils/dependencies.d.ts.map +0 -1
- package/dist/src/utils/dependencies.js +0 -61
- package/dist/src/utils/dependencies.js.map +0 -1
- package/dist/src/utils/file-system.d.ts +0 -2
- package/dist/src/utils/file-system.d.ts.map +0 -1
- package/dist/src/utils/file-system.js +0 -12
- package/dist/src/utils/file-system.js.map +0 -1
- package/dist/src/utils/help-formatting.d.ts +0 -35
- package/dist/src/utils/help-formatting.d.ts.map +0 -1
- package/dist/src/utils/help-formatting.js +0 -188
- package/dist/src/utils/help-formatting.js.map +0 -1
- package/dist/src/utils/help.d.ts +0 -31
- package/dist/src/utils/help.d.ts.map +0 -1
- package/dist/src/utils/help.js +0 -72
- package/dist/src/utils/help.js.map +0 -1
- package/dist/src/utils/index.d.ts +0 -8
- package/dist/src/utils/index.d.ts.map +0 -1
- package/dist/src/utils/index.js +0 -7
- package/dist/src/utils/index.js.map +0 -1
- package/dist/src/utils/package-manager.d.ts +0 -27
- package/dist/src/utils/package-manager.d.ts.map +0 -1
- package/dist/src/utils/package-manager.js +0 -177
- package/dist/src/utils/package-manager.js.map +0 -1
- package/dist/src/utils/parsing.d.ts +0 -20
- package/dist/src/utils/parsing.d.ts.map +0 -1
- package/dist/src/utils/parsing.js +0 -52
- package/dist/src/utils/parsing.js.map +0 -1
- package/dist/src/utils/run-cmd.d.ts +0 -2
- package/dist/src/utils/run-cmd.d.ts.map +0 -1
- package/dist/src/utils/run-cmd.js +0 -11
- package/dist/src/utils/run-cmd.js.map +0 -1
- package/dist/src/utils/types.d.ts +0 -21
- package/dist/src/utils/types.d.ts.map +0 -1
- package/dist/src/utils/types.js +0 -2
- package/dist/src/utils/types.js.map +0 -1
- package/dist/src/utils/validate-remote-drive-checkout.d.ts +0 -7
- package/dist/src/utils/validate-remote-drive-checkout.d.ts.map +0 -1
- package/dist/src/utils/validate-remote-drive-checkout.js +0 -45
- package/dist/src/utils/validate-remote-drive-checkout.js.map +0 -1
- package/dist/src/utils/validate-remote-drive.d.ts +0 -7
- package/dist/src/utils/validate-remote-drive.d.ts.map +0 -1
- package/dist/src/utils/validate-remote-drive.js +0 -51
- package/dist/src/utils/validate-remote-drive.js.map +0 -1
- package/dist/src/version.d.ts +0 -2
- package/dist/src/version.d.ts.map +0 -1
- package/dist/src/version.js +0 -3
- package/dist/src/version.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/dist/vitest.config.d.ts +0 -3
- package/dist/vitest.config.d.ts.map +0 -1
- package/dist/vitest.config.js +0 -7
- package/dist/vitest.config.js.map +0 -1
package/build/cli.js
ADDED
|
@@ -0,0 +1,1495 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli.ts
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
|
|
6
|
+
// src/utils/constants.ts
|
|
7
|
+
import { homedir } from "os";
|
|
8
|
+
import path from "path";
|
|
9
|
+
var PH_BIN_PATH = process.argv[1];
|
|
10
|
+
var PH_BIN = "ph-cli";
|
|
11
|
+
var POWERHOUSE_CONFIG_FILE = "powerhouse.config.json";
|
|
12
|
+
var HOME_DIR = homedir();
|
|
13
|
+
var PH_GLOBAL_DIR_NAME = ".ph";
|
|
14
|
+
var PH_GLOBAL_PACKAGE_NAME = "ph-global";
|
|
15
|
+
var POWERHOUSE_GLOBAL_DIR = path.join(HOME_DIR, PH_GLOBAL_DIR_NAME);
|
|
16
|
+
var packageManagers = {
|
|
17
|
+
bun: {
|
|
18
|
+
installCommand: "bun add {{dependency}}",
|
|
19
|
+
execCommand: `bun ${PH_BIN} {{arguments}}`,
|
|
20
|
+
execScript: `bun {{arguments}}`,
|
|
21
|
+
lockfile: "bun.lock",
|
|
22
|
+
globalPathRegexp: /[\\/].bun[\\/]/,
|
|
23
|
+
updateCommand: "bun update {{dependency}}",
|
|
24
|
+
buildAffected: "bun run build:affected",
|
|
25
|
+
workspaceOption: "",
|
|
26
|
+
installDepsCommand: "bun install"
|
|
27
|
+
},
|
|
28
|
+
pnpm: {
|
|
29
|
+
installCommand: "pnpm add {{dependency}}",
|
|
30
|
+
execCommand: `pnpm exec ${PH_BIN} {{arguments}}`,
|
|
31
|
+
execScript: `pnpm {{arguments}}`,
|
|
32
|
+
lockfile: "pnpm-lock.yaml",
|
|
33
|
+
globalPathRegexp: /[\\/]pnpm[\\/]/,
|
|
34
|
+
updateCommand: "pnpm update {{dependency}}",
|
|
35
|
+
buildAffected: "pnpm run build:affected",
|
|
36
|
+
workspaceOption: "--workspace-root",
|
|
37
|
+
installDepsCommand: "pnpm install"
|
|
38
|
+
},
|
|
39
|
+
yarn: {
|
|
40
|
+
installCommand: "yarn add {{dependency}}",
|
|
41
|
+
execCommand: `yarn ${PH_BIN} {{arguments}}`,
|
|
42
|
+
execScript: `yarn {{arguments}}`,
|
|
43
|
+
lockfile: "yarn.lock",
|
|
44
|
+
globalPathRegexp: /[\\/]yarn[\\/]/,
|
|
45
|
+
updateCommand: "yarn upgrade {{dependency}}",
|
|
46
|
+
buildAffected: "yarn run build:affected",
|
|
47
|
+
workspaceOption: "-W",
|
|
48
|
+
installDepsCommand: "yarn install"
|
|
49
|
+
},
|
|
50
|
+
npm: {
|
|
51
|
+
installCommand: "npm install {{dependency}}",
|
|
52
|
+
execCommand: `npx ${PH_BIN} {{arguments}}`,
|
|
53
|
+
execScript: `npm run {{arguments}}`,
|
|
54
|
+
lockfile: "package-lock.json",
|
|
55
|
+
updateCommand: "npm update {{dependency}} --save",
|
|
56
|
+
buildAffected: "npm run build:affected",
|
|
57
|
+
workspaceOption: "",
|
|
58
|
+
installDepsCommand: "npm install"
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
var PACKAGES_DEPENDENCIES = [
|
|
62
|
+
"@powerhousedao/builder-tools",
|
|
63
|
+
"@powerhousedao/codegen",
|
|
64
|
+
"@powerhousedao/common",
|
|
65
|
+
"@powerhousedao/config",
|
|
66
|
+
"@powerhousedao/design-system",
|
|
67
|
+
"document-drive",
|
|
68
|
+
"document-model",
|
|
69
|
+
"@powerhousedao/reactor",
|
|
70
|
+
"@powerhousedao/reactor-api",
|
|
71
|
+
"@powerhousedao/reactor-browser",
|
|
72
|
+
"@powerhousedao/reactor-local",
|
|
73
|
+
"@powerhousedao/reactor-mcp",
|
|
74
|
+
"@powerhousedao/switchboard-gui",
|
|
75
|
+
"@powerhousedao/vetra"
|
|
76
|
+
];
|
|
77
|
+
var CLIS_DEPENDENCIES = ["ph-cmd", "@powerhousedao/ph-cli"];
|
|
78
|
+
var APPS_DEPENDENCIES = [
|
|
79
|
+
"@powerhousedao/connect",
|
|
80
|
+
"@powerhousedao/switchboard"
|
|
81
|
+
];
|
|
82
|
+
var ALL_POWERHOUSE_DEPENDENCIES = [
|
|
83
|
+
...PACKAGES_DEPENDENCIES,
|
|
84
|
+
...CLIS_DEPENDENCIES,
|
|
85
|
+
...APPS_DEPENDENCIES
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
// src/utils/dependencies.ts
|
|
89
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
90
|
+
import { execSync } from "child_process";
|
|
91
|
+
import path2 from "path";
|
|
92
|
+
|
|
93
|
+
// src/utils/package-manager.ts
|
|
94
|
+
import { createProject } from "@powerhousedao/codegen";
|
|
95
|
+
import { execSync as execSync2 } from "child_process";
|
|
96
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
97
|
+
import path3, { dirname } from "path";
|
|
98
|
+
|
|
99
|
+
// src/utils/parsing.ts
|
|
100
|
+
import chalk from "chalk";
|
|
101
|
+
function parseTag(args) {
|
|
102
|
+
const { tag, dev, staging } = args;
|
|
103
|
+
if (tag) return tag;
|
|
104
|
+
if (dev) return "dev";
|
|
105
|
+
if (staging) return "staging";
|
|
106
|
+
return "latest";
|
|
107
|
+
}
|
|
108
|
+
function parsePackageManager(args) {
|
|
109
|
+
const { npm, pnpm, yarn, bun, packageManager } = args;
|
|
110
|
+
if (npm) return "npm";
|
|
111
|
+
if (pnpm) return "pnpm";
|
|
112
|
+
if (yarn) return "yarn";
|
|
113
|
+
if (bun) return "bun";
|
|
114
|
+
if (packageManager) return packageManager;
|
|
115
|
+
const userAgentPackageManager = process.env.npm_config_user_agent?.match(
|
|
116
|
+
/^(pnpm|npm|yarn|bun)\b/
|
|
117
|
+
)?.[1];
|
|
118
|
+
if (userAgentPackageManager) return userAgentPackageManager;
|
|
119
|
+
return void 0;
|
|
120
|
+
}
|
|
121
|
+
function handleMutuallyExclusiveOptions(options, optionsName) {
|
|
122
|
+
const mutuallyExclusiveOptions = Object.entries(options).map(([k, v]) => {
|
|
123
|
+
if (v !== void 0) return k;
|
|
124
|
+
return void 0;
|
|
125
|
+
}).filter((v) => v !== void 0);
|
|
126
|
+
if (mutuallyExclusiveOptions.length > 1) {
|
|
127
|
+
throw new Error(
|
|
128
|
+
`Cannot specify multiple ${optionsName} options. You provided: ${mutuallyExclusiveOptions.join(", ")}`
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function getTagFromVersion(version) {
|
|
133
|
+
if (version.includes("dev")) return "dev";
|
|
134
|
+
if (version.includes("staging")) return "staging";
|
|
135
|
+
return "latest";
|
|
136
|
+
}
|
|
137
|
+
function logVersionUpdate(args) {
|
|
138
|
+
const { name, version, newVersion } = args;
|
|
139
|
+
console.log(
|
|
140
|
+
`\u2699\uFE0F Updating ${chalk.bold(name)}: ${chalk.blue(version)} -> ${chalk.green(newVersion)}`
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// src/utils/package-manager.ts
|
|
145
|
+
function defaultPathValidation() {
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
function isPowerhouseProject(dir) {
|
|
149
|
+
const powerhouseConfigPath = path3.join(dir, POWERHOUSE_CONFIG_FILE);
|
|
150
|
+
return existsSync2(powerhouseConfigPath);
|
|
151
|
+
}
|
|
152
|
+
function findNodeProjectRoot(dir, pathValidation = defaultPathValidation) {
|
|
153
|
+
const packageJsonPath = path3.join(dir, "package.json");
|
|
154
|
+
if (existsSync2(packageJsonPath) && pathValidation(dir)) {
|
|
155
|
+
return dir;
|
|
156
|
+
}
|
|
157
|
+
const parentDir = dirname(dir);
|
|
158
|
+
if (parentDir === dir) {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
return findNodeProjectRoot(parentDir, pathValidation);
|
|
162
|
+
}
|
|
163
|
+
function getPackageManagerFromPath(dir) {
|
|
164
|
+
const lowerCasePath = dir.toLowerCase();
|
|
165
|
+
if (packageManagers.bun.globalPathRegexp.test(lowerCasePath)) {
|
|
166
|
+
return "bun";
|
|
167
|
+
} else if (packageManagers.pnpm.globalPathRegexp.test(lowerCasePath)) {
|
|
168
|
+
return "pnpm";
|
|
169
|
+
} else if (packageManagers.yarn.globalPathRegexp.test(lowerCasePath)) {
|
|
170
|
+
return "yarn";
|
|
171
|
+
}
|
|
172
|
+
return "npm";
|
|
173
|
+
}
|
|
174
|
+
function getPackageManagerFromLockfile(dir) {
|
|
175
|
+
if (existsSync2(path3.join(dir, packageManagers.pnpm.lockfile))) {
|
|
176
|
+
return "pnpm";
|
|
177
|
+
} else if (existsSync2(path3.join(dir, packageManagers.yarn.lockfile))) {
|
|
178
|
+
return "yarn";
|
|
179
|
+
} else if (existsSync2(path3.join(dir, packageManagers.bun.lockfile))) {
|
|
180
|
+
return "bun";
|
|
181
|
+
}
|
|
182
|
+
return "npm";
|
|
183
|
+
}
|
|
184
|
+
async function getProjectInfo(debug, generateGlobalProject = true) {
|
|
185
|
+
const currentPath = process.cwd();
|
|
186
|
+
if (debug) {
|
|
187
|
+
console.log(">>> currentPath:", currentPath);
|
|
188
|
+
}
|
|
189
|
+
const projectPath = findNodeProjectRoot(currentPath, isPowerhouseProject);
|
|
190
|
+
if (!projectPath) {
|
|
191
|
+
let available = existsSync2(POWERHOUSE_GLOBAL_DIR);
|
|
192
|
+
if (generateGlobalProject) {
|
|
193
|
+
await createGlobalProject();
|
|
194
|
+
available = true;
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
available,
|
|
198
|
+
isGlobal: true,
|
|
199
|
+
path: POWERHOUSE_GLOBAL_DIR
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
isGlobal: false,
|
|
204
|
+
available: true,
|
|
205
|
+
path: projectPath
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
function forwardPHCommand(packageManager, projectPath, args, debug, captureOutput = false) {
|
|
209
|
+
const manager = packageManagers[packageManager];
|
|
210
|
+
const command5 = manager.execCommand;
|
|
211
|
+
const execCommand = command5.replace("{{arguments}}", args);
|
|
212
|
+
const commandOptions = { cwd: projectPath };
|
|
213
|
+
if (debug) {
|
|
214
|
+
console.log(">>> execCommand:", execCommand);
|
|
215
|
+
console.log(">>> commandOptions:", commandOptions);
|
|
216
|
+
console.log(">>> projectPath:", projectPath);
|
|
217
|
+
console.log(">>> packageManager:", packageManager);
|
|
218
|
+
}
|
|
219
|
+
if (captureOutput) {
|
|
220
|
+
try {
|
|
221
|
+
return execSync2(execCommand, {
|
|
222
|
+
stdio: "pipe",
|
|
223
|
+
encoding: "utf8",
|
|
224
|
+
...commandOptions
|
|
225
|
+
});
|
|
226
|
+
} catch (error) {
|
|
227
|
+
throw new Error(
|
|
228
|
+
`Failed to execute command: ${execCommand}
|
|
229
|
+
Error: ${error instanceof Error ? error.message : String(error)}`
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
} else {
|
|
233
|
+
execSync2(execCommand, {
|
|
234
|
+
stdio: "inherit",
|
|
235
|
+
...commandOptions
|
|
236
|
+
});
|
|
237
|
+
return "";
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
var createGlobalProject = async (projectName, options = {}) => {
|
|
241
|
+
const globalProjectExists = existsSync2(POWERHOUSE_GLOBAL_DIR);
|
|
242
|
+
if (globalProjectExists) {
|
|
243
|
+
const packageJsonPath = path3.join(POWERHOUSE_GLOBAL_DIR, "package.json");
|
|
244
|
+
if (existsSync2(packageJsonPath)) {
|
|
245
|
+
try {
|
|
246
|
+
const packageJson = JSON.parse(
|
|
247
|
+
readFileSync2(packageJsonPath, "utf-8")
|
|
248
|
+
);
|
|
249
|
+
if (packageJson.name?.startsWith(".")) {
|
|
250
|
+
console.log("\u{1F4E6} Fixing invalid package name in global project...");
|
|
251
|
+
packageJson.name = PH_GLOBAL_PACKAGE_NAME;
|
|
252
|
+
writeFileSync2(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
253
|
+
}
|
|
254
|
+
} catch {
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
console.log(`\u{1F4E6} Using global project: ${POWERHOUSE_GLOBAL_DIR}`);
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
console.log("\u{1F4E6} Initializing global project...");
|
|
261
|
+
process.chdir(HOME_DIR);
|
|
262
|
+
try {
|
|
263
|
+
await createProject({
|
|
264
|
+
name: PH_GLOBAL_DIR_NAME,
|
|
265
|
+
tag: parseTag(options),
|
|
266
|
+
packageManager: parsePackageManager(options) ?? getPackageManagerFromPath(PH_BIN_PATH)
|
|
267
|
+
});
|
|
268
|
+
const packageJsonPath = path3.join(POWERHOUSE_GLOBAL_DIR, "package.json");
|
|
269
|
+
const packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
|
|
270
|
+
packageJson.name = PH_GLOBAL_PACKAGE_NAME;
|
|
271
|
+
writeFileSync2(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
272
|
+
console.log(
|
|
273
|
+
`\u{1F680} Global project initialized successfully: ${POWERHOUSE_GLOBAL_DIR}`
|
|
274
|
+
);
|
|
275
|
+
} catch (error) {
|
|
276
|
+
console.error("\u274C Failed to initialize the global project", error);
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
// src/utils/help-formatting.ts
|
|
281
|
+
var HELP_FORMATTING_CONFIG = {
|
|
282
|
+
// Column width for command descriptions alignment
|
|
283
|
+
FIXED_COLUMN_WIDTH: 55,
|
|
284
|
+
// List of command names to apply padding to
|
|
285
|
+
COMMANDS_TO_PAD: ["setup-globals", "init", "use", "update", "help"],
|
|
286
|
+
// Padding to add before command descriptions for alignment
|
|
287
|
+
DESCRIPTION_PADDING: " "
|
|
288
|
+
};
|
|
289
|
+
function extractCommandParts(line) {
|
|
290
|
+
let match = /^(\s+\S+(?:\|\S+)*(?:\s+\[options\])?(?:\s+\[[^\]]+\]|\s+<[^>]+>)*)(.*)$/.exec(
|
|
291
|
+
line
|
|
292
|
+
);
|
|
293
|
+
if (!match) {
|
|
294
|
+
match = /^(\s+\S+(?:\|\S+)*)(.*)$/.exec(line);
|
|
295
|
+
}
|
|
296
|
+
if (!match) {
|
|
297
|
+
return { cmd: line, desc: "" };
|
|
298
|
+
}
|
|
299
|
+
return {
|
|
300
|
+
cmd: match[1].trimEnd(),
|
|
301
|
+
desc: match[2].trim()
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
function formatCommandLine({ cmd, desc }, columnWidth) {
|
|
305
|
+
const padding = " ".repeat(Math.max(2, columnWidth - cmd.length));
|
|
306
|
+
return `${cmd}${padding}${desc}`;
|
|
307
|
+
}
|
|
308
|
+
function extractCommandLines(lines, startIndex) {
|
|
309
|
+
const commands2 = [];
|
|
310
|
+
for (let i = startIndex + 1; i < lines.length; i++) {
|
|
311
|
+
const line = lines[i];
|
|
312
|
+
if (!line.trim() || !/^\s{2}\S/.exec(line)) {
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
commands2.push(line);
|
|
316
|
+
}
|
|
317
|
+
return commands2;
|
|
318
|
+
}
|
|
319
|
+
function mergeHelp(cliHelp, forwardedHelp) {
|
|
320
|
+
const cliLines = cliHelp.split("\n");
|
|
321
|
+
const forwardedLines = forwardedHelp.split("\n");
|
|
322
|
+
const cliCommandsIndex = cliLines.findIndex(
|
|
323
|
+
(line) => line.trim() === "Commands:"
|
|
324
|
+
);
|
|
325
|
+
const forwardedCommandsIndex = forwardedLines.findIndex(
|
|
326
|
+
(line) => line.trim() === "Commands:"
|
|
327
|
+
);
|
|
328
|
+
const cliCommands = extractCommandLines(cliLines, cliCommandsIndex);
|
|
329
|
+
const forwardedCommands = extractCommandLines(
|
|
330
|
+
forwardedLines,
|
|
331
|
+
forwardedCommandsIndex
|
|
332
|
+
);
|
|
333
|
+
const cliCommandNames = /* @__PURE__ */ new Set();
|
|
334
|
+
cliCommands.forEach((line) => {
|
|
335
|
+
const match = /^\s+(\S+)(?:\|.*)?/.exec(line);
|
|
336
|
+
if (match) cliCommandNames.add(match[1]);
|
|
337
|
+
});
|
|
338
|
+
const uniqueForwardedCommands = forwardedCommands.filter((line) => {
|
|
339
|
+
const match = /^\s+(\S+)(?:\|.*)?/.exec(line);
|
|
340
|
+
if (!match) return false;
|
|
341
|
+
if (match[1] === "help") return false;
|
|
342
|
+
return !cliCommandNames.has(match[1]);
|
|
343
|
+
});
|
|
344
|
+
const cliParts = cliCommands.map(extractCommandParts);
|
|
345
|
+
const forwardedParts = uniqueForwardedCommands.map(extractCommandParts);
|
|
346
|
+
const formattedCliCommands = cliParts.map(
|
|
347
|
+
(parts) => formatCommandLine(parts, HELP_FORMATTING_CONFIG.FIXED_COLUMN_WIDTH)
|
|
348
|
+
);
|
|
349
|
+
const formattedForwardedCommands = forwardedParts.map(
|
|
350
|
+
(parts) => formatCommandLine(parts, HELP_FORMATTING_CONFIG.FIXED_COLUMN_WIDTH)
|
|
351
|
+
);
|
|
352
|
+
const headerSection = cliLines.slice(0, cliCommandsIndex + 1).join("\n");
|
|
353
|
+
return [
|
|
354
|
+
headerSection,
|
|
355
|
+
formattedCliCommands.join("\n"),
|
|
356
|
+
formattedForwardedCommands.join("\n")
|
|
357
|
+
].join("\n");
|
|
358
|
+
}
|
|
359
|
+
function applyCommandPadding(program2) {
|
|
360
|
+
program2.commands.forEach((cmd) => {
|
|
361
|
+
if (HELP_FORMATTING_CONFIG.COMMANDS_TO_PAD.includes(cmd.name())) {
|
|
362
|
+
const desc = cmd.description();
|
|
363
|
+
cmd.description(HELP_FORMATTING_CONFIG.DESCRIPTION_PADDING + desc);
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
function restoreCommandDescriptions(program2) {
|
|
368
|
+
program2.commands.forEach((cmd) => {
|
|
369
|
+
if (HELP_FORMATTING_CONFIG.COMMANDS_TO_PAD.includes(cmd.name())) {
|
|
370
|
+
const desc = cmd.description();
|
|
371
|
+
cmd.description(desc.trim());
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
function captureCommanderHelp(program2) {
|
|
376
|
+
let helpText = "";
|
|
377
|
+
const originalConsoleLog = console.log;
|
|
378
|
+
console.log = (...args) => {
|
|
379
|
+
helpText += args.join(" ") + "\n";
|
|
380
|
+
};
|
|
381
|
+
program2.outputHelp();
|
|
382
|
+
console.log = originalConsoleLog;
|
|
383
|
+
return helpText;
|
|
384
|
+
}
|
|
385
|
+
var extraHelpLines = `
|
|
386
|
+
init [name] [options] Initialize a new project
|
|
387
|
+
use [release] [options] Specify your version of Powerhouse dependencies
|
|
388
|
+
update Update your powerhouse dependencies
|
|
389
|
+
`;
|
|
390
|
+
function injectExtraHelpLines(helpText, extraLines) {
|
|
391
|
+
const result = `${extraLines}${helpText}`.replaceAll("\n\n", "").replace("\n", "");
|
|
392
|
+
return result;
|
|
393
|
+
}
|
|
394
|
+
async function generateMergedHelp(program2) {
|
|
395
|
+
const projectInfo = await getProjectInfo(void 0, false);
|
|
396
|
+
if (projectInfo.available) {
|
|
397
|
+
const packageManager = getPackageManagerFromLockfile(projectInfo.path);
|
|
398
|
+
const forwardedHelp = forwardPHCommand(
|
|
399
|
+
packageManager,
|
|
400
|
+
projectInfo.path,
|
|
401
|
+
"help",
|
|
402
|
+
void 0,
|
|
403
|
+
true
|
|
404
|
+
);
|
|
405
|
+
applyCommandPadding(program2);
|
|
406
|
+
const helpText = captureCommanderHelp(program2);
|
|
407
|
+
restoreCommandDescriptions(program2);
|
|
408
|
+
const mergedHelp = mergeHelp(helpText, forwardedHelp);
|
|
409
|
+
const withExtraLines = injectExtraHelpLines(mergedHelp, extraHelpLines);
|
|
410
|
+
console.log(withExtraLines);
|
|
411
|
+
} else {
|
|
412
|
+
console.log(captureCommanderHelp(program2));
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// src/utils/help.ts
|
|
417
|
+
function withHelpHandler(command5, actionFn) {
|
|
418
|
+
return (...args) => {
|
|
419
|
+
const rawArgs = process.argv;
|
|
420
|
+
const isHelpRequested = rawArgs.includes("--help") || rawArgs.includes("-h");
|
|
421
|
+
if (isHelpRequested) {
|
|
422
|
+
command5.outputHelp();
|
|
423
|
+
process.exit(0);
|
|
424
|
+
}
|
|
425
|
+
return actionFn(...args);
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
function withHelpAction(command5, actionFn, preCheck) {
|
|
429
|
+
command5.action(
|
|
430
|
+
withHelpHandler(command5, (...args) => {
|
|
431
|
+
if (preCheck) {
|
|
432
|
+
const result = preCheck(...args);
|
|
433
|
+
if (result === false) return;
|
|
434
|
+
}
|
|
435
|
+
return actionFn(...args);
|
|
436
|
+
})
|
|
437
|
+
);
|
|
438
|
+
return command5;
|
|
439
|
+
}
|
|
440
|
+
function withCustomHelp(command5, actionFn, helpText, preCheck) {
|
|
441
|
+
command5.helpInformation = function() {
|
|
442
|
+
const name = command5.name();
|
|
443
|
+
const args = command5.usage();
|
|
444
|
+
const description = command5.description();
|
|
445
|
+
let header = `
|
|
446
|
+
Usage: ph ${name}`;
|
|
447
|
+
if (args) header += ` ${args}`;
|
|
448
|
+
if (description) header += `
|
|
449
|
+
|
|
450
|
+
${description}
|
|
451
|
+
`;
|
|
452
|
+
return header + "\n" + helpText;
|
|
453
|
+
};
|
|
454
|
+
return withHelpAction(command5, actionFn, preCheck);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// src/utils/validate-remote-drive.ts
|
|
458
|
+
import {
|
|
459
|
+
createVetraDocument,
|
|
460
|
+
getVetraDocuments
|
|
461
|
+
} from "@powerhousedao/common/utils";
|
|
462
|
+
async function setupRemoteDrive(remoteDriveUrl) {
|
|
463
|
+
try {
|
|
464
|
+
const driveId = remoteDriveUrl.split("/").pop();
|
|
465
|
+
if (!remoteDriveUrl || remoteDriveUrl.trim() === "") {
|
|
466
|
+
console.error("\u274C Remote drive URL is required");
|
|
467
|
+
return false;
|
|
468
|
+
}
|
|
469
|
+
const url = new URL(remoteDriveUrl);
|
|
470
|
+
const graphqlEndpoint = `${url.protocol}//${url.host}/graphql`;
|
|
471
|
+
let documents = await getVetraDocuments(graphqlEndpoint, driveId);
|
|
472
|
+
if (documents.length === 0) {
|
|
473
|
+
console.log(
|
|
474
|
+
"No vetra package document found in the provided drive, creating one..."
|
|
475
|
+
);
|
|
476
|
+
try {
|
|
477
|
+
await createVetraDocument(graphqlEndpoint, driveId, "vetra-package");
|
|
478
|
+
documents = await getVetraDocuments(graphqlEndpoint, driveId);
|
|
479
|
+
if (documents.length === 0) {
|
|
480
|
+
console.error(
|
|
481
|
+
"\u274C Failed to create vetra package document in the remote drive"
|
|
482
|
+
);
|
|
483
|
+
return false;
|
|
484
|
+
}
|
|
485
|
+
console.log("\u2705 Vetra package document created successfully");
|
|
486
|
+
} catch (createError) {
|
|
487
|
+
console.error(
|
|
488
|
+
"\u274C Failed to create vetra package document:",
|
|
489
|
+
createError
|
|
490
|
+
);
|
|
491
|
+
return false;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
if (documents.length > 1) {
|
|
495
|
+
console.warn(
|
|
496
|
+
"\u26A0\uFE0F Multiple vetra package documents were found in the provided remote drive, this might be an error in your remote drive"
|
|
497
|
+
);
|
|
498
|
+
}
|
|
499
|
+
const hasGithubUrl = documents.some((doc) => doc.githubUrl);
|
|
500
|
+
if (hasGithubUrl) {
|
|
501
|
+
console.error(
|
|
502
|
+
"\u274C The remote drive provided already has been configured with a github url, please use the checkout command instead: ph checkout --remote-drive <remote drive url>"
|
|
503
|
+
);
|
|
504
|
+
return false;
|
|
505
|
+
}
|
|
506
|
+
return true;
|
|
507
|
+
} catch (error) {
|
|
508
|
+
console.error("\u274C Unable to fetch remote drive info:", error);
|
|
509
|
+
return false;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// src/commands/forward.ts
|
|
514
|
+
var forwardCommand = async (args, options) => {
|
|
515
|
+
const argsList = args.split(" ");
|
|
516
|
+
const isHelpCommand = argsList.includes("help") || argsList.includes("--help") || argsList.includes("-h");
|
|
517
|
+
if (options.debug) {
|
|
518
|
+
console.log(">>> command arguments:", { options });
|
|
519
|
+
}
|
|
520
|
+
const projectInfo = await getProjectInfo(options.debug, !isHelpCommand);
|
|
521
|
+
if (options.debug) {
|
|
522
|
+
console.log("\n>>> projectInfo:", projectInfo);
|
|
523
|
+
}
|
|
524
|
+
const packageManager = getPackageManagerFromLockfile(projectInfo.path);
|
|
525
|
+
if (options.debug) {
|
|
526
|
+
console.log("\n>>> forwardCommand arguments:");
|
|
527
|
+
console.log(">>> packageManager:", packageManager);
|
|
528
|
+
console.log(">>> projectPath:", projectInfo.path);
|
|
529
|
+
console.log(">>> args:", args);
|
|
530
|
+
}
|
|
531
|
+
try {
|
|
532
|
+
if (isHelpCommand || options.logOutput) {
|
|
533
|
+
const helpOutput = forwardPHCommand(
|
|
534
|
+
packageManager,
|
|
535
|
+
projectInfo.path,
|
|
536
|
+
args,
|
|
537
|
+
options.debug,
|
|
538
|
+
true
|
|
539
|
+
);
|
|
540
|
+
console.log(helpOutput);
|
|
541
|
+
} else {
|
|
542
|
+
forwardPHCommand(packageManager, projectInfo.path, args, options.debug);
|
|
543
|
+
}
|
|
544
|
+
} catch (error) {
|
|
545
|
+
if (!args.length) {
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
if (error.code === "ENOENT") {
|
|
549
|
+
console.error("Have you run `ph setup-globals` or `ph init`?");
|
|
550
|
+
}
|
|
551
|
+
if (options.debug) {
|
|
552
|
+
console.error("\u274C Failed to forward command");
|
|
553
|
+
throw error;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
|
|
558
|
+
// src/commands/checkout.ts
|
|
559
|
+
import { cloneRepository, installDependencies } from "@powerhousedao/codegen";
|
|
560
|
+
|
|
561
|
+
// src/help.ts
|
|
562
|
+
var setupGlobalsHelp = `
|
|
563
|
+
Command Overview:
|
|
564
|
+
The setup-globals command initializes a new Powerhouse project with the necessary global
|
|
565
|
+
configuration. It helps you set up a project quickly with proper defaults and dependencies.
|
|
566
|
+
|
|
567
|
+
This command:
|
|
568
|
+
1. Creates a new project with the specified name or in the current directory
|
|
569
|
+
2. Sets up all required Powerhouse dependencies
|
|
570
|
+
3. Configures the project with appropriate settings
|
|
571
|
+
4. Can run in interactive mode to guide you through the setup process
|
|
572
|
+
|
|
573
|
+
Arguments:
|
|
574
|
+
[project-name] Optional. Name of the project to create. If not provided,
|
|
575
|
+
the command will use the current directory.
|
|
576
|
+
|
|
577
|
+
Options:
|
|
578
|
+
-p, --project Specify the name of the project to create.
|
|
579
|
+
|
|
580
|
+
-i, --interactive Run the command in interactive mode, which will guide you
|
|
581
|
+
through the setup process with questions and prompts.
|
|
582
|
+
|
|
583
|
+
-v, --version Specify the development version to use. Defaults to "main".
|
|
584
|
+
|
|
585
|
+
--dev Use the "development" version of the boilerplate.
|
|
586
|
+
|
|
587
|
+
--staging Use the "staging" version of the boilerplate.
|
|
588
|
+
|
|
589
|
+
--package-manager Override the auto-detected package manager with the specified one.
|
|
590
|
+
|
|
591
|
+
Project Structure:
|
|
592
|
+
The command will set up a project with the following structure:
|
|
593
|
+
- Proper configuration files for TypeScript and ESLint
|
|
594
|
+
- Dependencies for Powerhouse packages
|
|
595
|
+
- Build and development scripts
|
|
596
|
+
|
|
597
|
+
Examples:
|
|
598
|
+
$ ph setup-globals my-project # Create a new project named "my-project"
|
|
599
|
+
$ ph setup-globals # Set up a project in the current directory
|
|
600
|
+
$ ph setup-globals -i # Run setup in interactive mode
|
|
601
|
+
$ ph setup-globals --dev # Use development version
|
|
602
|
+
$ ph setup-globals -v beta # Use specific version
|
|
603
|
+
$ ph setup-globals --package-manager npm # Use npm as package manager
|
|
604
|
+
`;
|
|
605
|
+
var checkoutHelp = `
|
|
606
|
+
Command Overview:
|
|
607
|
+
The checkout command clones an existing Powerhouse project from a remote Vetra drive.
|
|
608
|
+
This allows you to work on projects that have been initialized and configured by others.
|
|
609
|
+
|
|
610
|
+
This command:
|
|
611
|
+
1. Fetches the GitHub repository URL from the specified Vetra remote drive
|
|
612
|
+
2. Clones the repository to your local machine
|
|
613
|
+
3. Installs all project dependencies
|
|
614
|
+
|
|
615
|
+
Required Options:
|
|
616
|
+
-r, --remote-drive <url> URL of the Vetra remote drive containing the project.
|
|
617
|
+
The drive must have a Vetra package with a configured GitHub URL.
|
|
618
|
+
|
|
619
|
+
Options:
|
|
620
|
+
--package-manager <pm> Specify which package manager to use for installing dependencies.
|
|
621
|
+
Supported: npm, yarn, pnpm, bun
|
|
622
|
+
If not specified, uses the detected package manager from your environment.
|
|
623
|
+
|
|
624
|
+
Examples:
|
|
625
|
+
$ ph checkout --remote-drive https://vetra.example.com/d/abc123 # Clone project using default package manager
|
|
626
|
+
$ ph checkout --remote-drive https://vetra.example.com/d/abc123 --package-manager pnpm # Clone and install with pnpm
|
|
627
|
+
|
|
628
|
+
Notes:
|
|
629
|
+
- The remote drive must contain a Vetra package document with a GitHub URL configured
|
|
630
|
+
- If no GitHub URL is found, you'll need to use 'ph init --remote-drive' instead to create a new project
|
|
631
|
+
- The repository will be cloned into a directory named after the repository
|
|
632
|
+
`;
|
|
633
|
+
|
|
634
|
+
// src/utils/validate-remote-drive-checkout.ts
|
|
635
|
+
import { getVetraDocuments as getVetraDocuments2 } from "@powerhousedao/common/utils";
|
|
636
|
+
async function getPackageDocument(remoteDriveUrl) {
|
|
637
|
+
try {
|
|
638
|
+
const driveId = remoteDriveUrl.split("/").pop();
|
|
639
|
+
const url = new URL(remoteDriveUrl);
|
|
640
|
+
const graphqlEndpoint = `${url.protocol}//${url.host}/graphql`;
|
|
641
|
+
if (!driveId) {
|
|
642
|
+
return {
|
|
643
|
+
isValid: false,
|
|
644
|
+
error: "\u274C Invalid remote drive URL: unable to extract drive ID"
|
|
645
|
+
};
|
|
646
|
+
}
|
|
647
|
+
const documents = await getVetraDocuments2(graphqlEndpoint, driveId);
|
|
648
|
+
if (documents.length === 0) {
|
|
649
|
+
return {
|
|
650
|
+
isValid: false,
|
|
651
|
+
error: "\u274C No Vetra package documents found in the remote drive. Use 'ph init --remote-drive' to create a new project first."
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
const documentsWithUrl = documents.filter((doc) => doc.githubUrl);
|
|
655
|
+
if (documentsWithUrl.length === 0) {
|
|
656
|
+
return {
|
|
657
|
+
isValid: false,
|
|
658
|
+
error: "\u274C No GitHub URL configured in the Vetra package. Use 'ph init --remote-drive' to create a new project first."
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
if (documents.length > 1) {
|
|
662
|
+
console.warn(
|
|
663
|
+
`\u26A0\uFE0F Warning: Multiple Vetra package documents found (${documents.length}). Using first document with GitHub URL.`
|
|
664
|
+
);
|
|
665
|
+
}
|
|
666
|
+
return {
|
|
667
|
+
isValid: true,
|
|
668
|
+
githubUrl: documentsWithUrl[0].githubUrl
|
|
669
|
+
};
|
|
670
|
+
} catch (error) {
|
|
671
|
+
return {
|
|
672
|
+
isValid: false,
|
|
673
|
+
error: `\u274C Unable to fetch remote drive info: ${error instanceof Error ? error.message : String(error)}`
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
// src/commands/checkout.ts
|
|
679
|
+
var checkout = async (options) => {
|
|
680
|
+
console.log("Checking out project from remote drive...");
|
|
681
|
+
try {
|
|
682
|
+
const packageDocument = await getPackageDocument(options.remoteDrive);
|
|
683
|
+
if (!packageDocument.isValid) {
|
|
684
|
+
console.error(packageDocument.error);
|
|
685
|
+
process.exit(1);
|
|
686
|
+
}
|
|
687
|
+
const projectPath = cloneRepository(packageDocument.githubUrl);
|
|
688
|
+
const detectedPackageManager = getPackageManagerFromLockfile(projectPath);
|
|
689
|
+
const packageManager = options.packageManager ?? detectedPackageManager;
|
|
690
|
+
installDependencies(projectPath, packageManager);
|
|
691
|
+
console.log("\x1B[32m", "Checkout completed successfully!", "\x1B[0m");
|
|
692
|
+
} catch (error) {
|
|
693
|
+
console.error(
|
|
694
|
+
"Failed to checkout the project",
|
|
695
|
+
error instanceof Error ? error.message : String(error)
|
|
696
|
+
);
|
|
697
|
+
process.exit(1);
|
|
698
|
+
}
|
|
699
|
+
};
|
|
700
|
+
function checkoutCommand(program2) {
|
|
701
|
+
const checkoutCmd = program2.command("checkout").description("Checkout an existing project from a remote drive").requiredOption(
|
|
702
|
+
"-r, --remote-drive <remoteDrive>",
|
|
703
|
+
"Remote drive identifier"
|
|
704
|
+
).option("--package-manager <packageManager>", "Package manager to use");
|
|
705
|
+
return withCustomHelp(checkoutCmd, checkout, checkoutHelp);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
// src/commands/help.ts
|
|
709
|
+
function helpCommand(program2) {
|
|
710
|
+
program2.command("help").description("Display help information").action(async () => {
|
|
711
|
+
await generateMergedHelp(program2);
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
// src/commands/setup-globals.ts
|
|
716
|
+
var setupGlobals = async (projectName, options) => {
|
|
717
|
+
await createGlobalProject(projectName, options);
|
|
718
|
+
};
|
|
719
|
+
function setupGlobalsCommand(program2) {
|
|
720
|
+
const setupGlobalsCmd = program2.command("setup-globals").description("Initialize a new global project").argument("[project-name]", "Name of the project").option("-p, --project", "Name of the project").option("-i, --interactive", "Run the command in interactive mode").option(
|
|
721
|
+
"-t, --tag",
|
|
722
|
+
'Specify development version to use. Defaults to "main"'
|
|
723
|
+
).option("--dev", 'Use "development" version of the boilerplate').option("--staging", 'Use "development" version of the boilerplate').option("--package-manager <packageManager>", "package manager to be used").option("--npm", "Use 'npm' as package manager").option("--pnpm", "Use 'pnpm' as package manager").option("--yarn", "Use 'yarn' as package manager").option("--bun", "Use 'bun' as package manager");
|
|
724
|
+
return withCustomHelp(
|
|
725
|
+
setupGlobalsCmd,
|
|
726
|
+
setupGlobals,
|
|
727
|
+
setupGlobalsHelp
|
|
728
|
+
);
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
// src/commands/version.ts
|
|
732
|
+
import fs from "fs";
|
|
733
|
+
import path4 from "path";
|
|
734
|
+
var customVersionHandler = async () => {
|
|
735
|
+
const projectInfo = await getProjectInfo(void 0, false);
|
|
736
|
+
const { version } = await import("./version-RL3XZD32.js");
|
|
737
|
+
console.log("PH CMD version: ", version);
|
|
738
|
+
if (projectInfo.available) {
|
|
739
|
+
const packageManager = getPackageManagerFromLockfile(projectInfo.path);
|
|
740
|
+
try {
|
|
741
|
+
const packageJsonPath = path4.join(projectInfo.path, "package.json");
|
|
742
|
+
const packageJsonContent = fs.readFileSync(packageJsonPath, "utf-8");
|
|
743
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
744
|
+
const phCliVersion = packageJson.dependencies?.["@powerhousedao/ph-cli"] || packageJson.devDependencies?.["@powerhousedao/ph-cli"];
|
|
745
|
+
if (phCliVersion) {
|
|
746
|
+
console.log("PH CLI version: ", phCliVersion);
|
|
747
|
+
}
|
|
748
|
+
} catch (err) {
|
|
749
|
+
console.log(
|
|
750
|
+
"Error reading PH CLI version from package.json:",
|
|
751
|
+
err.message
|
|
752
|
+
);
|
|
753
|
+
}
|
|
754
|
+
console.log("-------------------------------------");
|
|
755
|
+
console.log("PH CLI path: ", projectInfo.path);
|
|
756
|
+
console.log("PH CLI isGlobalProject: ", projectInfo.isGlobal);
|
|
757
|
+
console.log("PH CLI packageManager: ", packageManager);
|
|
758
|
+
} else {
|
|
759
|
+
console.log("-------------------------------------");
|
|
760
|
+
console.log(
|
|
761
|
+
"PH CLI is not available, please run `ph setup-globals` to generate the default global project"
|
|
762
|
+
);
|
|
763
|
+
}
|
|
764
|
+
};
|
|
765
|
+
function versionOption(program2) {
|
|
766
|
+
return program2.option(
|
|
767
|
+
"-v, --version",
|
|
768
|
+
"Display version information",
|
|
769
|
+
customVersionHandler
|
|
770
|
+
);
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
// src/commands/index.ts
|
|
774
|
+
var commands = [
|
|
775
|
+
setupGlobalsCommand,
|
|
776
|
+
checkoutCommand,
|
|
777
|
+
helpCommand,
|
|
778
|
+
versionOption
|
|
779
|
+
];
|
|
780
|
+
function registerCommands(program2) {
|
|
781
|
+
commands.forEach((command5) => command5(program2));
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
// src/commands/init.ts
|
|
785
|
+
import { createProject as createProject2 } from "@powerhousedao/codegen";
|
|
786
|
+
import chalk2 from "chalk";
|
|
787
|
+
import { kebabCase } from "change-case";
|
|
788
|
+
import {
|
|
789
|
+
boolean,
|
|
790
|
+
command,
|
|
791
|
+
flag,
|
|
792
|
+
oneOf,
|
|
793
|
+
option,
|
|
794
|
+
optional,
|
|
795
|
+
positional,
|
|
796
|
+
run,
|
|
797
|
+
string
|
|
798
|
+
} from "cmd-ts";
|
|
799
|
+
import enquirer from "enquirer";
|
|
800
|
+
import { clean, valid } from "semver";
|
|
801
|
+
var commandParser = command({
|
|
802
|
+
name: "ph init",
|
|
803
|
+
description: "Initialize a new project",
|
|
804
|
+
args: {
|
|
805
|
+
namePositional: positional({
|
|
806
|
+
type: optional(string),
|
|
807
|
+
displayName: "name",
|
|
808
|
+
description: "The name of your project. A new directory will be created in your current directory with this name."
|
|
809
|
+
}),
|
|
810
|
+
nameOption: option({
|
|
811
|
+
type: optional(string),
|
|
812
|
+
long: "name",
|
|
813
|
+
short: "n",
|
|
814
|
+
description: "The name of your project. A new directory will be created in your current directory with this name."
|
|
815
|
+
}),
|
|
816
|
+
packageManager: option({
|
|
817
|
+
type: optional(oneOf(["npm", "pnpm", "yarn", "bun"])),
|
|
818
|
+
long: "package-manager",
|
|
819
|
+
short: "p",
|
|
820
|
+
description: "Specify the package manager to use for your project. Can be one of: `npm`, `pnpm`, `yarn`, or `bun`. Defaults to your environment package manager."
|
|
821
|
+
}),
|
|
822
|
+
npm: flag({
|
|
823
|
+
type: optional(boolean),
|
|
824
|
+
long: "npm",
|
|
825
|
+
description: "Use 'npm' as package manager"
|
|
826
|
+
}),
|
|
827
|
+
pnpm: flag({
|
|
828
|
+
type: optional(boolean),
|
|
829
|
+
long: "pnpm",
|
|
830
|
+
description: "Use 'pnpm' as package manager"
|
|
831
|
+
}),
|
|
832
|
+
yarn: flag({
|
|
833
|
+
type: optional(boolean),
|
|
834
|
+
long: "yarn",
|
|
835
|
+
description: "Use 'yarn' as package manager"
|
|
836
|
+
}),
|
|
837
|
+
bun: flag({
|
|
838
|
+
type: optional(boolean),
|
|
839
|
+
long: "bun",
|
|
840
|
+
description: "Use 'bun' as package manager"
|
|
841
|
+
}),
|
|
842
|
+
tag: option({
|
|
843
|
+
type: optional(oneOf(["latest", "staging", "dev"])),
|
|
844
|
+
long: "tag",
|
|
845
|
+
short: "t",
|
|
846
|
+
description: `Specify the release tag to use for your project. Can be one of: "latest", "staging", or "dev".`
|
|
847
|
+
}),
|
|
848
|
+
version: option({
|
|
849
|
+
type: optional(string),
|
|
850
|
+
long: "version",
|
|
851
|
+
short: "v",
|
|
852
|
+
description: "Specify the exact semver release version to use for your project."
|
|
853
|
+
}),
|
|
854
|
+
dev: flag({
|
|
855
|
+
type: optional(boolean),
|
|
856
|
+
long: "dev",
|
|
857
|
+
short: "d",
|
|
858
|
+
description: "Use the `dev` release tag."
|
|
859
|
+
}),
|
|
860
|
+
staging: flag({
|
|
861
|
+
type: optional(boolean),
|
|
862
|
+
long: "staging",
|
|
863
|
+
short: "s",
|
|
864
|
+
description: "Use the `staging` release tag."
|
|
865
|
+
}),
|
|
866
|
+
remoteDrive: option({
|
|
867
|
+
type: optional(string),
|
|
868
|
+
long: "remote-drive",
|
|
869
|
+
short: "r",
|
|
870
|
+
description: "Remote drive identifier."
|
|
871
|
+
})
|
|
872
|
+
},
|
|
873
|
+
handler: async ({
|
|
874
|
+
namePositional,
|
|
875
|
+
nameOption,
|
|
876
|
+
packageManager,
|
|
877
|
+
npm,
|
|
878
|
+
pnpm,
|
|
879
|
+
yarn,
|
|
880
|
+
bun,
|
|
881
|
+
tag,
|
|
882
|
+
version,
|
|
883
|
+
dev,
|
|
884
|
+
staging,
|
|
885
|
+
remoteDrive
|
|
886
|
+
}) => {
|
|
887
|
+
let name = namePositional ?? nameOption;
|
|
888
|
+
if (!name) {
|
|
889
|
+
const { prompt } = enquirer;
|
|
890
|
+
const result = await prompt([
|
|
891
|
+
{
|
|
892
|
+
type: "input",
|
|
893
|
+
name: "name",
|
|
894
|
+
message: "What is the project name?",
|
|
895
|
+
required: true,
|
|
896
|
+
result: (value) => kebabCase(value)
|
|
897
|
+
}
|
|
898
|
+
]);
|
|
899
|
+
name = result.name;
|
|
900
|
+
}
|
|
901
|
+
if (!name) {
|
|
902
|
+
throw new Error("You must provide a name for your project.");
|
|
903
|
+
}
|
|
904
|
+
if (version !== void 0 && !valid(clean(version))) {
|
|
905
|
+
throw new Error(`Invalid version: ${version}`);
|
|
906
|
+
}
|
|
907
|
+
handleMutuallyExclusiveOptions(
|
|
908
|
+
{
|
|
909
|
+
tag,
|
|
910
|
+
version,
|
|
911
|
+
dev,
|
|
912
|
+
staging
|
|
913
|
+
},
|
|
914
|
+
"versioning strategy"
|
|
915
|
+
);
|
|
916
|
+
handleMutuallyExclusiveOptions(
|
|
917
|
+
{
|
|
918
|
+
npm,
|
|
919
|
+
pnpm,
|
|
920
|
+
yarn,
|
|
921
|
+
bun,
|
|
922
|
+
packageManager
|
|
923
|
+
},
|
|
924
|
+
"package manager"
|
|
925
|
+
);
|
|
926
|
+
const parsedPackageManager = parsePackageManager({
|
|
927
|
+
npm,
|
|
928
|
+
pnpm,
|
|
929
|
+
yarn,
|
|
930
|
+
bun,
|
|
931
|
+
packageManager
|
|
932
|
+
}) ?? "npm";
|
|
933
|
+
const parsedTag = parseTag({
|
|
934
|
+
tag,
|
|
935
|
+
dev,
|
|
936
|
+
staging
|
|
937
|
+
});
|
|
938
|
+
return {
|
|
939
|
+
name,
|
|
940
|
+
version,
|
|
941
|
+
remoteDrive,
|
|
942
|
+
packageManager: parsedPackageManager,
|
|
943
|
+
tag: parsedTag
|
|
944
|
+
};
|
|
945
|
+
}
|
|
946
|
+
});
|
|
947
|
+
async function init(args) {
|
|
948
|
+
try {
|
|
949
|
+
const parsedArgs = await run(commandParser, args);
|
|
950
|
+
const { name, remoteDrive } = parsedArgs;
|
|
951
|
+
if (remoteDrive) {
|
|
952
|
+
console.log(chalk2.blue("\n\u23F3 Setting up remote drive...\n"));
|
|
953
|
+
await setupRemoteDrive(remoteDrive);
|
|
954
|
+
console.log(chalk2.green("\n\u2705 Remote drive set up."));
|
|
955
|
+
}
|
|
956
|
+
console.log(chalk2.bold("\n\u{1F680} Initializing a new project...\n"));
|
|
957
|
+
await createProject2(parsedArgs);
|
|
958
|
+
if (remoteDrive) {
|
|
959
|
+
console.log();
|
|
960
|
+
console.log("To link your project to GitHub:");
|
|
961
|
+
console.log();
|
|
962
|
+
console.log(" 1. Create a new repository on GitHub");
|
|
963
|
+
console.log(` 2. cd ${name}`);
|
|
964
|
+
console.log(" 3. git add . && git commit -m 'Initial commit'");
|
|
965
|
+
console.log(" 4. git remote add origin <your-github-url>");
|
|
966
|
+
console.log(` 5. git push -u origin main`);
|
|
967
|
+
console.log();
|
|
968
|
+
}
|
|
969
|
+
} catch (error) {
|
|
970
|
+
console.error("\n\u274C Failed to initialize project: \n");
|
|
971
|
+
console.error(error);
|
|
972
|
+
process.exit(1);
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
// src/commands/update.ts
|
|
977
|
+
import { getPackageVersion } from "@powerhousedao/codegen/utils";
|
|
978
|
+
import chalk3 from "chalk";
|
|
979
|
+
import { boolean as boolean2, command as command2, flag as flag2, optional as optional2, run as run2 } from "cmd-ts";
|
|
980
|
+
import { detect } from "package-manager-detector/detect";
|
|
981
|
+
import { readPackage } from "read-pkg";
|
|
982
|
+
import { writePackage } from "write-package";
|
|
983
|
+
|
|
984
|
+
// src/utils/run-cmd.ts
|
|
985
|
+
import { execSync as execSync3 } from "child_process";
|
|
986
|
+
function runCmd(command5) {
|
|
987
|
+
try {
|
|
988
|
+
execSync3(command5, { stdio: "inherit" });
|
|
989
|
+
} catch (error) {
|
|
990
|
+
console.log("\x1B[31m", error, "\x1B[0m");
|
|
991
|
+
throw error;
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
// src/commands/update.ts
|
|
996
|
+
var commandParser2 = command2({
|
|
997
|
+
name: "ph update",
|
|
998
|
+
description: "Update your powerhouse dependencies to their latest tagged version",
|
|
999
|
+
args: {
|
|
1000
|
+
skipInstall: flag2({
|
|
1001
|
+
type: optional2(boolean2),
|
|
1002
|
+
long: "skip-install",
|
|
1003
|
+
short: "s",
|
|
1004
|
+
description: "Skip running `install` with your package manager"
|
|
1005
|
+
})
|
|
1006
|
+
},
|
|
1007
|
+
handler: async ({ skipInstall }) => {
|
|
1008
|
+
console.log(`
|
|
1009
|
+
\u25B6\uFE0F Updating Powerhouse dependencies...
|
|
1010
|
+
`);
|
|
1011
|
+
const packageJson = await readPackage();
|
|
1012
|
+
if (packageJson.dependencies) {
|
|
1013
|
+
for (const [name, version] of Object.entries(packageJson.dependencies)) {
|
|
1014
|
+
if (version && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {
|
|
1015
|
+
const tag = getTagFromVersion(version);
|
|
1016
|
+
const newVersion = await getPackageVersion({ name, tag });
|
|
1017
|
+
packageJson.dependencies[name] = newVersion;
|
|
1018
|
+
logVersionUpdate({
|
|
1019
|
+
name,
|
|
1020
|
+
version,
|
|
1021
|
+
newVersion
|
|
1022
|
+
});
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
if (packageJson.devDependencies) {
|
|
1027
|
+
for (const [name, version] of Object.entries(
|
|
1028
|
+
packageJson.devDependencies
|
|
1029
|
+
)) {
|
|
1030
|
+
if (version && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {
|
|
1031
|
+
const tag = getTagFromVersion(version);
|
|
1032
|
+
const newVersion = await getPackageVersion({ name, tag });
|
|
1033
|
+
packageJson.devDependencies[name] = newVersion;
|
|
1034
|
+
logVersionUpdate({
|
|
1035
|
+
name,
|
|
1036
|
+
version,
|
|
1037
|
+
newVersion
|
|
1038
|
+
});
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
if (packageJson.optionalDependencies) {
|
|
1043
|
+
for (const [name, version] of Object.entries(
|
|
1044
|
+
packageJson.optionalDependencies
|
|
1045
|
+
)) {
|
|
1046
|
+
if (version && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {
|
|
1047
|
+
const tag = getTagFromVersion(version);
|
|
1048
|
+
const newVersion = await getPackageVersion({ name, tag });
|
|
1049
|
+
packageJson.optionalDependencies[name] = newVersion;
|
|
1050
|
+
logVersionUpdate({
|
|
1051
|
+
name,
|
|
1052
|
+
version,
|
|
1053
|
+
newVersion
|
|
1054
|
+
});
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
if (packageJson.peerDependencies) {
|
|
1059
|
+
for (const [name, version] of Object.entries(
|
|
1060
|
+
packageJson.peerDependencies
|
|
1061
|
+
)) {
|
|
1062
|
+
if (version && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {
|
|
1063
|
+
const tag = getTagFromVersion(version);
|
|
1064
|
+
const newVersion = await getPackageVersion({ name, tag });
|
|
1065
|
+
packageJson.peerDependencies[name] = newVersion;
|
|
1066
|
+
logVersionUpdate({
|
|
1067
|
+
name,
|
|
1068
|
+
version,
|
|
1069
|
+
newVersion
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
await writePackage(packageJson);
|
|
1075
|
+
console.log(chalk3.green(`
|
|
1076
|
+
\u2705 Project updated successfully
|
|
1077
|
+
`));
|
|
1078
|
+
if (skipInstall) return;
|
|
1079
|
+
const packageManager = await detect();
|
|
1080
|
+
if (!packageManager) {
|
|
1081
|
+
throw new Error(
|
|
1082
|
+
`\u274C Failed to detect your package manager. Run install manually.`
|
|
1083
|
+
);
|
|
1084
|
+
}
|
|
1085
|
+
console.log(
|
|
1086
|
+
`\u25B6\uFE0F Installing updated dependencies with \`${packageManager.agent}\`
|
|
1087
|
+
`
|
|
1088
|
+
);
|
|
1089
|
+
runCmd(`${packageManager.agent} install`);
|
|
1090
|
+
}
|
|
1091
|
+
});
|
|
1092
|
+
async function update(args) {
|
|
1093
|
+
await run2(commandParser2, args);
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
// src/commands/use-local.ts
|
|
1097
|
+
import chalk4 from "chalk";
|
|
1098
|
+
import {
|
|
1099
|
+
boolean as boolean3,
|
|
1100
|
+
command as command3,
|
|
1101
|
+
flag as flag3,
|
|
1102
|
+
option as option2,
|
|
1103
|
+
optional as optional3,
|
|
1104
|
+
positional as positional2,
|
|
1105
|
+
run as run3,
|
|
1106
|
+
string as string2
|
|
1107
|
+
} from "cmd-ts";
|
|
1108
|
+
import path5 from "path";
|
|
1109
|
+
import { readPackage as readPackage2 } from "read-pkg";
|
|
1110
|
+
import { writePackage as writePackage2 } from "write-package";
|
|
1111
|
+
|
|
1112
|
+
// src/utils/file-system.ts
|
|
1113
|
+
import { constants } from "fs";
|
|
1114
|
+
import { access } from "fs/promises";
|
|
1115
|
+
async function dirExists(path6) {
|
|
1116
|
+
try {
|
|
1117
|
+
await access(path6, constants.F_OK);
|
|
1118
|
+
return true;
|
|
1119
|
+
} catch {
|
|
1120
|
+
return false;
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
// src/commands/use-local.ts
|
|
1125
|
+
var commandParser3 = command3({
|
|
1126
|
+
name: "ph use-local",
|
|
1127
|
+
description: "Use your local `powerhouse` monorepo dependencies the current project. NOTE: The monorepo uses `pnpm`, so this only works with `pnpm`.",
|
|
1128
|
+
args: {
|
|
1129
|
+
monorepoPathPositional: positional2({
|
|
1130
|
+
type: optional3(string2),
|
|
1131
|
+
displayName: "monorepo path",
|
|
1132
|
+
description: "Path to your local powerhouse monorepo relative to this project"
|
|
1133
|
+
}),
|
|
1134
|
+
monorepoPathOption: option2({
|
|
1135
|
+
type: optional3(string2),
|
|
1136
|
+
long: "path",
|
|
1137
|
+
short: "p",
|
|
1138
|
+
description: "Path to your local powerhouse monorepo relative to this project"
|
|
1139
|
+
}),
|
|
1140
|
+
skipInstall: flag3({
|
|
1141
|
+
type: optional3(boolean3),
|
|
1142
|
+
long: "skip-install",
|
|
1143
|
+
short: "s",
|
|
1144
|
+
description: "Skip running `install` with `pnpm`"
|
|
1145
|
+
})
|
|
1146
|
+
},
|
|
1147
|
+
handler: async ({
|
|
1148
|
+
monorepoPathPositional,
|
|
1149
|
+
monorepoPathOption,
|
|
1150
|
+
skipInstall
|
|
1151
|
+
}) => {
|
|
1152
|
+
const monorepoPath = monorepoPathPositional ?? monorepoPathOption;
|
|
1153
|
+
if (!monorepoPath) {
|
|
1154
|
+
throw new Error(
|
|
1155
|
+
"\u274C Please provide the path to your local powerhouse monorepo."
|
|
1156
|
+
);
|
|
1157
|
+
}
|
|
1158
|
+
const monorepoDirExists = await dirExists(monorepoPath);
|
|
1159
|
+
if (!monorepoDirExists) {
|
|
1160
|
+
throw new Error(
|
|
1161
|
+
"\u274C No directory found at the powerhouse monorepo path you specified."
|
|
1162
|
+
);
|
|
1163
|
+
}
|
|
1164
|
+
console.log(
|
|
1165
|
+
`
|
|
1166
|
+
\u25B6\uFE0F Linking powerhouse dependencies to "${chalk4.bold(monorepoPath)}...
|
|
1167
|
+
`
|
|
1168
|
+
);
|
|
1169
|
+
const packageJson = await readPackage2();
|
|
1170
|
+
if (packageJson.dependencies) {
|
|
1171
|
+
for (const [name, version] of Object.entries(packageJson.dependencies)) {
|
|
1172
|
+
if (version && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {
|
|
1173
|
+
const newVersion = buildPnpmLink(name, monorepoPath);
|
|
1174
|
+
packageJson.dependencies[name] = newVersion;
|
|
1175
|
+
logVersionUpdate({
|
|
1176
|
+
name,
|
|
1177
|
+
version,
|
|
1178
|
+
newVersion
|
|
1179
|
+
});
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
if (packageJson.devDependencies) {
|
|
1184
|
+
for (const [name, version] of Object.entries(
|
|
1185
|
+
packageJson.devDependencies
|
|
1186
|
+
)) {
|
|
1187
|
+
if (version && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {
|
|
1188
|
+
const newVersion = buildPnpmLink(name, monorepoPath);
|
|
1189
|
+
packageJson.devDependencies[name] = newVersion;
|
|
1190
|
+
logVersionUpdate({
|
|
1191
|
+
name,
|
|
1192
|
+
version,
|
|
1193
|
+
newVersion
|
|
1194
|
+
});
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
if (packageJson.optionalDependencies) {
|
|
1199
|
+
for (const [name, version] of Object.entries(
|
|
1200
|
+
packageJson.optionalDependencies
|
|
1201
|
+
)) {
|
|
1202
|
+
if (version && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {
|
|
1203
|
+
const newVersion = buildPnpmLink(name, monorepoPath);
|
|
1204
|
+
packageJson.optionalDependencies[name] = newVersion;
|
|
1205
|
+
logVersionUpdate({
|
|
1206
|
+
name,
|
|
1207
|
+
version,
|
|
1208
|
+
newVersion
|
|
1209
|
+
});
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
if (packageJson.peerDependencies) {
|
|
1214
|
+
for (const [name, version] of Object.entries(
|
|
1215
|
+
packageJson.peerDependencies
|
|
1216
|
+
)) {
|
|
1217
|
+
if (version && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {
|
|
1218
|
+
const newVersion = buildPnpmLink(name, monorepoPath);
|
|
1219
|
+
packageJson.peerDependencies[name] = newVersion;
|
|
1220
|
+
logVersionUpdate({
|
|
1221
|
+
name,
|
|
1222
|
+
version,
|
|
1223
|
+
newVersion
|
|
1224
|
+
});
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
await writePackage2(packageJson);
|
|
1229
|
+
console.log(chalk4.green(`
|
|
1230
|
+
\u2705 Project linked successfully
|
|
1231
|
+
`));
|
|
1232
|
+
if (skipInstall) return;
|
|
1233
|
+
console.log(`Installing linked dependencies with \`pnpm\`
|
|
1234
|
+
`);
|
|
1235
|
+
runCmd(`pnpm install`);
|
|
1236
|
+
}
|
|
1237
|
+
});
|
|
1238
|
+
function buildPnpmLink(packageName, monorepoPath) {
|
|
1239
|
+
const isCli = CLIS_DEPENDENCIES.includes(packageName);
|
|
1240
|
+
const isApp = APPS_DEPENDENCIES.includes(packageName);
|
|
1241
|
+
const packageDir = isCli ? "clis" : isApp ? "apps" : "packages";
|
|
1242
|
+
const packageNameWithoutNamespace = packageName.replace(
|
|
1243
|
+
"@powerhousedao/",
|
|
1244
|
+
""
|
|
1245
|
+
);
|
|
1246
|
+
const packagePath = path5.join(
|
|
1247
|
+
monorepoPath,
|
|
1248
|
+
packageDir,
|
|
1249
|
+
packageNameWithoutNamespace
|
|
1250
|
+
);
|
|
1251
|
+
const pnpmLink = `link:${packagePath}`;
|
|
1252
|
+
return pnpmLink;
|
|
1253
|
+
}
|
|
1254
|
+
async function useLocal(args) {
|
|
1255
|
+
await run3(commandParser3, args);
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
// src/commands/use.ts
|
|
1259
|
+
import { getPackageVersion as getPackageVersion2 } from "@powerhousedao/codegen/utils";
|
|
1260
|
+
import chalk5 from "chalk";
|
|
1261
|
+
import {
|
|
1262
|
+
boolean as boolean4,
|
|
1263
|
+
command as command4,
|
|
1264
|
+
flag as flag4,
|
|
1265
|
+
oneOf as oneOf2,
|
|
1266
|
+
option as option3,
|
|
1267
|
+
optional as optional4,
|
|
1268
|
+
positional as positional3,
|
|
1269
|
+
run as run4,
|
|
1270
|
+
string as string3
|
|
1271
|
+
} from "cmd-ts";
|
|
1272
|
+
import { detect as detect2 } from "package-manager-detector/detect";
|
|
1273
|
+
import { readPackage as readPackage3 } from "read-pkg";
|
|
1274
|
+
import { clean as clean2, valid as valid2 } from "semver";
|
|
1275
|
+
import { writePackage as writePackage3 } from "write-package";
|
|
1276
|
+
var commandParser4 = command4({
|
|
1277
|
+
name: "ph use",
|
|
1278
|
+
description: "Specify the release version of Powerhouse dependencies to use.\nTo use a release tag, specify `staging`, `dev`, or `latest` as the first argument to this command or with the --tag option.\n You can also use a specific version with the --version option.",
|
|
1279
|
+
args: {
|
|
1280
|
+
tagPositional: positional3({
|
|
1281
|
+
type: optional4(oneOf2(["latest", "staging", "dev"])),
|
|
1282
|
+
displayName: "tag",
|
|
1283
|
+
description: `Specify the release tag to use for your project. Can be one of: "latest", "staging", or "dev".`
|
|
1284
|
+
}),
|
|
1285
|
+
tagOption: option3({
|
|
1286
|
+
type: optional4(oneOf2(["latest", "staging", "dev"])),
|
|
1287
|
+
long: "tag",
|
|
1288
|
+
short: "t",
|
|
1289
|
+
description: `Specify the release tag to use for your project. Can be one of: "latest", "staging", or "dev".`
|
|
1290
|
+
}),
|
|
1291
|
+
version: option3({
|
|
1292
|
+
type: optional4(string3),
|
|
1293
|
+
long: "version",
|
|
1294
|
+
short: "v",
|
|
1295
|
+
description: "Specify the exact semver release version to use for your project."
|
|
1296
|
+
}),
|
|
1297
|
+
skipInstall: flag4({
|
|
1298
|
+
type: optional4(boolean4),
|
|
1299
|
+
long: "skip-install",
|
|
1300
|
+
short: "s",
|
|
1301
|
+
description: "Skip running `install` with your package manager"
|
|
1302
|
+
})
|
|
1303
|
+
},
|
|
1304
|
+
handler: async ({ tagPositional, tagOption, version, skipInstall }) => {
|
|
1305
|
+
const tag = tagPositional ?? tagOption;
|
|
1306
|
+
handleMutuallyExclusiveOptions({ tag, version }, "versioning strategy");
|
|
1307
|
+
if (!tag && !version) {
|
|
1308
|
+
throw new Error(
|
|
1309
|
+
"Please specify either a release tag or a version to use."
|
|
1310
|
+
);
|
|
1311
|
+
}
|
|
1312
|
+
if (version && !valid2(clean2(version))) {
|
|
1313
|
+
throw new Error(`\u274C Invalid version: ${chalk5.bold(version)}`);
|
|
1314
|
+
}
|
|
1315
|
+
console.log(
|
|
1316
|
+
`\u25B6\uFE0F Updating project to use ${chalk5.bold(version ?? tag)}...
|
|
1317
|
+
`
|
|
1318
|
+
);
|
|
1319
|
+
const packageJson = await readPackage3();
|
|
1320
|
+
if (packageJson.dependencies) {
|
|
1321
|
+
for (const [name, existingVersion] of Object.entries(
|
|
1322
|
+
packageJson.dependencies
|
|
1323
|
+
)) {
|
|
1324
|
+
if (existingVersion && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {
|
|
1325
|
+
const newVersion = await getPackageVersion2({ name, tag, version });
|
|
1326
|
+
packageJson.dependencies[name] = newVersion;
|
|
1327
|
+
logVersionUpdate({
|
|
1328
|
+
name,
|
|
1329
|
+
version: existingVersion,
|
|
1330
|
+
newVersion
|
|
1331
|
+
});
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
if (packageJson.devDependencies) {
|
|
1336
|
+
for (const [name, existingVersion] of Object.entries(
|
|
1337
|
+
packageJson.devDependencies
|
|
1338
|
+
)) {
|
|
1339
|
+
if (existingVersion && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {
|
|
1340
|
+
const newVersion = await getPackageVersion2({ name, tag, version });
|
|
1341
|
+
packageJson.devDependencies[name] = newVersion;
|
|
1342
|
+
logVersionUpdate({
|
|
1343
|
+
name,
|
|
1344
|
+
version: existingVersion,
|
|
1345
|
+
newVersion
|
|
1346
|
+
});
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
if (packageJson.optionalDependencies) {
|
|
1351
|
+
for (const [name, existingVersion] of Object.entries(
|
|
1352
|
+
packageJson.optionalDependencies
|
|
1353
|
+
)) {
|
|
1354
|
+
if (existingVersion && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {
|
|
1355
|
+
const newVersion = await getPackageVersion2({ name, tag, version });
|
|
1356
|
+
packageJson.optionalDependencies[name] = newVersion;
|
|
1357
|
+
logVersionUpdate({
|
|
1358
|
+
name,
|
|
1359
|
+
version: existingVersion,
|
|
1360
|
+
newVersion
|
|
1361
|
+
});
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
if (packageJson.peerDependencies) {
|
|
1366
|
+
for (const [name, existingVersion] of Object.entries(
|
|
1367
|
+
packageJson.peerDependencies
|
|
1368
|
+
)) {
|
|
1369
|
+
if (existingVersion && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {
|
|
1370
|
+
const newVersion = await getPackageVersion2({ name, tag, version });
|
|
1371
|
+
packageJson.peerDependencies[name] = newVersion;
|
|
1372
|
+
logVersionUpdate({
|
|
1373
|
+
name,
|
|
1374
|
+
version: existingVersion,
|
|
1375
|
+
newVersion
|
|
1376
|
+
});
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
await writePackage3(packageJson);
|
|
1381
|
+
console.log(
|
|
1382
|
+
chalk5.green(
|
|
1383
|
+
`
|
|
1384
|
+
\u2705 Project updated to use ${chalk5.bold(version ?? tag)}
|
|
1385
|
+
`
|
|
1386
|
+
)
|
|
1387
|
+
);
|
|
1388
|
+
if (skipInstall) return;
|
|
1389
|
+
const packageManager = await detect2();
|
|
1390
|
+
if (!packageManager) {
|
|
1391
|
+
throw new Error(
|
|
1392
|
+
`\u274C Failed to detect your package manager. Run install manually.`
|
|
1393
|
+
);
|
|
1394
|
+
}
|
|
1395
|
+
console.log(
|
|
1396
|
+
`\u25B6\uFE0F Installing updated dependencies with \`${packageManager.agent}\`
|
|
1397
|
+
`
|
|
1398
|
+
);
|
|
1399
|
+
runCmd(`${packageManager.agent} install`);
|
|
1400
|
+
}
|
|
1401
|
+
});
|
|
1402
|
+
async function use(args) {
|
|
1403
|
+
await run4(commandParser4, args);
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
// src/cli.ts
|
|
1407
|
+
function ensureNodeVersion(minVersion = "22") {
|
|
1408
|
+
const version = process.versions.node;
|
|
1409
|
+
if (!version) {
|
|
1410
|
+
return;
|
|
1411
|
+
}
|
|
1412
|
+
if (version < minVersion) {
|
|
1413
|
+
console.error(
|
|
1414
|
+
`Node version ${minVersion} or higher is required. Current version: ${version}`
|
|
1415
|
+
);
|
|
1416
|
+
process.exit(1);
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
ensureNodeVersion("22");
|
|
1420
|
+
var program = new Command();
|
|
1421
|
+
var helpShown = false;
|
|
1422
|
+
async function customHelpHandler() {
|
|
1423
|
+
if (helpShown) return;
|
|
1424
|
+
helpShown = true;
|
|
1425
|
+
await generateMergedHelp(program);
|
|
1426
|
+
process.exit(0);
|
|
1427
|
+
}
|
|
1428
|
+
var defaultCommand = async (options) => {
|
|
1429
|
+
const allArgs = process.argv.slice(2);
|
|
1430
|
+
const args = allArgs.join(" ");
|
|
1431
|
+
const firstPositionalArg = allArgs[0];
|
|
1432
|
+
const isInit = firstPositionalArg === "init";
|
|
1433
|
+
if (isInit) {
|
|
1434
|
+
await init(process.argv.slice(3));
|
|
1435
|
+
process.exit(0);
|
|
1436
|
+
}
|
|
1437
|
+
const isUpdate = firstPositionalArg === "update";
|
|
1438
|
+
if (isUpdate) {
|
|
1439
|
+
await update(process.argv.slice(3));
|
|
1440
|
+
process.exit(0);
|
|
1441
|
+
}
|
|
1442
|
+
const isUse = firstPositionalArg === "use";
|
|
1443
|
+
if (isUse) {
|
|
1444
|
+
await use(process.argv.slice(3));
|
|
1445
|
+
process.exit(0);
|
|
1446
|
+
}
|
|
1447
|
+
const isUseLocal = firstPositionalArg === "use-local";
|
|
1448
|
+
if (isUseLocal) {
|
|
1449
|
+
await useLocal(process.argv.slice(3));
|
|
1450
|
+
process.exit(0);
|
|
1451
|
+
}
|
|
1452
|
+
const isHelpCommand = args.startsWith("--help") || args.startsWith("-h");
|
|
1453
|
+
const isVersionCommand = args.startsWith("--version") || args.startsWith("-v") || args.startsWith("version");
|
|
1454
|
+
if (!args.length) {
|
|
1455
|
+
program.parse(process.argv.concat("--help"));
|
|
1456
|
+
process.exit(0);
|
|
1457
|
+
}
|
|
1458
|
+
if (!isHelpCommand && !isVersionCommand) {
|
|
1459
|
+
forwardCommand(args, { debug: !!options.verbose }).catch(
|
|
1460
|
+
(error) => {
|
|
1461
|
+
if (typeof error === "string" || options.verbose) {
|
|
1462
|
+
console.error(error);
|
|
1463
|
+
} else if (error instanceof Error) {
|
|
1464
|
+
console.error(error.message);
|
|
1465
|
+
}
|
|
1466
|
+
process.exit(1);
|
|
1467
|
+
}
|
|
1468
|
+
);
|
|
1469
|
+
}
|
|
1470
|
+
};
|
|
1471
|
+
program.name("ph").description(
|
|
1472
|
+
"The Powerhouse CLI (ph-cmd) is a command-line interface tool that provides essential commands for managing Powerhouse projects. The tool and it's commands are fundamental for creating, building, and running Document Models as a builder in studio mode."
|
|
1473
|
+
).allowUnknownOption().option("--verbose, --debug", "Enable debug mode").option("-h, --help", "Display help information");
|
|
1474
|
+
registerCommands(program);
|
|
1475
|
+
program.action(defaultCommand);
|
|
1476
|
+
program.on("option:help", () => {
|
|
1477
|
+
const nonHelpArgs = process.argv.slice(2).filter((arg) => arg !== "--help" && arg !== "-h");
|
|
1478
|
+
if (nonHelpArgs.length === 0) {
|
|
1479
|
+
customHelpHandler().catch((error) => {
|
|
1480
|
+
console.error(error);
|
|
1481
|
+
process.exit(1);
|
|
1482
|
+
});
|
|
1483
|
+
}
|
|
1484
|
+
});
|
|
1485
|
+
program.parseAsync(process.argv).catch((error) => {
|
|
1486
|
+
const isDebug = process.argv.find(
|
|
1487
|
+
(arg) => ["--verbose", "--debug"].includes(arg)
|
|
1488
|
+
);
|
|
1489
|
+
if (isDebug) {
|
|
1490
|
+
console.error(error);
|
|
1491
|
+
return;
|
|
1492
|
+
}
|
|
1493
|
+
const errorMessage = error instanceof Error ? error.message : typeof error === "string" ? error : JSON.stringify(error, null, 2);
|
|
1494
|
+
console.error(errorMessage);
|
|
1495
|
+
});
|