ph-cmd 6.0.0-dev.5 → 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.
Files changed (139) hide show
  1. package/build/cli.js +1495 -0
  2. package/package.json +8 -8
  3. package/dist/scripts/generate-commands-md.d.ts +0 -2
  4. package/dist/scripts/generate-commands-md.d.ts.map +0 -1
  5. package/dist/scripts/generate-commands-md.js +0 -72
  6. package/dist/scripts/generate-commands-md.js.map +0 -1
  7. package/dist/scripts/generate-version.d.ts +0 -2
  8. package/dist/scripts/generate-version.d.ts.map +0 -1
  9. package/dist/scripts/generate-version.js +0 -13
  10. package/dist/scripts/generate-version.js.map +0 -1
  11. package/dist/src/cli.d.ts +0 -3
  12. package/dist/src/cli.d.ts.map +0 -1
  13. package/dist/src/cli.js +0 -120
  14. package/dist/src/cli.js.map +0 -1
  15. package/dist/src/commands/__tests__/update.test.d.ts +0 -2
  16. package/dist/src/commands/__tests__/update.test.d.ts.map +0 -1
  17. package/dist/src/commands/__tests__/update.test.js +0 -157
  18. package/dist/src/commands/__tests__/update.test.js.map +0 -1
  19. package/dist/src/commands/__tests__/use.test.d.ts +0 -2
  20. package/dist/src/commands/__tests__/use.test.d.ts.map +0 -1
  21. package/dist/src/commands/__tests__/use.test.js +0 -496
  22. package/dist/src/commands/__tests__/use.test.js.map +0 -1
  23. package/dist/src/commands/checkout.d.ts +0 -9
  24. package/dist/src/commands/checkout.d.ts.map +0 -1
  25. package/dist/src/commands/checkout.js +0 -37
  26. package/dist/src/commands/checkout.js.map +0 -1
  27. package/dist/src/commands/forward.d.ts +0 -7
  28. package/dist/src/commands/forward.d.ts.map +0 -1
  29. package/dist/src/commands/forward.js +0 -45
  30. package/dist/src/commands/forward.js.map +0 -1
  31. package/dist/src/commands/help.d.ts +0 -7
  32. package/dist/src/commands/help.d.ts.map +0 -1
  33. package/dist/src/commands/help.js +0 -14
  34. package/dist/src/commands/help.js.map +0 -1
  35. package/dist/src/commands/index.d.ts +0 -9
  36. package/dist/src/commands/index.d.ts.map +0 -1
  37. package/dist/src/commands/index.js +0 -15
  38. package/dist/src/commands/index.js.map +0 -1
  39. package/dist/src/commands/init.d.ts +0 -2
  40. package/dist/src/commands/init.d.ts.map +0 -1
  41. package/dist/src/commands/init.js +0 -165
  42. package/dist/src/commands/init.js.map +0 -1
  43. package/dist/src/commands/setup-globals.d.ts +0 -20
  44. package/dist/src/commands/setup-globals.d.ts.map +0 -1
  45. package/dist/src/commands/setup-globals.js +0 -24
  46. package/dist/src/commands/setup-globals.js.map +0 -1
  47. package/dist/src/commands/update.d.ts +0 -2
  48. package/dist/src/commands/update.d.ts.map +0 -1
  49. package/dist/src/commands/update.js +0 -95
  50. package/dist/src/commands/update.js.map +0 -1
  51. package/dist/src/commands/update.old.d.ts +0 -13
  52. package/dist/src/commands/update.old.d.ts.map +0 -1
  53. package/dist/src/commands/update.old.js +0 -105
  54. package/dist/src/commands/update.old.js.map +0 -1
  55. package/dist/src/commands/use-local.d.ts +0 -2
  56. package/dist/src/commands/use-local.d.ts.map +0 -1
  57. package/dist/src/commands/use-local.js +0 -115
  58. package/dist/src/commands/use-local.js.map +0 -1
  59. package/dist/src/commands/use.d.ts +0 -2
  60. package/dist/src/commands/use.d.ts.map +0 -1
  61. package/dist/src/commands/use.js +0 -117
  62. package/dist/src/commands/use.js.map +0 -1
  63. package/dist/src/commands/use.old.d.ts +0 -55
  64. package/dist/src/commands/use.old.d.ts.map +0 -1
  65. package/dist/src/commands/use.old.js +0 -219
  66. package/dist/src/commands/use.old.js.map +0 -1
  67. package/dist/src/commands/version.d.ts +0 -5
  68. package/dist/src/commands/version.d.ts.map +0 -1
  69. package/dist/src/commands/version.js +0 -42
  70. package/dist/src/commands/version.js.map +0 -1
  71. package/dist/src/help.d.ts +0 -25
  72. package/dist/src/help.d.ts.map +0 -1
  73. package/dist/src/help.js +0 -230
  74. package/dist/src/help.js.map +0 -1
  75. package/dist/src/index.d.ts +0 -3
  76. package/dist/src/index.d.ts.map +0 -1
  77. package/dist/src/index.js +0 -3
  78. package/dist/src/index.js.map +0 -1
  79. package/dist/src/types.d.ts +0 -2
  80. package/dist/src/types.d.ts.map +0 -1
  81. package/dist/src/types.js +0 -2
  82. package/dist/src/types.js.map +0 -1
  83. package/dist/src/utils/constants.d.ts +0 -59
  84. package/dist/src/utils/constants.d.ts.map +0 -1
  85. package/dist/src/utils/constants.js +0 -102
  86. package/dist/src/utils/constants.js.map +0 -1
  87. package/dist/src/utils/dependencies.d.ts +0 -4
  88. package/dist/src/utils/dependencies.d.ts.map +0 -1
  89. package/dist/src/utils/dependencies.js +0 -61
  90. package/dist/src/utils/dependencies.js.map +0 -1
  91. package/dist/src/utils/file-system.d.ts +0 -2
  92. package/dist/src/utils/file-system.d.ts.map +0 -1
  93. package/dist/src/utils/file-system.js +0 -12
  94. package/dist/src/utils/file-system.js.map +0 -1
  95. package/dist/src/utils/help-formatting.d.ts +0 -35
  96. package/dist/src/utils/help-formatting.d.ts.map +0 -1
  97. package/dist/src/utils/help-formatting.js +0 -188
  98. package/dist/src/utils/help-formatting.js.map +0 -1
  99. package/dist/src/utils/help.d.ts +0 -31
  100. package/dist/src/utils/help.d.ts.map +0 -1
  101. package/dist/src/utils/help.js +0 -72
  102. package/dist/src/utils/help.js.map +0 -1
  103. package/dist/src/utils/index.d.ts +0 -8
  104. package/dist/src/utils/index.d.ts.map +0 -1
  105. package/dist/src/utils/index.js +0 -7
  106. package/dist/src/utils/index.js.map +0 -1
  107. package/dist/src/utils/package-manager.d.ts +0 -27
  108. package/dist/src/utils/package-manager.d.ts.map +0 -1
  109. package/dist/src/utils/package-manager.js +0 -177
  110. package/dist/src/utils/package-manager.js.map +0 -1
  111. package/dist/src/utils/parsing.d.ts +0 -20
  112. package/dist/src/utils/parsing.d.ts.map +0 -1
  113. package/dist/src/utils/parsing.js +0 -52
  114. package/dist/src/utils/parsing.js.map +0 -1
  115. package/dist/src/utils/run-cmd.d.ts +0 -2
  116. package/dist/src/utils/run-cmd.d.ts.map +0 -1
  117. package/dist/src/utils/run-cmd.js +0 -11
  118. package/dist/src/utils/run-cmd.js.map +0 -1
  119. package/dist/src/utils/types.d.ts +0 -21
  120. package/dist/src/utils/types.d.ts.map +0 -1
  121. package/dist/src/utils/types.js +0 -2
  122. package/dist/src/utils/types.js.map +0 -1
  123. package/dist/src/utils/validate-remote-drive-checkout.d.ts +0 -7
  124. package/dist/src/utils/validate-remote-drive-checkout.d.ts.map +0 -1
  125. package/dist/src/utils/validate-remote-drive-checkout.js +0 -45
  126. package/dist/src/utils/validate-remote-drive-checkout.js.map +0 -1
  127. package/dist/src/utils/validate-remote-drive.d.ts +0 -7
  128. package/dist/src/utils/validate-remote-drive.d.ts.map +0 -1
  129. package/dist/src/utils/validate-remote-drive.js +0 -51
  130. package/dist/src/utils/validate-remote-drive.js.map +0 -1
  131. package/dist/src/version.d.ts +0 -2
  132. package/dist/src/version.d.ts.map +0 -1
  133. package/dist/src/version.js +0 -3
  134. package/dist/src/version.js.map +0 -1
  135. package/dist/tsconfig.tsbuildinfo +0 -1
  136. package/dist/vitest.config.d.ts +0 -3
  137. package/dist/vitest.config.d.ts.map +0 -1
  138. package/dist/vitest.config.js +0 -7
  139. 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
+ });