ph-cmd 6.2.3-dev.0 → 6.2.3-dev.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="1b86dd82-6b93-5626-9454-0799daf0f315")}catch(e){}}();
4
- import { t as getVersion } from "./get-version-G0G6fFLl.mjs";
3
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="3c343493-d1c1-53be-8105-8600810b1670")}catch(e){}}();
4
+ import { t as getVersion } from "./get-version-CKWHzzHh.mjs";
5
+ import { r as maybeNotifyOutdated } from "./version-check-BxMITre2.mjs";
5
6
  import { phCliCommandNames } from "@powerhousedao/shared/clis/command-names";
6
7
  import { initCliTelemetry } from "@powerhousedao/shared/clis/telemetry";
7
8
  import { assertNodeVersion } from "@powerhousedao/shared/clis/utils";
@@ -17,11 +18,11 @@ function detectPackageManager() {
17
18
  * any code is parsed to avoid errors on startup due to unsupported dependencies.
18
19
  */
19
20
  async function runPhCliCommand(phCliCommand) {
20
- const { executePhCliCommand } = await import("./ph-cli-D42c_L7U.mjs");
21
+ const { executePhCliCommand } = await import("./ph-cli-BxlV6SZ2.mjs");
21
22
  return await executePhCliCommand(phCliCommand);
22
23
  }
23
24
  async function runPhCmdCommand(args) {
24
- const { run } = await import("./run-DX-j7-DZ.mjs");
25
+ const { run } = await import("./run-0gjMNmbN.mjs");
25
26
  return await run(args);
26
27
  }
27
28
  let sentryClient = void 0;
@@ -46,6 +47,11 @@ async function main() {
46
47
  console.log(await getPhCmdVersionInfo(getVersion()));
47
48
  process.exit(0);
48
49
  }
50
+ await maybeNotifyOutdated({
51
+ args,
52
+ currentVersion: getVersion(),
53
+ stderrIsTty: Boolean(process.stderr.isTTY)
54
+ });
49
55
  if (command === "connect" && !args.some((arg) => [
50
56
  "studio",
51
57
  "build",
@@ -74,4 +80,4 @@ await main().catch(async (error) => {
74
80
  export {};
75
81
 
76
82
  //# sourceMappingURL=cli.mjs.map
77
- //# debugId=1b86dd82-6b93-5626-9454-0799daf0f315
83
+ //# debugId=3c343493-d1c1-53be-8105-8600810b1670
package/dist/cli.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.mjs","sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { phCliCommandNames } from \"@powerhousedao/shared/clis/command-names\";\nimport {\n initCliTelemetry,\n type TelemetryClient,\n} from \"@powerhousedao/shared/clis/telemetry\";\nimport { assertNodeVersion } from \"@powerhousedao/shared/clis/utils\";\nimport { getVersion } from \"./get-version.js\";\n\n// Commands whose second positional is itself a subcommand (vs. a project\n// name / file path). Keeping this explicit avoids high-cardinality tag\n// values like `subcommand:my-package` polluting Sentry.\nconst COMMANDS_WITH_SUBCOMMANDS = new Set([\"connect\", \"vetra\"]);\n\nfunction detectPackageManager(): string | undefined {\n // npm, pnpm, yarn and bun all set npm_config_user_agent like\n // \"pnpm/8.5.0 npm/? node/v20.11.1 darwin arm64\". When the user invokes\n // `ph` directly (not via dlx/exec) it's typically unset — skip the tag\n // in that case rather than mislabel.\n const ua = process.env.npm_config_user_agent;\n if (!ua) return undefined;\n return ua.split(\" \")[0]?.split(\"/\")[0] || undefined;\n}\n\n/**\n * ph-cli and ph-cmd are loaded lazily so that the node version is checked before\n * any code is parsed to avoid errors on startup due to unsupported dependencies.\n */\n\nasync function runPhCliCommand(phCliCommand: string) {\n const { executePhCliCommand } = await import(\"./ph-cli.js\");\n return await executePhCliCommand(phCliCommand);\n}\nasync function runPhCmdCommand(args: string[]) {\n const { run } = await import(\"./run.js\");\n return await run(args);\n}\n\nlet sentryClient: TelemetryClient | undefined = undefined;\n\nasync function main() {\n assertNodeVersion();\n // Opt-out telemetry; asked once on first interactive run. No-op under\n // PH_NO_TELEMETRY / DO_NOT_TRACK / CI.\n sentryClient = await initCliTelemetry({\n cliName: \"ph-cmd\",\n release: getVersion(),\n });\n const args = process.argv.slice(2);\n const command = args[0];\n const subcommand =\n command &&\n COMMANDS_WITH_SUBCOMMANDS.has(command) &&\n args[1] &&\n !args[1].startsWith(\"-\")\n ? args[1]\n : undefined;\n sentryClient?.attachInvocationContext({\n command,\n subcommand,\n pm: detectPackageManager(),\n argv: args,\n cwd: process.cwd(),\n });\n\n // Short-circuit `ph --version` / `ph -v` so we don't pay for the full\n // cmd-ts subcommand tree (which dynamic-imports the heavy clis bundle\n // just to populate the `version` field). `ph use --version 1.2.3` and\n // similar are unaffected because they have a subcommand first.\n if (args.length === 1 && (command === \"--version\" || command === \"-v\")) {\n const { getPhCmdVersionInfo } = await import(\"@powerhousedao/shared/clis\");\n console.log(await getPhCmdVersionInfo(getVersion()));\n process.exit(0);\n }\n\n // handle the special case where running `connect` with no positional argument\n // defaults to `connect studio`\n if (\n command === \"connect\" &&\n !args.some((arg) => [\"studio\", \"build\", \"preview\"].includes(arg)) &&\n // do not default to `connect studio` when help is present, instead show general help\n // for the `connect` command\n !args.some((arg) => [\"--help\", \"-h\"].includes(arg))\n ) {\n await runPhCliCommand(\"connect\");\n process.exit(0);\n }\n\n // forward command to the local ph-cli installation if it exists\n if (\n phCliCommandNames.includes(command as (typeof phCliCommandNames)[number])\n ) {\n await runPhCliCommand(command);\n process.exit(0);\n }\n\n await runPhCmdCommand(args);\n process.exit(0);\n}\n\nawait main().catch(async (error) => {\n const isDebug = process.argv.slice(2).includes(\"--debug\");\n // No-op when telemetry is disabled; flushes before we exit otherwise.\n await sentryClient?.captureCliError(error);\n if (isDebug) {\n throw error;\n }\n if (error instanceof Error) {\n console.error(error.message);\n process.exit(1);\n } else {\n throw error;\n }\n});\n"],"names":[],"mappings":";;;;;;;;AAYA,MAAM,4BAA4B,IAAI,IAAI,CAAC,WAAW,QAAQ,CAAC;AAE/D,SAAS,uBAA2C;CAKlD,MAAM,KAAK,QAAQ,IAAI;AACvB,KAAI,CAAC,GAAI,QAAO,KAAA;AAChB,QAAO,GAAG,MAAM,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,MAAM,KAAA;;;;;;AAQ5C,eAAe,gBAAgB,cAAsB;CACnD,MAAM,EAAE,wBAAwB,MAAM,OAAO;AAC7C,QAAO,MAAM,oBAAoB,aAAa;;AAEhD,eAAe,gBAAgB,MAAgB;CAC7C,MAAM,EAAE,QAAQ,MAAM,OAAO;AAC7B,QAAO,MAAM,IAAI,KAAK;;AAGxB,IAAI,eAA4C,KAAA;AAEhD,eAAe,OAAO;AACpB,oBAAmB;AAGnB,gBAAe,MAAM,iBAAiB;EACpC,SAAS;EACT,SAAS,YAAY;EACtB,CAAC;CACF,MAAM,OAAO,QAAQ,KAAK,MAAM,EAAE;CAClC,MAAM,UAAU,KAAK;CACrB,MAAM,aACJ,WACA,0BAA0B,IAAI,QAAQ,IACtC,KAAK,MACL,CAAC,KAAK,GAAG,WAAW,IAAI,GACpB,KAAK,KACL,KAAA;AACN,eAAc,wBAAwB;EACpC;EACA;EACA,IAAI,sBAAsB;EAC1B,MAAM;EACN,KAAK,QAAQ,KAAK;EACnB,CAAC;AAMF,KAAI,KAAK,WAAW,MAAM,YAAY,eAAe,YAAY,OAAO;EACtE,MAAM,EAAE,wBAAwB,MAAM,OAAO;AAC7C,UAAQ,IAAI,MAAM,oBAAoB,YAAY,CAAC,CAAC;AACpD,UAAQ,KAAK,EAAE;;AAKjB,KACE,YAAY,aACZ,CAAC,KAAK,MAAM,QAAQ;EAAC;EAAU;EAAS;EAAU,CAAC,SAAS,IAAI,CAAC,IAGjE,CAAC,KAAK,MAAM,QAAQ,CAAC,UAAU,KAAK,CAAC,SAAS,IAAI,CAAC,EACnD;AACA,QAAM,gBAAgB,UAAU;AAChC,UAAQ,KAAK,EAAE;;AAIjB,KACE,kBAAkB,SAAS,QAA8C,EACzE;AACA,QAAM,gBAAgB,QAAQ;AAC9B,UAAQ,KAAK,EAAE;;AAGjB,OAAM,gBAAgB,KAAK;AAC3B,SAAQ,KAAK,EAAE;;AAGjB,MAAM,MAAM,CAAC,MAAM,OAAO,UAAU;CAClC,MAAM,UAAU,QAAQ,KAAK,MAAM,EAAE,CAAC,SAAS,UAAU;AAEzD,OAAM,cAAc,gBAAgB,MAAM;AAC1C,KAAI,QACF,OAAM;AAER,KAAI,iBAAiB,OAAO;AAC1B,UAAQ,MAAM,MAAM,QAAQ;AAC5B,UAAQ,KAAK,EAAE;OAEf,OAAM;EAER","debug_id":"1b86dd82-6b93-5626-9454-0799daf0f315"}
1
+ {"version":3,"file":"cli.mjs","sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { phCliCommandNames } from \"@powerhousedao/shared/clis/command-names\";\nimport {\n initCliTelemetry,\n type TelemetryClient,\n} from \"@powerhousedao/shared/clis/telemetry\";\nimport { assertNodeVersion } from \"@powerhousedao/shared/clis/utils\";\nimport { getVersion } from \"./get-version.js\";\nimport { maybeNotifyOutdated } from \"./utils/version-check.js\";\n\n// Commands whose second positional is itself a subcommand (vs. a project\n// name / file path). Keeping this explicit avoids high-cardinality tag\n// values like `subcommand:my-package` polluting Sentry.\nconst COMMANDS_WITH_SUBCOMMANDS = new Set([\"connect\", \"vetra\"]);\n\nfunction detectPackageManager(): string | undefined {\n // npm, pnpm, yarn and bun all set npm_config_user_agent like\n // \"pnpm/8.5.0 npm/? node/v20.11.1 darwin arm64\". When the user invokes\n // `ph` directly (not via dlx/exec) it's typically unset — skip the tag\n // in that case rather than mislabel.\n const ua = process.env.npm_config_user_agent;\n if (!ua) return undefined;\n return ua.split(\" \")[0]?.split(\"/\")[0] || undefined;\n}\n\n/**\n * ph-cli and ph-cmd are loaded lazily so that the node version is checked before\n * any code is parsed to avoid errors on startup due to unsupported dependencies.\n */\n\nasync function runPhCliCommand(phCliCommand: string) {\n const { executePhCliCommand } = await import(\"./ph-cli.js\");\n return await executePhCliCommand(phCliCommand);\n}\nasync function runPhCmdCommand(args: string[]) {\n const { run } = await import(\"./run.js\");\n return await run(args);\n}\n\nlet sentryClient: TelemetryClient | undefined = undefined;\n\nasync function main() {\n assertNodeVersion();\n // Opt-out telemetry; asked once on first interactive run. No-op under\n // PH_NO_TELEMETRY / DO_NOT_TRACK / CI.\n sentryClient = await initCliTelemetry({\n cliName: \"ph-cmd\",\n release: getVersion(),\n });\n const args = process.argv.slice(2);\n const command = args[0];\n const subcommand =\n command &&\n COMMANDS_WITH_SUBCOMMANDS.has(command) &&\n args[1] &&\n !args[1].startsWith(\"-\")\n ? args[1]\n : undefined;\n sentryClient?.attachInvocationContext({\n command,\n subcommand,\n pm: detectPackageManager(),\n argv: args,\n cwd: process.cwd(),\n });\n\n // Short-circuit `ph --version` / `ph -v` so we don't pay for the full\n // cmd-ts subcommand tree (which dynamic-imports the heavy clis bundle\n // just to populate the `version` field). `ph use --version 1.2.3` and\n // similar are unaffected because they have a subcommand first.\n if (args.length === 1 && (command === \"--version\" || command === \"-v\")) {\n const { getPhCmdVersionInfo } = await import(\"@powerhousedao/shared/clis\");\n console.log(await getPhCmdVersionInfo(getVersion()));\n process.exit(0);\n }\n\n // Outdated-build notice: a stream-aware version check against the\n // registry, cached for 24 hours and shown only on a TTY. It never\n // blocks or breaks the command — every failure is swallowed inside\n // `maybeNotifyOutdated`.\n await maybeNotifyOutdated({\n args,\n currentVersion: getVersion(),\n stderrIsTty: Boolean(process.stderr.isTTY),\n });\n\n // handle the special case where running `connect` with no positional argument\n // defaults to `connect studio`\n if (\n command === \"connect\" &&\n !args.some((arg) => [\"studio\", \"build\", \"preview\"].includes(arg)) &&\n // do not default to `connect studio` when help is present, instead show general help\n // for the `connect` command\n !args.some((arg) => [\"--help\", \"-h\"].includes(arg))\n ) {\n await runPhCliCommand(\"connect\");\n process.exit(0);\n }\n\n // forward command to the local ph-cli installation if it exists\n if (\n phCliCommandNames.includes(command as (typeof phCliCommandNames)[number])\n ) {\n await runPhCliCommand(command);\n process.exit(0);\n }\n\n await runPhCmdCommand(args);\n process.exit(0);\n}\n\nawait main().catch(async (error) => {\n const isDebug = process.argv.slice(2).includes(\"--debug\");\n // No-op when telemetry is disabled; flushes before we exit otherwise.\n await sentryClient?.captureCliError(error);\n if (isDebug) {\n throw error;\n }\n if (error instanceof Error) {\n console.error(error.message);\n process.exit(1);\n } else {\n throw error;\n }\n});\n"],"names":[],"mappings":";;;;;;;;;AAaA,MAAM,4BAA4B,IAAI,IAAI,CAAC,WAAW,QAAQ,CAAC;AAE/D,SAAS,uBAA2C;CAKlD,MAAM,KAAK,QAAQ,IAAI;AACvB,KAAI,CAAC,GAAI,QAAO,KAAA;AAChB,QAAO,GAAG,MAAM,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,MAAM,KAAA;;;;;;AAQ5C,eAAe,gBAAgB,cAAsB;CACnD,MAAM,EAAE,wBAAwB,MAAM,OAAO;AAC7C,QAAO,MAAM,oBAAoB,aAAa;;AAEhD,eAAe,gBAAgB,MAAgB;CAC7C,MAAM,EAAE,QAAQ,MAAM,OAAO;AAC7B,QAAO,MAAM,IAAI,KAAK;;AAGxB,IAAI,eAA4C,KAAA;AAEhD,eAAe,OAAO;AACpB,oBAAmB;AAGnB,gBAAe,MAAM,iBAAiB;EACpC,SAAS;EACT,SAAS,YAAY;EACtB,CAAC;CACF,MAAM,OAAO,QAAQ,KAAK,MAAM,EAAE;CAClC,MAAM,UAAU,KAAK;CACrB,MAAM,aACJ,WACA,0BAA0B,IAAI,QAAQ,IACtC,KAAK,MACL,CAAC,KAAK,GAAG,WAAW,IAAI,GACpB,KAAK,KACL,KAAA;AACN,eAAc,wBAAwB;EACpC;EACA;EACA,IAAI,sBAAsB;EAC1B,MAAM;EACN,KAAK,QAAQ,KAAK;EACnB,CAAC;AAMF,KAAI,KAAK,WAAW,MAAM,YAAY,eAAe,YAAY,OAAO;EACtE,MAAM,EAAE,wBAAwB,MAAM,OAAO;AAC7C,UAAQ,IAAI,MAAM,oBAAoB,YAAY,CAAC,CAAC;AACpD,UAAQ,KAAK,EAAE;;AAOjB,OAAM,oBAAoB;EACxB;EACA,gBAAgB,YAAY;EAC5B,aAAa,QAAQ,QAAQ,OAAO,MAAM;EAC3C,CAAC;AAIF,KACE,YAAY,aACZ,CAAC,KAAK,MAAM,QAAQ;EAAC;EAAU;EAAS;EAAU,CAAC,SAAS,IAAI,CAAC,IAGjE,CAAC,KAAK,MAAM,QAAQ,CAAC,UAAU,KAAK,CAAC,SAAS,IAAI,CAAC,EACnD;AACA,QAAM,gBAAgB,UAAU;AAChC,UAAQ,KAAK,EAAE;;AAIjB,KACE,kBAAkB,SAAS,QAA8C,EACzE;AACA,QAAM,gBAAgB,QAAQ;AAC9B,UAAQ,KAAK,EAAE;;AAGjB,OAAM,gBAAgB,KAAK;AAC3B,SAAQ,KAAK,EAAE;;AAGjB,MAAM,MAAM,CAAC,MAAM,OAAO,UAAU;CAClC,MAAM,UAAU,QAAQ,KAAK,MAAM,EAAE,CAAC,SAAS,UAAU;AAEzD,OAAM,cAAc,gBAAgB,MAAM;AAC1C,KAAI,QACF,OAAM;AAER,KAAI,iBAAiB,OAAO;AAC1B,UAAQ,MAAM,MAAM,QAAQ;AAC5B,UAAQ,KAAK,EAAE;OAEf,OAAM;EAER","debug_id":"3c343493-d1c1-53be-8105-8600810b1670"}
@@ -1,5 +1,5 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="6507d40c-85cc-5f0d-aaa8-3287d011fd2a")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="a8fa3f98-459c-513d-a52e-b2e156cfb207")}catch(e){}}();
3
3
  import { execSync } from "node:child_process";
4
4
  //#region src/utils/delegate-init.ts
5
5
  const PH_CLI_PACKAGE = "@powerhousedao/ph-cli";
@@ -69,5 +69,5 @@ async function delegateInit(args, extraForwardedArgs = []) {
69
69
  //#endregion
70
70
  export { delegateInit as t };
71
71
 
72
- //# sourceMappingURL=delegate-init-B3_b7484.mjs.map
73
- //# debugId=6507d40c-85cc-5f0d-aaa8-3287d011fd2a
72
+ //# sourceMappingURL=delegate-init-BiHdTmaF.mjs.map
73
+ //# debugId=a8fa3f98-459c-513d-a52e-b2e156cfb207
@@ -1 +1 @@
1
- {"version":3,"file":"delegate-init-B3_b7484.mjs","sources":["../src/utils/delegate-init.ts"],"sourcesContent":["import type { Agent } from \"package-manager-detector\";\nimport { execSync } from \"node:child_process\";\n\nconst PH_CLI_PACKAGE = \"@powerhousedao/ph-cli\";\n// `init` was added to ph-cli in the 6.x rewrite. Older versions (still on\n// the `latest` tag at time of writing) shell out via commander and bail with\n// a confusing \"unknown command 'init'\" error after a 90-second dlx install.\n// This floor lets us fail fast with an actionable message instead.\nconst MIN_PH_CLI_MAJOR = 6;\n\n/**\n * Subset of `initArgs` the delegator actually inspects. Keeping this loose\n * lets `setup-globals` reuse the helper without an extra type import dance.\n */\nexport interface DelegateInitArgs {\n packageManager?: Agent;\n npm?: boolean;\n pnpm?: boolean;\n yarn?: boolean;\n bun?: boolean;\n tag?: string;\n version?: string;\n dev?: boolean;\n staging?: boolean;\n rc?: boolean;\n debug?: boolean;\n}\n\n/**\n * Resolves a concrete `@powerhousedao/ph-cli` version, verifies it's >= 6.x,\n * and shells out via the user's package manager (npx / pnpm dlx / etc.) to\n * run `ph-cli init`. Used by both `ph init` (forwards verbatim) and\n * `ph setup-globals` (forwards with `--name .ph` injected after chdir to ~).\n *\n * Does NOT call `process.exit`: callers are responsible for any post-init\n * fix-up + exit.\n */\nexport async function delegateInit(\n args: DelegateInitArgs,\n extraForwardedArgs: string[] = [],\n): Promise<void> {\n const {\n fetchNpmVersionFromRegistryForTag,\n handleMutuallyExclusiveOptions,\n parsePackageManager,\n parseTag,\n } = await import(\"@powerhousedao/shared/clis\");\n\n handleMutuallyExclusiveOptions(\n {\n tag: args.tag,\n version: args.version,\n dev: args.dev,\n staging: args.staging,\n rc: args.rc,\n },\n \"versioning strategy\",\n );\n\n handleMutuallyExclusiveOptions(\n {\n npm: args.npm,\n pnpm: args.pnpm,\n yarn: args.yarn,\n bun: args.bun,\n packageManager: args.packageManager,\n },\n \"package manager\",\n );\n\n const tag = parseTag(args);\n const phCliVersionOrTag = args.version ?? tag;\n const pm = parsePackageManager(args) ?? \"npm\";\n // `process.argv` here is `[node, ph-cmd-bin, <subcommand>, ...userArgs]`.\n // Forward everything from the user, prepending caller-supplied flags.\n const forwardedArgs = [...extraForwardedArgs, ...process.argv.slice(3)];\n\n // Resolve the tag to a concrete version up front and verify it's >= 6.x.\n // `--version` is user-supplied so we trust it and only resolve when a tag\n // (latest/staging/dev) is in play.\n let resolvedVersion = args.version;\n try {\n if (!resolvedVersion) {\n resolvedVersion = await fetchNpmVersionFromRegistryForTag(\n PH_CLI_PACKAGE,\n tag,\n );\n }\n } catch (err) {\n // Network/registry hiccup — fall through to the dlx so a flaky\n // connection doesn't block the user. The dlx will surface its own\n // error if the version genuinely can't be installed.\n if (args.debug) {\n console.error(\">>> ph-cli version resolution skipped:\", err);\n }\n }\n const { coerce } = await import(\"semver\");\n const parsed = resolvedVersion ? coerce(resolvedVersion) : null;\n if (parsed && parsed.major < MIN_PH_CLI_MAJOR) {\n // Print + exit (rather than throw) to avoid the cli.ts catch handler\n // shipping this expected user-input error to Sentry.\n console.error(\n `${PH_CLI_PACKAGE}@${phCliVersionOrTag} resolves to ${resolvedVersion}, ` +\n `which doesn't support 'init' (requires >= ${MIN_PH_CLI_MAJOR}.0.0).\\n` +\n `Try: ph init --dev <args> or ph init --version <${MIN_PH_CLI_MAJOR}.x.x> <args>`,\n );\n process.exit(1);\n }\n\n const phCliPackage = `${PH_CLI_PACKAGE}@${resolvedVersion ?? phCliVersionOrTag}`;\n const { resolveCommand } = await import(\"package-manager-detector\");\n const resolved = resolveCommand(pm, \"execute\", [\n phCliPackage,\n \"init\",\n ...forwardedArgs,\n ]);\n\n if (!resolved) {\n throw new Error(\n `Could not resolve execute command for package manager \"${pm}\".`,\n );\n }\n\n const { injectPnpmAllowBuilds } = await import(\"@powerhousedao/shared/clis\");\n injectPnpmAllowBuilds(pm, resolved);\n\n const { command: cmd, args: cmdArgs } = resolved;\n const fullCmd = `${cmd} ${cmdArgs.join(\" \")}`;\n\n if (args.debug) {\n console.log(\">>> Delegating to ph-cli:\", fullCmd);\n }\n\n try {\n execSync(fullCmd, { stdio: \"inherit\" });\n } catch (err) {\n // Propagate normal non-zero exits but throw on abnormal exits to ensure\n // the error is reported.\n const e = err as {\n status?: number | null;\n signal?: NodeJS.Signals | null;\n };\n if (typeof e.status === \"number\" && !e.signal) {\n process.exit(e.status);\n }\n throw err;\n }\n}\n"],"names":[],"mappings":";;;;AAGA,MAAM,iBAAiB;AAKvB,MAAM,mBAAmB;;;;;;;;;;AA6BzB,eAAsB,aACpB,MACA,qBAA+B,EAAE,EAClB;CACf,MAAM,EACJ,mCACA,gCACA,qBACA,aACE,MAAM,OAAO;AAEjB,gCACE;EACE,KAAK,KAAK;EACV,SAAS,KAAK;EACd,KAAK,KAAK;EACV,SAAS,KAAK;EACd,IAAI,KAAK;EACV,EACD,sBACD;AAED,gCACE;EACE,KAAK,KAAK;EACV,MAAM,KAAK;EACX,MAAM,KAAK;EACX,KAAK,KAAK;EACV,gBAAgB,KAAK;EACtB,EACD,kBACD;CAED,MAAM,MAAM,SAAS,KAAK;CAC1B,MAAM,oBAAoB,KAAK,WAAW;CAC1C,MAAM,KAAK,oBAAoB,KAAK,IAAI;CAGxC,MAAM,gBAAgB,CAAC,GAAG,oBAAoB,GAAG,QAAQ,KAAK,MAAM,EAAE,CAAC;CAKvE,IAAI,kBAAkB,KAAK;AAC3B,KAAI;AACF,MAAI,CAAC,gBACH,mBAAkB,MAAM,kCACtB,gBACA,IACD;UAEI,KAAK;AAIZ,MAAI,KAAK,MACP,SAAQ,MAAM,0CAA0C,IAAI;;CAGhE,MAAM,EAAE,WAAW,MAAM,OAAO;CAChC,MAAM,SAAS,kBAAkB,OAAO,gBAAgB,GAAG;AAC3D,KAAI,UAAU,OAAO,QAAQ,kBAAkB;AAG7C,UAAQ,MACN,GAAG,eAAe,GAAG,kBAAkB,eAAe,gBAAgB,8CACvB,iBAAiB,+DACN,iBAAiB,cAC5E;AACD,UAAQ,KAAK,EAAE;;CAGjB,MAAM,eAAe,GAAG,eAAe,GAAG,mBAAmB;CAC7D,MAAM,EAAE,mBAAmB,MAAM,OAAO;CACxC,MAAM,WAAW,eAAe,IAAI,WAAW;EAC7C;EACA;EACA,GAAG;EACJ,CAAC;AAEF,KAAI,CAAC,SACH,OAAM,IAAI,MACR,0DAA0D,GAAG,IAC9D;CAGH,MAAM,EAAE,0BAA0B,MAAM,OAAO;AAC/C,uBAAsB,IAAI,SAAS;CAEnC,MAAM,EAAE,SAAS,KAAK,MAAM,YAAY;CACxC,MAAM,UAAU,GAAG,IAAI,GAAG,QAAQ,KAAK,IAAI;AAE3C,KAAI,KAAK,MACP,SAAQ,IAAI,6BAA6B,QAAQ;AAGnD,KAAI;AACF,WAAS,SAAS,EAAE,OAAO,WAAW,CAAC;UAChC,KAAK;EAGZ,MAAM,IAAI;AAIV,MAAI,OAAO,EAAE,WAAW,YAAY,CAAC,EAAE,OACrC,SAAQ,KAAK,EAAE,OAAO;AAExB,QAAM","debug_id":"6507d40c-85cc-5f0d-aaa8-3287d011fd2a"}
1
+ {"version":3,"file":"delegate-init-BiHdTmaF.mjs","sources":["../src/utils/delegate-init.ts"],"sourcesContent":["import type { Agent } from \"package-manager-detector\";\nimport { execSync } from \"node:child_process\";\n\nconst PH_CLI_PACKAGE = \"@powerhousedao/ph-cli\";\n// `init` was added to ph-cli in the 6.x rewrite. Older versions (still on\n// the `latest` tag at time of writing) shell out via commander and bail with\n// a confusing \"unknown command 'init'\" error after a 90-second dlx install.\n// This floor lets us fail fast with an actionable message instead.\nconst MIN_PH_CLI_MAJOR = 6;\n\n/**\n * Subset of `initArgs` the delegator actually inspects. Keeping this loose\n * lets `setup-globals` reuse the helper without an extra type import dance.\n */\nexport interface DelegateInitArgs {\n packageManager?: Agent;\n npm?: boolean;\n pnpm?: boolean;\n yarn?: boolean;\n bun?: boolean;\n tag?: string;\n version?: string;\n dev?: boolean;\n staging?: boolean;\n rc?: boolean;\n debug?: boolean;\n}\n\n/**\n * Resolves a concrete `@powerhousedao/ph-cli` version, verifies it's >= 6.x,\n * and shells out via the user's package manager (npx / pnpm dlx / etc.) to\n * run `ph-cli init`. Used by both `ph init` (forwards verbatim) and\n * `ph setup-globals` (forwards with `--name .ph` injected after chdir to ~).\n *\n * Does NOT call `process.exit`: callers are responsible for any post-init\n * fix-up + exit.\n */\nexport async function delegateInit(\n args: DelegateInitArgs,\n extraForwardedArgs: string[] = [],\n): Promise<void> {\n const {\n fetchNpmVersionFromRegistryForTag,\n handleMutuallyExclusiveOptions,\n parsePackageManager,\n parseTag,\n } = await import(\"@powerhousedao/shared/clis\");\n\n handleMutuallyExclusiveOptions(\n {\n tag: args.tag,\n version: args.version,\n dev: args.dev,\n staging: args.staging,\n rc: args.rc,\n },\n \"versioning strategy\",\n );\n\n handleMutuallyExclusiveOptions(\n {\n npm: args.npm,\n pnpm: args.pnpm,\n yarn: args.yarn,\n bun: args.bun,\n packageManager: args.packageManager,\n },\n \"package manager\",\n );\n\n const tag = parseTag(args);\n const phCliVersionOrTag = args.version ?? tag;\n const pm = parsePackageManager(args) ?? \"npm\";\n // `process.argv` here is `[node, ph-cmd-bin, <subcommand>, ...userArgs]`.\n // Forward everything from the user, prepending caller-supplied flags.\n const forwardedArgs = [...extraForwardedArgs, ...process.argv.slice(3)];\n\n // Resolve the tag to a concrete version up front and verify it's >= 6.x.\n // `--version` is user-supplied so we trust it and only resolve when a tag\n // (latest/staging/dev) is in play.\n let resolvedVersion = args.version;\n try {\n if (!resolvedVersion) {\n resolvedVersion = await fetchNpmVersionFromRegistryForTag(\n PH_CLI_PACKAGE,\n tag,\n );\n }\n } catch (err) {\n // Network/registry hiccup — fall through to the dlx so a flaky\n // connection doesn't block the user. The dlx will surface its own\n // error if the version genuinely can't be installed.\n if (args.debug) {\n console.error(\">>> ph-cli version resolution skipped:\", err);\n }\n }\n const { coerce } = await import(\"semver\");\n const parsed = resolvedVersion ? coerce(resolvedVersion) : null;\n if (parsed && parsed.major < MIN_PH_CLI_MAJOR) {\n // Print + exit (rather than throw) to avoid the cli.ts catch handler\n // shipping this expected user-input error to Sentry.\n console.error(\n `${PH_CLI_PACKAGE}@${phCliVersionOrTag} resolves to ${resolvedVersion}, ` +\n `which doesn't support 'init' (requires >= ${MIN_PH_CLI_MAJOR}.0.0).\\n` +\n `Try: ph init --dev <args> or ph init --version <${MIN_PH_CLI_MAJOR}.x.x> <args>`,\n );\n process.exit(1);\n }\n\n const phCliPackage = `${PH_CLI_PACKAGE}@${resolvedVersion ?? phCliVersionOrTag}`;\n const { resolveCommand } = await import(\"package-manager-detector\");\n const resolved = resolveCommand(pm, \"execute\", [\n phCliPackage,\n \"init\",\n ...forwardedArgs,\n ]);\n\n if (!resolved) {\n throw new Error(\n `Could not resolve execute command for package manager \"${pm}\".`,\n );\n }\n\n const { injectPnpmAllowBuilds } = await import(\"@powerhousedao/shared/clis\");\n injectPnpmAllowBuilds(pm, resolved);\n\n const { command: cmd, args: cmdArgs } = resolved;\n const fullCmd = `${cmd} ${cmdArgs.join(\" \")}`;\n\n if (args.debug) {\n console.log(\">>> Delegating to ph-cli:\", fullCmd);\n }\n\n try {\n execSync(fullCmd, { stdio: \"inherit\" });\n } catch (err) {\n // Propagate normal non-zero exits but throw on abnormal exits to ensure\n // the error is reported.\n const e = err as {\n status?: number | null;\n signal?: NodeJS.Signals | null;\n };\n if (typeof e.status === \"number\" && !e.signal) {\n process.exit(e.status);\n }\n throw err;\n }\n}\n"],"names":[],"mappings":";;;;AAGA,MAAM,iBAAiB;AAKvB,MAAM,mBAAmB;;;;;;;;;;AA6BzB,eAAsB,aACpB,MACA,qBAA+B,EAAE,EAClB;CACf,MAAM,EACJ,mCACA,gCACA,qBACA,aACE,MAAM,OAAO;AAEjB,gCACE;EACE,KAAK,KAAK;EACV,SAAS,KAAK;EACd,KAAK,KAAK;EACV,SAAS,KAAK;EACd,IAAI,KAAK;EACV,EACD,sBACD;AAED,gCACE;EACE,KAAK,KAAK;EACV,MAAM,KAAK;EACX,MAAM,KAAK;EACX,KAAK,KAAK;EACV,gBAAgB,KAAK;EACtB,EACD,kBACD;CAED,MAAM,MAAM,SAAS,KAAK;CAC1B,MAAM,oBAAoB,KAAK,WAAW;CAC1C,MAAM,KAAK,oBAAoB,KAAK,IAAI;CAGxC,MAAM,gBAAgB,CAAC,GAAG,oBAAoB,GAAG,QAAQ,KAAK,MAAM,EAAE,CAAC;CAKvE,IAAI,kBAAkB,KAAK;AAC3B,KAAI;AACF,MAAI,CAAC,gBACH,mBAAkB,MAAM,kCACtB,gBACA,IACD;UAEI,KAAK;AAIZ,MAAI,KAAK,MACP,SAAQ,MAAM,0CAA0C,IAAI;;CAGhE,MAAM,EAAE,WAAW,MAAM,OAAO;CAChC,MAAM,SAAS,kBAAkB,OAAO,gBAAgB,GAAG;AAC3D,KAAI,UAAU,OAAO,QAAQ,kBAAkB;AAG7C,UAAQ,MACN,GAAG,eAAe,GAAG,kBAAkB,eAAe,gBAAgB,8CACvB,iBAAiB,+DACN,iBAAiB,cAC5E;AACD,UAAQ,KAAK,EAAE;;CAGjB,MAAM,eAAe,GAAG,eAAe,GAAG,mBAAmB;CAC7D,MAAM,EAAE,mBAAmB,MAAM,OAAO;CACxC,MAAM,WAAW,eAAe,IAAI,WAAW;EAC7C;EACA;EACA,GAAG;EACJ,CAAC;AAEF,KAAI,CAAC,SACH,OAAM,IAAI,MACR,0DAA0D,GAAG,IAC9D;CAGH,MAAM,EAAE,0BAA0B,MAAM,OAAO;AAC/C,uBAAsB,IAAI,SAAS;CAEnC,MAAM,EAAE,SAAS,KAAK,MAAM,YAAY;CACxC,MAAM,UAAU,GAAG,IAAI,GAAG,QAAQ,KAAK,IAAI;AAE3C,KAAI,KAAK,MACP,SAAQ,IAAI,6BAA6B,QAAQ;AAGnD,KAAI;AACF,WAAS,SAAS,EAAE,OAAO,WAAW,CAAC;UAChC,KAAK;EAGZ,MAAM,IAAI;AAIV,MAAI,OAAO,EAAE,WAAW,YAAY,CAAC,EAAE,OACrC,SAAQ,KAAK,EAAE,OAAO;AAExB,QAAM","debug_id":"a8fa3f98-459c-513d-a52e-b2e156cfb207"}
@@ -0,0 +1,4 @@
1
+ import { t as delegateInit } from "./delegate-init-BiHdTmaF.mjs";
2
+ export { delegateInit };
3
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="fda490f2-c9df-5061-a8af-11fd881c2df9")}catch(e){}}();
4
+ //# debugId=fda490f2-c9df-5061-a8af-11fd881c2df9
@@ -5,12 +5,12 @@
5
5
  * `bun run scripts/generate-commands-docs.ts` or `bun run src/cli.ts`).
6
6
  */
7
7
 
8
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="3646ae72-6a60-54da-8cd1-3968bddfb48b")}catch(e){}}();
8
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="e2358f09-76ed-53a8-80d6-3ca98286552c")}catch(e){}}();
9
9
  function getVersion() {
10
- return "6.2.3-dev.0";
10
+ return "6.2.3-dev.2";
11
11
  }
12
12
  //#endregion
13
13
  export { getVersion as t };
14
14
 
15
- //# sourceMappingURL=get-version-G0G6fFLl.mjs.map
16
- //# debugId=3646ae72-6a60-54da-8cd1-3968bddfb48b
15
+ //# sourceMappingURL=get-version-CKWHzzHh.mjs.map
16
+ //# debugId=e2358f09-76ed-53a8-80d6-3ca98286552c
@@ -1 +1 @@
1
- {"version":3,"file":"get-version-G0G6fFLl.mjs","sources":["../src/get-version.ts"],"sourcesContent":["declare const CLI_VERSION: string | undefined;\ndeclare const CLI_GIT_SHA: string | undefined;\n\n/**\n * Returns the CLI version string. Replaced inline by tsdown's `define` at\n * build time; falls back to env vars when running un-bundled (e.g. via\n * `bun run scripts/generate-commands-docs.ts` or `bun run src/cli.ts`).\n */\nexport function getVersion() {\n if (typeof CLI_VERSION !== \"undefined\") return CLI_VERSION;\n return (\n process.env.WORKSPACE_VERSION ||\n process.env.npm_package_version ||\n \"unknown\"\n );\n}\n\nexport function getGitHash() {\n if (typeof CLI_GIT_SHA !== \"undefined\") return CLI_GIT_SHA;\n return process.env.WORKSPACE_GIT_SHA || \"unknown\";\n}\n"],"names":[],"mappings":";;;;;;;;AAQA,SAAgB,aAAa;AACa,QAAA","debug_id":"3646ae72-6a60-54da-8cd1-3968bddfb48b"}
1
+ {"version":3,"file":"get-version-CKWHzzHh.mjs","sources":["../src/get-version.ts"],"sourcesContent":["declare const CLI_VERSION: string | undefined;\ndeclare const CLI_GIT_SHA: string | undefined;\n\n/**\n * Returns the CLI version string. Replaced inline by tsdown's `define` at\n * build time; falls back to env vars when running un-bundled (e.g. via\n * `bun run scripts/generate-commands-docs.ts` or `bun run src/cli.ts`).\n */\nexport function getVersion() {\n if (typeof CLI_VERSION !== \"undefined\") return CLI_VERSION;\n return (\n process.env.WORKSPACE_VERSION ||\n process.env.npm_package_version ||\n \"unknown\"\n );\n}\n\nexport function getGitHash() {\n if (typeof CLI_GIT_SHA !== \"undefined\") return CLI_GIT_SHA;\n return process.env.WORKSPACE_GIT_SHA || \"unknown\";\n}\n"],"names":[],"mappings":";;;;;;;;AAQA,SAAgB,aAAa;AACa,QAAA","debug_id":"e2358f09-76ed-53a8-80d6-3ca98286552c"}
@@ -1,8 +1,8 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="87829fab-6934-5627-aa03-050f4b43fe51")}catch(e){}}();
3
- import { t as getVersion } from "./get-version-G0G6fFLl.mjs";
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="c314f2ec-070a-5cb6-ad21-e712b3eaa232")}catch(e){}}();
3
+ import { t as getVersion } from "./get-version-CKWHzzHh.mjs";
4
4
  import { getPowerhouseProjectInfo } from "@powerhousedao/shared/clis";
5
- import spawn from "cross-spawn";
5
+ import spawn$1 from "cross-spawn";
6
6
  import { resolveCommand } from "package-manager-detector";
7
7
  //#region src/ph-cli.ts
8
8
  const PH_CLI_PACKAGE = "@powerhousedao/ph-cli";
@@ -29,7 +29,7 @@ async function executePhCliCommand(phCliCommand) {
29
29
  injectPnpmAllowBuilds(packageManager, resolved);
30
30
  }
31
31
  const { command, args } = resolved;
32
- const result = spawn.sync(command, args, {
32
+ const result = spawn$1.sync(command, args, {
33
33
  stdio: "inherit",
34
34
  cwd: projectPath ?? process.cwd()
35
35
  });
@@ -40,5 +40,5 @@ async function executePhCliCommand(phCliCommand) {
40
40
  //#endregion
41
41
  export { executePhCliCommand };
42
42
 
43
- //# sourceMappingURL=ph-cli-D42c_L7U.mjs.map
44
- //# debugId=87829fab-6934-5627-aa03-050f4b43fe51
43
+ //# sourceMappingURL=ph-cli-BxlV6SZ2.mjs.map
44
+ //# debugId=c314f2ec-070a-5cb6-ad21-e712b3eaa232
@@ -1 +1 @@
1
- {"version":3,"file":"ph-cli-D42c_L7U.mjs","sources":["../src/ph-cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { getPowerhouseProjectInfo } from \"@powerhousedao/shared/clis\";\nimport spawn from \"cross-spawn\";\nimport { resolveCommand } from \"package-manager-detector\";\nimport { getVersion } from \"./get-version.js\";\n\nconst PH_CLI_PACKAGE = \"@powerhousedao/ph-cli\";\n\n// Auth/identity commands write global state (~/.renown.json, ~/.npmrc), not a\n// project, so they run outside a project via dlx when no ph-cli is installed.\nconst PROJECT_OPTIONAL_COMMANDS = new Set([\n \"login\",\n \"logout\",\n \"registry-login\",\n]);\n\nexport async function executePhCliCommand(phCliCommand: string) {\n const forwardedArgs = process.argv.slice(3);\n const { projectPath, packageManager } = await getPowerhouseProjectInfo(\n undefined,\n { silent: true },\n );\n\n if (!projectPath && !PROJECT_OPTIONAL_COMMANDS.has(phCliCommand)) {\n throw new Error(\n `No Powerhouse project directory found, cannot run \\`ph ${phCliCommand}\\`.\\nTo create a local project, run \\`ph init\\`.\\nTo create a global project, run \\`ph setup-globals\\`.`,\n );\n }\n\n // In a project run the installed binary; otherwise dlx ph-cli pinned to this\n // ph-cmd version, falling back to `latest` when the version is unknown.\n const version = getVersion();\n const phCliTarget = projectPath\n ? \"ph-cli\"\n : `${PH_CLI_PACKAGE}@${version === \"unknown\" ? \"latest\" : version}`;\n const action = projectPath ? \"execute-local\" : \"execute\";\n\n const resolved = resolveCommand(packageManager, action, [\n phCliTarget,\n phCliCommand,\n ...forwardedArgs,\n ]);\n if (!resolved) {\n throw new Error(\n `Could not resolve a \"${action}\" command for package manager \"${packageManager}\" to run ph-cli. Supported package managers: npm, pnpm, yarn, bun.`,\n );\n }\n\n if (!projectPath) {\n const { injectPnpmAllowBuilds } =\n await import(\"@powerhousedao/shared/clis\");\n injectPnpmAllowBuilds(packageManager, resolved);\n }\n\n const { command, args } = resolved;\n // spawn (not a shell-joined string) so args with shell metacharacters — e.g.\n // `connect build --json '{\"a\":\"b\"}'` — survive intact. cross-spawn keeps that\n // guarantee on Windows too: `command` here is an npx/pnpm/yarn `.cmd` shim,\n // which node:child_process refuses to run without `shell: true` (spawn\n // EINVAL), and `shell: true` is exactly what would break those arguments.\n const result = spawn.sync(command, args, {\n stdio: \"inherit\",\n cwd: projectPath ?? process.cwd(),\n });\n if (result.error) throw result.error;\n if (result.signal) {\n throw new Error(`${command} terminated by signal ${result.signal}`);\n }\n if (typeof result.status === \"number\" && result.status !== 0) {\n process.exit(result.status);\n }\n}\n"],"names":[],"mappings":";;;;;;;AAMA,MAAM,iBAAiB;AAIvB,MAAM,4BAA4B,IAAI,IAAI;CACxC;CACA;CACA;CACD,CAAC;AAEF,eAAsB,oBAAoB,cAAsB;CAC9D,MAAM,gBAAgB,QAAQ,KAAK,MAAM,EAAE;CAC3C,MAAM,EAAE,aAAa,mBAAmB,MAAM,yBAC5C,KAAA,GACA,EAAE,QAAQ,MAAM,CACjB;AAED,KAAI,CAAC,eAAe,CAAC,0BAA0B,IAAI,aAAa,CAC9D,OAAM,IAAI,MACR,0DAA0D,aAAa,yGACxE;CAKH,MAAM,UAAU,YAAY;CAC5B,MAAM,cAAc,cAChB,WACA,GAAG,eAAe,GAAG,YAAY,YAAY,WAAW;CAC5D,MAAM,SAAS,cAAc,kBAAkB;CAE/C,MAAM,WAAW,eAAe,gBAAgB,QAAQ;EACtD;EACA;EACA,GAAG;EACJ,CAAC;AACF,KAAI,CAAC,SACH,OAAM,IAAI,MACR,wBAAwB,OAAO,iCAAiC,eAAe,oEAChF;AAGH,KAAI,CAAC,aAAa;EAChB,MAAM,EAAE,0BACN,MAAM,OAAO;AACf,wBAAsB,gBAAgB,SAAS;;CAGjD,MAAM,EAAE,SAAS,SAAS;CAM1B,MAAM,SAAS,MAAM,KAAK,SAAS,MAAM;EACvC,OAAO;EACP,KAAK,eAAe,QAAQ,KAAK;EAClC,CAAC;AACF,KAAI,OAAO,MAAO,OAAM,OAAO;AAC/B,KAAI,OAAO,OACT,OAAM,IAAI,MAAM,GAAG,QAAQ,wBAAwB,OAAO,SAAS;AAErE,KAAI,OAAO,OAAO,WAAW,YAAY,OAAO,WAAW,EACzD,SAAQ,KAAK,OAAO,OAAO","debug_id":"87829fab-6934-5627-aa03-050f4b43fe51"}
1
+ {"version":3,"file":"ph-cli-BxlV6SZ2.mjs","sources":["../src/ph-cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { getPowerhouseProjectInfo } from \"@powerhousedao/shared/clis\";\nimport spawn from \"cross-spawn\";\nimport { resolveCommand } from \"package-manager-detector\";\nimport { getVersion } from \"./get-version.js\";\n\nconst PH_CLI_PACKAGE = \"@powerhousedao/ph-cli\";\n\n// Auth/identity commands write global state (~/.renown.json, ~/.npmrc), not a\n// project, so they run outside a project via dlx when no ph-cli is installed.\nconst PROJECT_OPTIONAL_COMMANDS = new Set([\n \"login\",\n \"logout\",\n \"registry-login\",\n]);\n\nexport async function executePhCliCommand(phCliCommand: string) {\n const forwardedArgs = process.argv.slice(3);\n const { projectPath, packageManager } = await getPowerhouseProjectInfo(\n undefined,\n { silent: true },\n );\n\n if (!projectPath && !PROJECT_OPTIONAL_COMMANDS.has(phCliCommand)) {\n throw new Error(\n `No Powerhouse project directory found, cannot run \\`ph ${phCliCommand}\\`.\\nTo create a local project, run \\`ph init\\`.\\nTo create a global project, run \\`ph setup-globals\\`.`,\n );\n }\n\n // In a project run the installed binary; otherwise dlx ph-cli pinned to this\n // ph-cmd version, falling back to `latest` when the version is unknown.\n const version = getVersion();\n const phCliTarget = projectPath\n ? \"ph-cli\"\n : `${PH_CLI_PACKAGE}@${version === \"unknown\" ? \"latest\" : version}`;\n const action = projectPath ? \"execute-local\" : \"execute\";\n\n const resolved = resolveCommand(packageManager, action, [\n phCliTarget,\n phCliCommand,\n ...forwardedArgs,\n ]);\n if (!resolved) {\n throw new Error(\n `Could not resolve a \"${action}\" command for package manager \"${packageManager}\" to run ph-cli. Supported package managers: npm, pnpm, yarn, bun.`,\n );\n }\n\n if (!projectPath) {\n const { injectPnpmAllowBuilds } =\n await import(\"@powerhousedao/shared/clis\");\n injectPnpmAllowBuilds(packageManager, resolved);\n }\n\n const { command, args } = resolved;\n // spawn (not a shell-joined string) so args with shell metacharacters — e.g.\n // `connect build --json '{\"a\":\"b\"}'` — survive intact. cross-spawn keeps that\n // guarantee on Windows too: `command` here is an npx/pnpm/yarn `.cmd` shim,\n // which node:child_process refuses to run without `shell: true` (spawn\n // EINVAL), and `shell: true` is exactly what would break those arguments.\n const result = spawn.sync(command, args, {\n stdio: \"inherit\",\n cwd: projectPath ?? process.cwd(),\n });\n if (result.error) throw result.error;\n if (result.signal) {\n throw new Error(`${command} terminated by signal ${result.signal}`);\n }\n if (typeof result.status === \"number\" && result.status !== 0) {\n process.exit(result.status);\n }\n}\n"],"names":["spawn"],"mappings":";;;;;;;AAMA,MAAM,iBAAiB;AAIvB,MAAM,4BAA4B,IAAI,IAAI;CACxC;CACA;CACA;CACD,CAAC;AAEF,eAAsB,oBAAoB,cAAsB;CAC9D,MAAM,gBAAgB,QAAQ,KAAK,MAAM,EAAE;CAC3C,MAAM,EAAE,aAAa,mBAAmB,MAAM,yBAC5C,KAAA,GACA,EAAE,QAAQ,MAAM,CACjB;AAED,KAAI,CAAC,eAAe,CAAC,0BAA0B,IAAI,aAAa,CAC9D,OAAM,IAAI,MACR,0DAA0D,aAAa,yGACxE;CAKH,MAAM,UAAU,YAAY;CAC5B,MAAM,cAAc,cAChB,WACA,GAAG,eAAe,GAAG,YAAY,YAAY,WAAW;CAC5D,MAAM,SAAS,cAAc,kBAAkB;CAE/C,MAAM,WAAW,eAAe,gBAAgB,QAAQ;EACtD;EACA;EACA,GAAG;EACJ,CAAC;AACF,KAAI,CAAC,SACH,OAAM,IAAI,MACR,wBAAwB,OAAO,iCAAiC,eAAe,oEAChF;AAGH,KAAI,CAAC,aAAa;EAChB,MAAM,EAAE,0BACN,MAAM,OAAO;AACf,wBAAsB,gBAAgB,SAAS;;CAGjD,MAAM,EAAE,SAAS,SAAS;CAM1B,MAAM,SAASA,QAAM,KAAK,SAAS,MAAM;EACvC,OAAO;EACP,KAAK,eAAe,QAAQ,KAAK;EAClC,CAAC;AACF,KAAI,OAAO,MAAO,OAAM,OAAO;AAC/B,KAAI,OAAO,OACT,OAAM,IAAI,MAAM,GAAG,QAAQ,wBAAwB,OAAO,SAAS;AAErE,KAAI,OAAO,OAAO,WAAW,YAAY,OAAO,WAAW,EACzD,SAAQ,KAAK,OAAO,OAAO","debug_id":"c314f2ec-070a-5cb6-ad21-e712b3eaa232"}
@@ -1,11 +1,14 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="8fd02ae1-0c73-50f0-847b-abb14891c6f3")}catch(e){}}();
3
- import { t as getVersion } from "./get-version-G0G6fFLl.mjs";
4
- import { t as delegateInit } from "./delegate-init-B3_b7484.mjs";
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="83556561-3410-5523-ae16-bd17b5ed604c")}catch(e){}}();
3
+ import { t as getVersion } from "./get-version-CKWHzzHh.mjs";
4
+ import { i as setCacheCurrent, n as getStream, t as PH_CMD_STREAMS } from "./version-check-BxMITre2.mjs";
5
+ import { t as delegateInit } from "./delegate-init-BiHdTmaF.mjs";
6
+ import { readFile, realpath } from "node:fs/promises";
7
+ import path from "node:path";
8
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
9
+ import { spawn } from "cross-spawn";
5
10
  import { boolean, command, flag, oneOf, option, optional, positional, run as run$1, string, subcommands } from "cmd-ts";
6
11
  import { debugArgs, initArgs, phCliHelpCommands } from "@powerhousedao/shared/clis/args";
7
- import { existsSync, readFileSync, writeFileSync } from "node:fs";
8
- import path from "node:path";
9
12
  import { ALL_POWERHOUSE_DEPENDENCIES } from "@powerhousedao/shared/constants";
10
13
  //#region src/commands/init.ts
11
14
  /**
@@ -24,6 +27,188 @@ const init = command({
24
27
  }
25
28
  });
26
29
  //#endregion
30
+ //#region src/utils/self-update.ts
31
+ const PACKAGE_NAME = "ph-cmd";
32
+ function normalizePath(p) {
33
+ return p.replace(/\\/g, "/").replace(/\/+$/, "");
34
+ }
35
+ /**
36
+ * Which package manager owns the running global install, resolved from the
37
+ * real path of the running bundle (the bin entry is a symlink; the ESM
38
+ * loader resolves it). Path signatures:
39
+ * pnpm: <global>/node_modules/.pnpm/ph-cmd@<v>/node_modules/ph-cmd/...
40
+ * bun: <home>/.bun/install/global/node_modules/ph-cmd/...
41
+ * yarn: <global>/yarn/global/node_modules/ph-cmd/... (yarn classic)
42
+ * npm: <prefix>/lib/node_modules/ph-cmd/... (any plain node_modules)
43
+ * A source checkout (<repo>/clis/ph-cmd/dist/cli.mjs) and any unrecognized
44
+ * layout are refused with a reason instead of guessing.
45
+ */
46
+ function detectGlobalInstall(rawPath) {
47
+ const real = normalizePath(rawPath);
48
+ if (real.includes("/clis/ph-cmd/")) return {
49
+ pm: null,
50
+ reason: "source-checkout"
51
+ };
52
+ const pkgDir = real.endsWith(`/dist/cli.mjs`) ? real.slice(0, -13) : null;
53
+ if (!pkgDir || !pkgDir.endsWith(`/${PACKAGE_NAME}`)) return {
54
+ pm: null,
55
+ reason: "unknown"
56
+ };
57
+ if (real.includes(`/node_modules/.pnpm/${PACKAGE_NAME}@`)) return {
58
+ pm: "pnpm",
59
+ pkgRoot: pkgDir
60
+ };
61
+ if (real.includes("/.bun/install/global/node_modules/")) return {
62
+ pm: "bun",
63
+ pkgRoot: pkgDir
64
+ };
65
+ if (real.includes("/yarn/global/node_modules/")) return {
66
+ pm: "yarn",
67
+ pkgRoot: pkgDir
68
+ };
69
+ if (real.includes("/node_modules/")) return {
70
+ pm: "npm",
71
+ pkgRoot: pkgDir
72
+ };
73
+ return {
74
+ pm: null,
75
+ reason: "unknown"
76
+ };
77
+ }
78
+ const UPDATE_COMMANDS = {
79
+ npm: {
80
+ command: (spec) => `npm install -g ${spec}`,
81
+ argv: (spec) => [
82
+ "npm",
83
+ "install",
84
+ "-g",
85
+ spec
86
+ ]
87
+ },
88
+ pnpm: {
89
+ command: (spec) => `pnpm add -g ${spec}`,
90
+ argv: (spec) => [
91
+ "pnpm",
92
+ "add",
93
+ "-g",
94
+ spec
95
+ ]
96
+ },
97
+ bun: {
98
+ command: (spec) => `bun add -g ${spec}`,
99
+ argv: (spec) => [
100
+ "bun",
101
+ "add",
102
+ "-g",
103
+ spec
104
+ ]
105
+ },
106
+ yarn: {
107
+ command: (spec) => `yarn global add ${spec}`,
108
+ argv: (spec) => [
109
+ "yarn",
110
+ "global",
111
+ "add",
112
+ spec
113
+ ]
114
+ }
115
+ };
116
+ /** Human-readable update command (for error hints). */
117
+ function updateCommand(pm, tag) {
118
+ return UPDATE_COMMANDS[pm].command(`${PACKAGE_NAME}@${tag}`);
119
+ }
120
+ /** Exact argv used to spawn the package manager. */
121
+ function updateArgv(pm, tag) {
122
+ return UPDATE_COMMANDS[pm].argv(`${PACKAGE_NAME}@${tag}`);
123
+ }
124
+ function defaultSpawner(argv, opts) {
125
+ const { promise, resolve, reject } = Promise.withResolvers();
126
+ const child = spawn(argv[0], argv.slice(1), opts);
127
+ child.on("close", (code) => code === 0 ? resolve() : reject(/* @__PURE__ */ new Error(`${argv[0]} exited with code ${code}`)));
128
+ child.on("error", reject);
129
+ return promise;
130
+ }
131
+ /**
132
+ * Upgrade the global ph-cmd install to `tag` (default: the running build's
133
+ * stream) using the owning package manager, then report the new version.
134
+ * Never throws: refusals and failures come back as `{ ok: false }` so the
135
+ * command layer owns the exit code.
136
+ */
137
+ async function runSelfUpdate(opts) {
138
+ const { spawner = defaultSpawner, readFile: readFile$1 = (p) => readFile(p, "utf-8"), stdout = (line) => console.log(line), stderr = (line) => console.error(line), refreshCache } = opts.deps ?? {};
139
+ const detection = detectGlobalInstall(opts.realPath);
140
+ if (detection.pm === null) {
141
+ if (detection.reason === "source-checkout") {
142
+ const message = "ph is running from a source checkout; self-update only applies to global installs.";
143
+ stderr(message);
144
+ return {
145
+ ok: false,
146
+ message
147
+ };
148
+ }
149
+ const manual = Object.keys(UPDATE_COMMANDS).map((pm) => ` ${updateCommand(pm, "latest")}`).join("\n");
150
+ const message = `Couldn't determine how ph was installed (${opts.realPath}). Update manually:\n${manual}`;
151
+ stderr(message);
152
+ return {
153
+ ok: false,
154
+ message
155
+ };
156
+ }
157
+ const tag = opts.tag ?? getStream(opts.currentVersion);
158
+ stdout(`Updating ph-cmd via ${detection.pm} (${updateCommand(detection.pm, tag)})...`);
159
+ try {
160
+ await spawner(updateArgv(detection.pm, tag), { stdio: "inherit" });
161
+ } catch (error) {
162
+ const message = `ph-cmd update failed via ${detection.pm}. Try manually: ${updateCommand(detection.pm, tag)}`;
163
+ stderr(message);
164
+ if (error instanceof Error) stderr(error.message);
165
+ return {
166
+ ok: false,
167
+ message
168
+ };
169
+ }
170
+ let to = "unknown";
171
+ try {
172
+ const pkg = JSON.parse(await readFile$1(`${detection.pkgRoot}/package.json`));
173
+ if (typeof pkg.version === "string") to = pkg.version;
174
+ } catch {}
175
+ stdout(`Updated ph-cmd from ${opts.currentVersion} to ${to}. The new version takes effect on your next 'ph' run.`);
176
+ await refreshCache?.(to).catch(() => {});
177
+ return {
178
+ ok: true,
179
+ from: opts.currentVersion,
180
+ to
181
+ };
182
+ }
183
+ //#endregion
184
+ //#region src/commands/self-update.ts
185
+ const selfUpdate = command({
186
+ name: "self-update",
187
+ description: "Update the globally installed ph to the newest version of its release stream",
188
+ args: {
189
+ tag: option({
190
+ type: optional(string),
191
+ long: "tag",
192
+ short: "t",
193
+ description: `dist-tag to install (defaults to the running build's stream; e.g. ${PH_CMD_STREAMS.join(", ")})`
194
+ }),
195
+ ...debugArgs
196
+ },
197
+ handler: async (args) => {
198
+ if (args.debug) console.log({ args });
199
+ const entry = process.argv[1];
200
+ const realPath = entry ? await realpath(entry) : import.meta.url.replace(/^file:\/\//, "");
201
+ const result = await runSelfUpdate({
202
+ currentVersion: getVersion(),
203
+ tag: args.tag,
204
+ realPath
205
+ });
206
+ if (!result.ok) process.exit(1);
207
+ await setCacheCurrent(result.to);
208
+ process.exit(0);
209
+ }
210
+ });
211
+ //#endregion
27
212
  //#region src/commands/setup-globals.ts
28
213
  const PH_GLOBAL_PACKAGE_NAME = "ph-global";
29
214
  /**
@@ -63,7 +248,7 @@ const setupGlobals = command({
63
248
  }
64
249
  console.log("📦 Initializing global project...");
65
250
  process.chdir(HOME_DIR);
66
- const { delegateInit } = await import("./delegate-init-4NaG2HDm.mjs");
251
+ const { delegateInit } = await import("./delegate-init-DwTgkpW-.mjs");
67
252
  await delegateInit(args, ["--name", PH_GLOBAL_DIR_NAME]);
68
253
  fixGlobalPackageName();
69
254
  console.log(`🚀 Global project initialized successfully: ${POWERHOUSE_GLOBAL_DIR}`);
@@ -74,7 +259,7 @@ const setupGlobals = command({
74
259
  //#region src/commands/update.ts
75
260
  const update = command({
76
261
  name: "update",
77
- description: "Update your powerhouse dependencies to their latest tagged version",
262
+ description: "Update your Powerhouse dependencies and installed packages to their latest versions",
78
263
  args: {
79
264
  skipInstall: flag({
80
265
  type: optional(boolean),
@@ -82,18 +267,26 @@ const update = command({
82
267
  short: "s",
83
268
  description: "Skip running `install` with your package manager"
84
269
  }),
270
+ updatePackages: flag({
271
+ type: optional(boolean),
272
+ long: "update-packages",
273
+ description: "Auto-update installed packages (powerhouse.config.json) to their newest same-major version"
274
+ }),
85
275
  ...debugArgs
86
276
  },
87
277
  handler: async (args) => {
88
- const { skipInstall, debug } = args;
278
+ const { skipInstall, updatePackages, debug } = args;
89
279
  if (debug) console.log({ args });
90
280
  console.log(`\n▶️ Updating Powerhouse dependencies...\n`);
91
- const [{ default: chalk }, { readPackage }, { writePackage }, { getTagFromVersion, logVersionUpdate, parsePackageVersion, runCmd }] = await Promise.all([
281
+ const [{ default: chalk }, { readPackage }, { writePackage }, { getTagFromVersion, logVersionUpdate, parsePackageVersion, runCmd }, { resolveRegistryUrl }, { updateInstalledPackages }] = await Promise.all([
92
282
  import("chalk"),
93
283
  import("read-pkg"),
94
284
  import("write-package"),
95
- import("@powerhousedao/shared/clis")
285
+ import("@powerhousedao/shared/clis"),
286
+ import("@powerhousedao/shared/registry"),
287
+ import("./update-packages-BTDhXqEj.mjs")
96
288
  ]);
289
+ const registryUrl = resolveRegistryUrl({ projectPath: process.cwd() });
97
290
  const packageJson = await readPackage();
98
291
  if (packageJson.dependencies) {
99
292
  for (const [name, version] of Object.entries(packageJson.dependencies)) if (version && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {
@@ -153,9 +346,15 @@ const update = command({
153
346
  }
154
347
  await writePackage(packageJson);
155
348
  console.log(chalk.green(`\n✅ Project updated successfully\n`));
156
- if (skipInstall) return;
157
349
  const { detect } = await import("package-manager-detector/detect");
158
350
  const packageManager = await detect();
351
+ await updateInstalledPackages({
352
+ registryUrl,
353
+ auto: updatePackages ?? false,
354
+ skipInstall: skipInstall ?? false,
355
+ packageManager
356
+ });
357
+ if (skipInstall) return;
159
358
  if (!packageManager) throw new Error(`❌ Failed to detect your package manager. Run install manually.`);
160
359
  console.log(`▶️ Installing updated dependencies with \`${packageManager.agent}\`\n`);
161
360
  runCmd(`${packageManager.agent} install`);
@@ -339,6 +538,7 @@ const ph = subcommands({
339
538
  init,
340
539
  use,
341
540
  update,
541
+ "self-update": selfUpdate,
342
542
  "setup-globals": setupGlobals,
343
543
  "use-local": useLocal,
344
544
  ...phCliHelpCommands
@@ -352,5 +552,5 @@ async function run(args) {
352
552
  //#endregion
353
553
  export { run };
354
554
 
355
- //# sourceMappingURL=run-DX-j7-DZ.mjs.map
356
- //# debugId=8fd02ae1-0c73-50f0-847b-abb14891c6f3
555
+ //# sourceMappingURL=run-0gjMNmbN.mjs.map
556
+ //# debugId=83556561-3410-5523-ae16-bd17b5ed604c
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-0gjMNmbN.mjs","sources":["../src/commands/init.ts","../src/utils/self-update.ts","../src/commands/self-update.ts","../src/commands/setup-globals.ts","../src/commands/update.ts","../src/commands/use-local.ts","../src/commands/use.ts","../src/commands/ph.ts","../src/run.ts"],"sourcesContent":["import { initArgs } from \"@powerhousedao/shared/clis/args\";\nimport { command } from \"cmd-ts\";\nimport { delegateInit } from \"../utils/delegate-init.js\";\n\n/**\n * Delegates `ph init` to the appropriate version of `@powerhousedao/ph-cli`.\n * This ensures the init logic (boilerplate, codegen) always matches the\n * ph-cli version being installed in the new project.\n */\nexport const init = command({\n name: \"init\",\n description: \"Initialize a new project\",\n args: initArgs,\n handler: async (args) => {\n if (args.debug) {\n console.log({ args });\n }\n await delegateInit(args);\n process.exit(0);\n },\n});\n","import { spawn as spawnChild } from \"cross-spawn\";\nimport { readFile as readFileAsync } from \"node:fs/promises\";\n\nimport { getStream } from \"./version-check.js\";\n\nexport type GlobalPackageManager = \"npm\" | \"pnpm\" | \"bun\" | \"yarn\";\n\nexport type InstallDetection =\n | { pm: GlobalPackageManager; pkgRoot: string }\n | { pm: null; reason: \"source-checkout\" | \"unknown\" };\n\nconst PACKAGE_NAME = \"ph-cmd\";\n\nfunction normalizePath(p: string): string {\n return p.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n}\n\n/**\n * Which package manager owns the running global install, resolved from the\n * real path of the running bundle (the bin entry is a symlink; the ESM\n * loader resolves it). Path signatures:\n * pnpm: <global>/node_modules/.pnpm/ph-cmd@<v>/node_modules/ph-cmd/...\n * bun: <home>/.bun/install/global/node_modules/ph-cmd/...\n * yarn: <global>/yarn/global/node_modules/ph-cmd/... (yarn classic)\n * npm: <prefix>/lib/node_modules/ph-cmd/... (any plain node_modules)\n * A source checkout (<repo>/clis/ph-cmd/dist/cli.mjs) and any unrecognized\n * layout are refused with a reason instead of guessing.\n */\nexport function detectGlobalInstall(rawPath: string): InstallDetection {\n const real = normalizePath(rawPath);\n if (real.includes(\"/clis/ph-cmd/\")) {\n return { pm: null, reason: \"source-checkout\" };\n }\n const pkgDir = real.endsWith(`/dist/cli.mjs`)\n ? real.slice(0, -\"/dist/cli.mjs\".length)\n : null;\n if (!pkgDir || !pkgDir.endsWith(`/${PACKAGE_NAME}`)) {\n return { pm: null, reason: \"unknown\" };\n }\n if (real.includes(`/node_modules/.pnpm/${PACKAGE_NAME}@`)) {\n return { pm: \"pnpm\", pkgRoot: pkgDir };\n }\n if (real.includes(\"/.bun/install/global/node_modules/\")) {\n return { pm: \"bun\", pkgRoot: pkgDir };\n }\n if (real.includes(\"/yarn/global/node_modules/\")) {\n return { pm: \"yarn\", pkgRoot: pkgDir };\n }\n if (real.includes(\"/node_modules/\")) {\n return { pm: \"npm\", pkgRoot: pkgDir };\n }\n return { pm: null, reason: \"unknown\" };\n}\n\nconst UPDATE_COMMANDS: Record<\n GlobalPackageManager,\n { command: (spec: string) => string; argv: (spec: string) => string[] }\n> = {\n npm: {\n command: (spec) => `npm install -g ${spec}`,\n argv: (spec) => [\"npm\", \"install\", \"-g\", spec],\n },\n pnpm: {\n command: (spec) => `pnpm add -g ${spec}`,\n argv: (spec) => [\"pnpm\", \"add\", \"-g\", spec],\n },\n bun: {\n command: (spec) => `bun add -g ${spec}`,\n argv: (spec) => [\"bun\", \"add\", \"-g\", spec],\n },\n yarn: {\n command: (spec) => `yarn global add ${spec}`,\n argv: (spec) => [\"yarn\", \"global\", \"add\", spec],\n },\n};\n\n/** Human-readable update command (for error hints). */\nexport function updateCommand(pm: GlobalPackageManager, tag: string): string {\n return UPDATE_COMMANDS[pm].command(`${PACKAGE_NAME}@${tag}`);\n}\n\n/** Exact argv used to spawn the package manager. */\nexport function updateArgv(pm: GlobalPackageManager, tag: string): string[] {\n return UPDATE_COMMANDS[pm].argv(`${PACKAGE_NAME}@${tag}`);\n}\n\nexport type SelfUpdateDeps = {\n /** Runs a full argv (program first); rejects on non-zero exit. */\n spawner?: (argv: string[], opts: { stdio: \"inherit\" }) => Promise<void>;\n readFile?: (path: string) => Promise<string>;\n stdout?: (line: string) => void;\n stderr?: (line: string) => void;\n /** called with the new version after a successful update (clears the notice). */\n refreshCache?: (newVersion: string) => Promise<void>;\n};\n\nexport type SelfUpdateResult =\n | { ok: true; from: string; to: string }\n | { ok: false; message: string };\n\nfunction defaultSpawner(\n argv: string[],\n opts: { stdio: \"inherit\" },\n): Promise<void> {\n const { promise, resolve, reject } = Promise.withResolvers<void>();\n const child = spawnChild(argv[0], argv.slice(1), opts);\n child.on(\"close\", (code) =>\n code === 0\n ? resolve()\n : reject(new Error(`${argv[0]} exited with code ${code}`)),\n );\n child.on(\"error\", reject);\n return promise;\n}\n\n/**\n * Upgrade the global ph-cmd install to `tag` (default: the running build's\n * stream) using the owning package manager, then report the new version.\n * Never throws: refusals and failures come back as `{ ok: false }` so the\n * command layer owns the exit code.\n */\nexport async function runSelfUpdate(opts: {\n currentVersion: string;\n tag?: string;\n realPath: string;\n deps?: SelfUpdateDeps;\n}): Promise<SelfUpdateResult> {\n const {\n spawner = defaultSpawner,\n readFile = (p: string) => readFileAsync(p, \"utf-8\"),\n stdout = (line: string) => console.log(line),\n stderr = (line: string) => console.error(line),\n refreshCache,\n } = opts.deps ?? {};\n\n const detection = detectGlobalInstall(opts.realPath);\n if (detection.pm === null) {\n if (detection.reason === \"source-checkout\") {\n const message =\n \"ph is running from a source checkout; self-update only applies to global installs.\";\n stderr(message);\n return { ok: false, message };\n }\n const manual = (Object.keys(UPDATE_COMMANDS) as GlobalPackageManager[])\n .map((pm) => ` ${updateCommand(pm, \"latest\")}`)\n .join(\"\\n\");\n const message = `Couldn't determine how ph was installed (${opts.realPath}). Update manually:\\n${manual}`;\n stderr(message);\n return { ok: false, message };\n }\n\n const tag = opts.tag ?? getStream(opts.currentVersion);\n stdout(\n `Updating ph-cmd via ${detection.pm} (${updateCommand(detection.pm, tag)})...`,\n );\n try {\n await spawner(updateArgv(detection.pm, tag), { stdio: \"inherit\" });\n } catch (error: unknown) {\n const message = `ph-cmd update failed via ${detection.pm}. Try manually: ${updateCommand(detection.pm, tag)}`;\n stderr(message);\n if (error instanceof Error) stderr(error.message);\n return { ok: false, message };\n }\n\n let to = \"unknown\";\n try {\n const pkg = JSON.parse(\n await readFile(`${detection.pkgRoot}/package.json`),\n ) as { version?: unknown };\n if (typeof pkg.version === \"string\") to = pkg.version;\n } catch {\n // leave \"unknown\" — the PM already printed its own result\n }\n stdout(\n `Updated ph-cmd from ${opts.currentVersion} to ${to}. The new version takes effect on your next 'ph' run.`,\n );\n await refreshCache?.(to).catch(() => {});\n return { ok: true, from: opts.currentVersion, to };\n}\n","import { debugArgs } from \"@powerhousedao/shared/clis/args\";\nimport { command, optional, option, string } from \"cmd-ts\";\nimport { realpath } from \"node:fs/promises\";\nimport { PH_CMD_STREAMS, setCacheCurrent } from \"../utils/version-check.js\";\nimport { runSelfUpdate } from \"../utils/self-update.js\";\nimport { getVersion } from \"../get-version.js\";\n\nexport const selfUpdate = command({\n name: \"self-update\",\n description:\n \"Update the globally installed ph to the newest version of its release stream\",\n args: {\n tag: option({\n type: optional(string),\n long: \"tag\",\n short: \"t\",\n description: `dist-tag to install (defaults to the running build's stream; e.g. ${PH_CMD_STREAMS.join(\n \", \",\n )})`,\n }),\n ...debugArgs,\n },\n handler: async (args) => {\n if (args.debug) {\n console.log({ args });\n }\n // The real path of the running bundle identifies the global install\n // (and its package manager). argv[1] is the entry script; the ESM\n // loader already resolved symlinks, realpath is belt-and-braces.\n const entry = process.argv[1];\n const realPath = entry\n ? await realpath(entry)\n : import.meta.url.replace(/^file:\\/\\//, \"\");\n const result = await runSelfUpdate({\n currentVersion: getVersion(),\n tag: args.tag,\n realPath,\n });\n if (!result.ok) {\n process.exit(1);\n }\n // Quiet the notice on the next run: the new version is now current.\n await setCacheCurrent(result.to);\n process.exit(0);\n },\n});\n","import { initArgs } from \"@powerhousedao/shared/clis/args\";\nimport { command } from \"cmd-ts\";\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\nconst PH_GLOBAL_PACKAGE_NAME = \"ph-global\";\n\n/**\n * `ph setup-globals` bootstraps the `~/.ph` project. It's the same flow as\n * `ph init` with `--name .ph` from the user's home directory, plus a\n * post-step that renames the package.json to `ph-global` (since `.ph` is\n * an invalid npm name).\n */\nexport const setupGlobals = command({\n name: \"setup-globals\",\n description: \"Initialize a new global project\",\n args: initArgs,\n handler: async (args) => {\n if (args.debug) {\n console.log({ args });\n }\n\n const { HOME_DIR, PH_GLOBAL_DIR_NAME, POWERHOUSE_GLOBAL_DIR } =\n await import(\"@powerhousedao/shared/clis\");\n\n /**\n * Fix the package.json `name` field for the global project — `.ph` is a\n * valid directory name but not a valid npm package name (vite + npm\n * reject names starting with a dot). We let `ph init` create the project\n * as `.ph` and then rename it here to `ph-global`.\n */\n const fixGlobalPackageName = (): void => {\n const packageJsonPath = path.join(POWERHOUSE_GLOBAL_DIR, \"package.json\");\n if (!existsSync(packageJsonPath)) return;\n try {\n const packageJson = JSON.parse(\n readFileSync(packageJsonPath, \"utf-8\"),\n ) as { name?: string };\n if (packageJson.name?.startsWith(\".\")) {\n packageJson.name = PH_GLOBAL_PACKAGE_NAME;\n writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));\n }\n } catch {\n // Ignore parse/write failures — leaves the file untouched.\n }\n };\n\n // The directory itself can exist without the project being bootstrapped —\n // telemetry writes `~/.ph/telemetry.json` early on. Use the presence of\n // `package.json` as the real \"is initialized\" signal.\n const globalPackageJson = path.join(POWERHOUSE_GLOBAL_DIR, \"package.json\");\n if (existsSync(globalPackageJson)) {\n // Repair-in-place: an older bootstrap may have left `name: \".ph\"` in\n // package.json, which breaks vite/npm. Fix it on every invocation.\n fixGlobalPackageName();\n console.log(`📦 Using global project: ${POWERHOUSE_GLOBAL_DIR}`);\n process.exit(0);\n }\n\n console.log(\"📦 Initializing global project...\");\n process.chdir(HOME_DIR);\n const { delegateInit } = await import(\"../utils/delegate-init.js\");\n await delegateInit(args, [\"--name\", PH_GLOBAL_DIR_NAME]);\n fixGlobalPackageName();\n console.log(\n `🚀 Global project initialized successfully: ${POWERHOUSE_GLOBAL_DIR}`,\n );\n process.exit(0);\n },\n});\n","import { debugArgs } from \"@powerhousedao/shared/clis/args\";\nimport { ALL_POWERHOUSE_DEPENDENCIES } from \"@powerhousedao/shared/constants\";\nimport { boolean, command, flag, optional } from \"cmd-ts\";\n\nexport const update = command({\n name: \"update\",\n description:\n \"Update your Powerhouse dependencies and installed packages to their latest versions\",\n args: {\n skipInstall: flag({\n type: optional(boolean),\n long: \"skip-install\",\n short: \"s\",\n description: \"Skip running `install` with your package manager\",\n }),\n updatePackages: flag({\n type: optional(boolean),\n long: \"update-packages\",\n description:\n \"Auto-update installed packages (powerhouse.config.json) to their newest same-major version\",\n }),\n ...debugArgs,\n },\n handler: async (args) => {\n const { skipInstall, updatePackages, debug } = args;\n if (debug) {\n console.log({ args });\n }\n console.log(`\\n▶️ Updating Powerhouse dependencies...\\n`);\n const [\n { default: chalk },\n { readPackage },\n { writePackage },\n { getTagFromVersion, logVersionUpdate, parsePackageVersion, runCmd },\n { resolveRegistryUrl },\n { updateInstalledPackages },\n ] = await Promise.all([\n import(\"chalk\"),\n import(\"read-pkg\"),\n import(\"write-package\"),\n import(\"@powerhousedao/shared/clis\"),\n import(\"@powerhousedao/shared/registry\"),\n import(\"./update-packages.js\"),\n ]);\n const registryUrl = resolveRegistryUrl({ projectPath: process.cwd() });\n const packageJson = await readPackage();\n\n if (packageJson.dependencies) {\n for (const [name, version] of Object.entries(packageJson.dependencies)) {\n if (version && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {\n const tag = getTagFromVersion(version);\n const newVersion = await parsePackageVersion({ name, tag });\n packageJson.dependencies[name] = newVersion;\n logVersionUpdate({\n name,\n version,\n newVersion,\n });\n }\n }\n }\n\n if (packageJson.devDependencies) {\n for (const [name, version] of Object.entries(\n packageJson.devDependencies,\n )) {\n if (version && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {\n const tag = getTagFromVersion(version);\n const newVersion = await parsePackageVersion({ name, tag });\n packageJson.devDependencies[name] = newVersion;\n logVersionUpdate({\n name,\n version,\n newVersion,\n });\n }\n }\n }\n\n if (packageJson.optionalDependencies) {\n for (const [name, version] of Object.entries(\n packageJson.optionalDependencies,\n )) {\n if (version && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {\n const tag = getTagFromVersion(version);\n const newVersion = await parsePackageVersion({ name, tag });\n packageJson.optionalDependencies[name] = newVersion;\n logVersionUpdate({\n name,\n version,\n newVersion,\n });\n }\n }\n }\n\n if (packageJson.peerDependencies) {\n for (const [name, version] of Object.entries(\n packageJson.peerDependencies,\n )) {\n if (version && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {\n const tag = getTagFromVersion(version);\n const newVersion = await parsePackageVersion({ name, tag });\n packageJson.peerDependencies[name] = newVersion;\n logVersionUpdate({\n name,\n version,\n newVersion,\n });\n }\n }\n }\n\n await writePackage(packageJson);\n\n console.log(chalk.green(`\\n✅ Project updated successfully\\n`));\n\n // Detect the package manager once; it backs the install below and the\n // update of `local` (node_modules) installed packages.\n const { detect } = await import(\"package-manager-detector/detect\");\n const packageManager = await detect();\n\n await updateInstalledPackages({\n registryUrl,\n auto: updatePackages ?? false,\n skipInstall: skipInstall ?? false,\n packageManager,\n });\n\n if (skipInstall) return;\n\n if (!packageManager) {\n throw new Error(\n `❌ Failed to detect your package manager. Run install manually.`,\n );\n }\n console.log(\n `▶️ Installing updated dependencies with \\`${packageManager.agent}\\`\\n`,\n );\n runCmd(`${packageManager.agent} install`);\n process.exit(0);\n },\n});\n","import { debugArgs } from \"@powerhousedao/shared/clis/args\";\nimport {\n boolean,\n command,\n flag,\n option,\n optional,\n positional,\n string,\n} from \"cmd-ts\";\n\nexport const useLocal = command({\n name: \"use-local\",\n description:\n \"Use your local `powerhouse` monorepo dependencies the current project.\",\n args: {\n monorepoPathPositional: positional({\n type: optional(string),\n displayName: \"monorepo path\",\n description:\n \"Path to your local powerhouse monorepo relative to this project\",\n }),\n monorepoPathOption: option({\n type: optional(string),\n long: \"path\",\n short: \"p\",\n description:\n \"Path to your local powerhouse monorepo relative to this project\",\n }),\n skipInstall: flag({\n type: optional(boolean),\n long: \"skip-install\",\n short: \"s\",\n description: \"Skip running `install` with `pnpm`\",\n }),\n ...debugArgs,\n },\n handler: async (args) => {\n const { monorepoPathPositional, monorepoPathOption, skipInstall, debug } =\n args;\n if (debug) {\n console.log({ args });\n }\n const monorepoPath = monorepoPathPositional ?? monorepoPathOption;\n\n if (!monorepoPath) {\n throw new Error(\n \"❌ Please provide the path to your local powerhouse monorepo.\",\n );\n }\n\n const { runUseLocal } = await import(\"@powerhousedao/shared/clis\");\n await runUseLocal(monorepoPath, skipInstall);\n process.exit(0);\n },\n});\n","import { debugArgs } from \"@powerhousedao/shared/clis/args\";\nimport { ALL_POWERHOUSE_DEPENDENCIES } from \"@powerhousedao/shared/constants\";\nimport {\n boolean,\n command,\n flag,\n oneOf,\n option,\n optional,\n positional,\n run,\n string,\n} from \"cmd-ts\";\n\nexport const use = command({\n name: \"use\",\n description: \"Specify the release version of Powerhouse dependencies to use.\",\n args: {\n tagPositional: positional({\n type: optional(oneOf([\"latest\", \"staging\", \"dev\", \"rc\"])),\n displayName: \"tag\",\n description: `Specify the release tag to use for your project. Can be one of: \"latest\", \"staging\", \"dev\", or \"rc\".`,\n }),\n tagOption: option({\n type: optional(oneOf([\"latest\", \"staging\", \"dev\", \"rc\"])),\n long: \"tag\",\n short: \"t\",\n description: `Specify the release tag to use for your project. Can be one of: \"latest\", \"staging\", \"dev\", or \"rc\".`,\n }),\n version: option({\n type: optional(string),\n long: \"version\",\n short: \"v\",\n description:\n \"Specify the exact semver release version to use for your project.\",\n }),\n skipInstall: flag({\n type: optional(boolean),\n long: \"skip-install\",\n short: \"s\",\n description: \"Skip running `install` with your package manager\",\n }),\n ...debugArgs,\n },\n handler: async (args) => {\n const { tagPositional, tagOption, version, skipInstall, debug } = args;\n if (debug) {\n console.log({ args });\n }\n const tag = tagPositional ?? tagOption;\n const {\n handleMutuallyExclusiveOptions,\n logVersionUpdate,\n parsePackageVersion,\n runCmd,\n } = await import(\"@powerhousedao/shared/clis\");\n handleMutuallyExclusiveOptions({ tag, version }, \"versioning strategy\");\n\n if (!tag && !version) {\n throw new Error(\n \"Please specify either a release tag or a version to use.\",\n );\n }\n\n const [\n { default: chalk },\n { readPackage },\n { writePackage },\n { clean, valid },\n ] = await Promise.all([\n import(\"chalk\"),\n import(\"read-pkg\"),\n import(\"write-package\"),\n import(\"semver\"),\n ]);\n\n if (version && !valid(clean(version))) {\n throw new Error(`❌ Invalid version: ${chalk.bold(version)}`);\n }\n\n console.log(\n `▶️ Updating project to use ${chalk.bold(version ?? tag)}...\\n`,\n );\n\n const packageJson = await readPackage();\n\n if (packageJson.dependencies) {\n for (const [name, existingVersion] of Object.entries(\n packageJson.dependencies,\n )) {\n if (existingVersion && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {\n const newVersion = await parsePackageVersion({ name, tag, version });\n packageJson.dependencies[name] = newVersion;\n logVersionUpdate({\n name,\n version: existingVersion,\n newVersion,\n });\n }\n }\n }\n\n if (packageJson.devDependencies) {\n for (const [name, existingVersion] of Object.entries(\n packageJson.devDependencies,\n )) {\n if (existingVersion && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {\n const newVersion = await parsePackageVersion({ name, tag, version });\n packageJson.devDependencies[name] = newVersion;\n logVersionUpdate({\n name,\n version: existingVersion,\n newVersion,\n });\n }\n }\n }\n\n if (packageJson.optionalDependencies) {\n for (const [name, existingVersion] of Object.entries(\n packageJson.optionalDependencies,\n )) {\n if (existingVersion && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {\n const newVersion = await parsePackageVersion({ name, tag, version });\n packageJson.optionalDependencies[name] = newVersion;\n logVersionUpdate({\n name,\n version: existingVersion,\n newVersion,\n });\n }\n }\n }\n\n if (packageJson.peerDependencies) {\n for (const [name, existingVersion] of Object.entries(\n packageJson.peerDependencies,\n )) {\n if (existingVersion && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {\n const newVersion = await parsePackageVersion({ name, tag, version });\n packageJson.peerDependencies[name] = newVersion;\n logVersionUpdate({\n name,\n version: existingVersion,\n newVersion,\n });\n }\n }\n }\n\n await writePackage(packageJson);\n\n console.log(\n chalk.green(\n `\\n✅ Project updated to use ${chalk.bold(version ?? tag)}\\n`,\n ),\n );\n\n if (!skipInstall) {\n const { detect } = await import(\"package-manager-detector/detect\");\n const packageManager = await detect();\n if (!packageManager) {\n throw new Error(\n `❌ Failed to detect your package manager. Run install manually.`,\n );\n }\n console.log(\n `▶️ Installing updated dependencies with \\`${packageManager.agent}\\`\\n`,\n );\n runCmd(`${packageManager.agent} install`);\n }\n\n process.exit(0);\n },\n});\n\nexport async function runUse(args: string[]) {\n await run(use, args);\n}\n","import { phCliHelpCommands } from \"@powerhousedao/shared/clis/args\";\nimport { subcommands } from \"cmd-ts\";\nimport { getVersion } from \"../get-version.js\";\nimport { init } from \"./init.js\";\nimport { selfUpdate } from \"./self-update.js\";\nimport { setupGlobals } from \"./setup-globals.js\";\nimport { update } from \"./update.js\";\nimport { useLocal } from \"./use-local.js\";\nimport { use } from \"./use.js\";\n\n// `--version` is intercepted in cli.ts before the subcommand tree is\n// constructed, so cmd-ts only needs the bare version string here. The\n// rich version output (with project info, package manager, etc.) is\n// produced by `getPhCmdVersionInfo` along that short-circuit path.\nexport const ph = subcommands({\n name: \"ph\",\n version: getVersion(),\n description:\n \"The Powerhouse CLI (ph-cmd) is a command-line interface tool that provides essential commands for managing Powerhouse projects.\\nThe tool and it's commands are fundamental for creating, building, and running Document Models as a builder in studio mode.\",\n cmds: {\n init,\n use,\n update,\n \"self-update\": selfUpdate,\n \"setup-globals\": setupGlobals,\n \"use-local\": useLocal,\n ...phCliHelpCommands,\n },\n});\n","import { run as runCmdTs } from \"cmd-ts\";\nimport { ph } from \"./commands/ph.js\";\n\nexport async function run(args: string[]) {\n return await runCmdTs(ph, args);\n}\n"],"names":["spawnChild","readFileAsync","readFile","runCmdTs"],"mappings":"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","debug_id":"83556561-3410-5523-ae16-bd17b5ed604c"}
@@ -0,0 +1,141 @@
1
+
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="9f4ee2ee-1b16-5029-9264-fd743423f35c")}catch(e){}}();
3
+ import { join } from "node:path";
4
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
5
+ import { cwd } from "node:process";
6
+ import { createInterface } from "node:readline/promises";
7
+ //#region src/commands/update-packages.ts
8
+ /**
9
+ * True when the stored value is a dist-tag (dev/staging/rc/latest) rather than
10
+ * a concrete semver version. Dist-tags are re-resolved against the registry at
11
+ * load time, so they self-update and must not be bumped.
12
+ */
13
+ function isDistTag(version, semver) {
14
+ return !semver.valid(semver.clean(version));
15
+ }
16
+ /**
17
+ * Pure: decide which pinned packages have a newer release. Dist-tags are
18
+ * skipped (they self-update via the tag). `resolveLatest` is injected so this
19
+ * decision logic is testable without a network; `semver` is lazy-loaded.
20
+ */
21
+ async function findOutdatedPackages(packages, resolveLatest) {
22
+ const semver = await import("semver");
23
+ const outdated = [];
24
+ for (const pkg of packages) {
25
+ if (!pkg.version || isDistTag(pkg.version, semver)) continue;
26
+ const newVersion = await resolveLatest(pkg.packageName, pkg.version);
27
+ if (newVersion && newVersion !== pkg.version) outdated.push({
28
+ name: pkg.packageName,
29
+ currentVersion: pkg.version,
30
+ newVersion,
31
+ provider: pkg.provider === "local" ? "local" : "registry"
32
+ });
33
+ }
34
+ return outdated;
35
+ }
36
+ /**
37
+ * Pure: bump the given packages' versions in place, preserving each entry's
38
+ * provider and any other fields. Only the listed packages are touched.
39
+ */
40
+ function applyVersionBumps(config, updates) {
41
+ const byName = new Map(updates.map((u) => [u.name, u.newVersion]));
42
+ for (const pkg of config.packages ?? []) {
43
+ const next = byName.get(pkg.packageName);
44
+ if (next !== void 0) pkg.version = next;
45
+ }
46
+ }
47
+ /** Fetch every published version string for a package from the registry. */
48
+ async function fetchNpmVersions(name, registryUrl) {
49
+ const { spawnAsync } = await import("@powerhousedao/shared/clis");
50
+ const args = [
51
+ "view",
52
+ name,
53
+ "versions",
54
+ "--json"
55
+ ];
56
+ if (registryUrl) args.push("--registry", registryUrl);
57
+ try {
58
+ const parsed = JSON.parse(await spawnAsync("npm", args));
59
+ return Array.isArray(parsed) ? parsed : [];
60
+ } catch {
61
+ return [];
62
+ }
63
+ }
64
+ /**
65
+ * The newest published version within the same major as `currentVersion`, or
66
+ * null when the current version is already the newest in that major.
67
+ */
68
+ async function resolveLatestSameMajor(name, currentVersion, registryUrl) {
69
+ const semver = await import("semver");
70
+ const current = semver.clean(currentVersion);
71
+ if (!current || !semver.valid(current)) return null;
72
+ const currentMajor = semver.major(current);
73
+ const candidates = (await fetchNpmVersions(name, registryUrl)).map((v) => semver.clean(v)).filter((v) => v !== null && semver.valid(v) !== null).filter((v) => semver.major(v) === currentMajor && semver.gt(v, current));
74
+ if (candidates.length === 0) return null;
75
+ candidates.sort(semver.compare);
76
+ return candidates[candidates.length - 1];
77
+ }
78
+ /** Interactive prompt; returns the subset of `outdated` the user accepts. */
79
+ async function promptForUpdates(outdated) {
80
+ const chosen = [];
81
+ for (const pkg of outdated) if (await confirm(`${pkg.name} ${pkg.currentVersion} → ${pkg.newVersion} — update? [y/N]`)) chosen.push(pkg);
82
+ return chosen;
83
+ }
84
+ async function confirm(prompt) {
85
+ const { default: chalk } = await import("chalk");
86
+ const rl = createInterface({
87
+ input: process.stdin,
88
+ output: process.stdout
89
+ });
90
+ try {
91
+ const answer = (await rl.question(chalk.cyan(prompt))).trim().toLowerCase();
92
+ return answer === "y" || answer === "yes";
93
+ } finally {
94
+ rl.close();
95
+ }
96
+ }
97
+ /**
98
+ * The `ph update` step that keeps installed (powerhouse.config.json) packages
99
+ * current. Bumps each outdated pinned package's version, writes the config,
100
+ * and, for `local`-provider packages, runs the package manager's update.
101
+ * Returns the names of the local packages it bumped.
102
+ *
103
+ * `chalk` and the shared CLI helpers are lazy-imported (CLI cold-path rule).
104
+ * `runCommand`, `resolveLatest` and `prompt` are injectable for tests; they
105
+ * default to the shared module's behavior.
106
+ */
107
+ async function updateInstalledPackages(args) {
108
+ const [chalkMod, { runCmd, POWERHOUSE_CONFIG_FILE }] = await Promise.all([import("chalk"), import("@powerhousedao/shared/clis")]);
109
+ const chalk = chalkMod.default;
110
+ const { registryUrl, auto, skipInstall, packageManager, resolveLatest, prompt } = args;
111
+ const run = args.runCommand ?? runCmd;
112
+ const configPath = args.configPath ?? join(cwd(), POWERHOUSE_CONFIG_FILE);
113
+ if (!existsSync(configPath)) return [];
114
+ const config = JSON.parse(readFileSync(configPath, "utf-8"));
115
+ if (!config.packages?.length) return [];
116
+ const resolve = resolveLatest ?? ((name, version) => resolveLatestSameMajor(name, version, registryUrl));
117
+ const outdated = await findOutdatedPackages(config.packages, resolve);
118
+ if (outdated.length === 0) {
119
+ console.log(chalk.dim("\nInstalled packages are up to date."));
120
+ return [];
121
+ }
122
+ const toUpdate = auto ? outdated : await (prompt ?? promptForUpdates)(outdated);
123
+ if (toUpdate.length === 0) {
124
+ console.log(chalk.dim("No packages updated."));
125
+ return [];
126
+ }
127
+ for (const pkg of toUpdate) console.log(chalk.green(` ↻ ${pkg.name} ${pkg.currentVersion} → ${pkg.newVersion}`));
128
+ applyVersionBumps(config, toUpdate);
129
+ writeFileSync(configPath, JSON.stringify(config, null, 2));
130
+ const localBumped = toUpdate.filter((pkg) => pkg.provider === "local").map((pkg) => pkg.name);
131
+ if (localBumped.length > 0 && !skipInstall && packageManager) {
132
+ console.log(chalk.cyan(`\nUpdating local package(s) with \`${packageManager.agent}\`...`));
133
+ run(`${packageManager.agent} update ${localBumped.join(" ")}`);
134
+ }
135
+ return localBumped;
136
+ }
137
+ //#endregion
138
+ export { applyVersionBumps, fetchNpmVersions, findOutdatedPackages, isDistTag, promptForUpdates, resolveLatestSameMajor, updateInstalledPackages };
139
+
140
+ //# sourceMappingURL=update-packages-BTDhXqEj.mjs.map
141
+ //# debugId=9f4ee2ee-1b16-5029-9264-fd743423f35c
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-packages-BTDhXqEj.mjs","sources":["../src/commands/update-packages.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { cwd } from \"node:process\";\nimport { createInterface } from \"node:readline/promises\";\n\nexport interface ConfigPackage {\n packageName: string;\n version: string;\n provider?: \"registry\" | \"local\";\n [key: string]: unknown;\n}\n\nexport interface OutdatedPackage {\n name: string;\n currentVersion: string;\n newVersion: string;\n provider: \"registry\" | \"local\";\n}\n\nexport type ResolveLatest = (\n name: string,\n currentVersion: string,\n) => Promise<string | null>;\n\n/**\n * The slice of `semver` this module uses. It is injected (rather than\n * statically imported) because the CLI cold-path rule forbids static imports\n * of heavy modules in command files — the caller lazy-loads `semver` and\n * passes it in.\n */\nexport interface SemverFns {\n valid: (v: string | null) => unknown;\n clean: (v: string) => string | null;\n major: (v: string) => number;\n gt: (a: string, b: string) => boolean;\n compare: (a: string, b: string) => number;\n}\n\n/**\n * True when the stored value is a dist-tag (dev/staging/rc/latest) rather than\n * a concrete semver version. Dist-tags are re-resolved against the registry at\n * load time, so they self-update and must not be bumped.\n */\nexport function isDistTag(version: string, semver: SemverFns): boolean {\n return !semver.valid(semver.clean(version));\n}\n\n/**\n * Pure: decide which pinned packages have a newer release. Dist-tags are\n * skipped (they self-update via the tag). `resolveLatest` is injected so this\n * decision logic is testable without a network; `semver` is lazy-loaded.\n */\nexport async function findOutdatedPackages(\n packages: ConfigPackage[],\n resolveLatest: ResolveLatest,\n): Promise<OutdatedPackage[]> {\n const semver = await import(\"semver\");\n const outdated: OutdatedPackage[] = [];\n for (const pkg of packages) {\n if (!pkg.version || isDistTag(pkg.version, semver)) continue;\n const newVersion = await resolveLatest(pkg.packageName, pkg.version);\n if (newVersion && newVersion !== pkg.version) {\n outdated.push({\n name: pkg.packageName,\n currentVersion: pkg.version,\n newVersion,\n provider: pkg.provider === \"local\" ? \"local\" : \"registry\",\n });\n }\n }\n return outdated;\n}\n\n/**\n * Pure: bump the given packages' versions in place, preserving each entry's\n * provider and any other fields. Only the listed packages are touched.\n */\nexport function applyVersionBumps(\n config: { packages?: ConfigPackage[] },\n updates: Pick<OutdatedPackage, \"name\" | \"newVersion\">[],\n): void {\n const byName = new Map(updates.map((u) => [u.name, u.newVersion]));\n for (const pkg of config.packages ?? []) {\n const next = byName.get(pkg.packageName);\n if (next !== undefined) pkg.version = next;\n }\n}\n\n/** Fetch every published version string for a package from the registry. */\nexport async function fetchNpmVersions(\n name: string,\n registryUrl?: string,\n): Promise<string[]> {\n const { spawnAsync } = await import(\"@powerhousedao/shared/clis\");\n const args = [\"view\", name, \"versions\", \"--json\"];\n if (registryUrl) args.push(\"--registry\", registryUrl);\n try {\n const parsed: unknown = JSON.parse(await spawnAsync(\"npm\", args));\n return Array.isArray(parsed) ? (parsed as string[]) : [];\n } catch {\n return [];\n }\n}\n\n/**\n * The newest published version within the same major as `currentVersion`, or\n * null when the current version is already the newest in that major.\n */\nexport async function resolveLatestSameMajor(\n name: string,\n currentVersion: string,\n registryUrl?: string,\n): Promise<string | null> {\n const semver = await import(\"semver\");\n const current = semver.clean(currentVersion);\n if (!current || !semver.valid(current)) return null;\n const currentMajor = semver.major(current);\n const candidates = (await fetchNpmVersions(name, registryUrl))\n .map((v) => semver.clean(v))\n .filter((v): v is string => v !== null && semver.valid(v) !== null)\n .filter((v) => semver.major(v) === currentMajor && semver.gt(v, current));\n if (candidates.length === 0) return null;\n candidates.sort(semver.compare);\n return candidates[candidates.length - 1];\n}\n\n/** Interactive prompt; returns the subset of `outdated` the user accepts. */\nexport async function promptForUpdates(\n outdated: OutdatedPackage[],\n): Promise<OutdatedPackage[]> {\n const chosen: OutdatedPackage[] = [];\n for (const pkg of outdated) {\n const answer = await confirm(\n `${pkg.name} ${pkg.currentVersion} → ${pkg.newVersion} — update? [y/N]`,\n );\n if (answer) chosen.push(pkg);\n }\n return chosen;\n}\n\nasync function confirm(prompt: string): Promise<boolean> {\n const { default: chalk } = await import(\"chalk\");\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n try {\n const answer = (await rl.question(chalk.cyan(prompt))).trim().toLowerCase();\n return answer === \"y\" || answer === \"yes\";\n } finally {\n rl.close();\n }\n}\n\nexport interface UpdateInstalledArgs {\n registryUrl?: string;\n /** true for `--update-packages`: apply automatically, no prompt. */\n auto: boolean;\n skipInstall: boolean;\n packageManager?: { agent: string } | null;\n /** Config file path; defaults to the cwd's powerhouse.config.json. */\n configPath?: string;\n /** Command runner; defaults to the shared `runCmd`. */\n runCommand?: (command: string) => void;\n /** Version resolver; defaults to `resolveLatestSameMajor`. */\n resolveLatest?: ResolveLatest;\n /** Interactive prompt; defaults to `promptForUpdates`. */\n prompt?: (outdated: OutdatedPackage[]) => Promise<OutdatedPackage[]>;\n}\n\n/**\n * The `ph update` step that keeps installed (powerhouse.config.json) packages\n * current. Bumps each outdated pinned package's version, writes the config,\n * and, for `local`-provider packages, runs the package manager's update.\n * Returns the names of the local packages it bumped.\n *\n * `chalk` and the shared CLI helpers are lazy-imported (CLI cold-path rule).\n * `runCommand`, `resolveLatest` and `prompt` are injectable for tests; they\n * default to the shared module's behavior.\n */\nexport async function updateInstalledPackages(\n args: UpdateInstalledArgs,\n): Promise<string[]> {\n const [chalkMod, { runCmd, POWERHOUSE_CONFIG_FILE }] = await Promise.all([\n import(\"chalk\"),\n import(\"@powerhousedao/shared/clis\"),\n ]);\n const chalk = chalkMod.default;\n const {\n registryUrl,\n auto,\n skipInstall,\n packageManager,\n resolveLatest,\n prompt,\n } = args;\n const run = args.runCommand ?? runCmd;\n const configPath = args.configPath ?? join(cwd(), POWERHOUSE_CONFIG_FILE);\n\n if (!existsSync(configPath)) return [];\n const config = JSON.parse(readFileSync(configPath, \"utf-8\")) as {\n packages?: ConfigPackage[];\n };\n if (!config.packages?.length) return [];\n\n const resolve =\n resolveLatest ??\n ((name, version) => resolveLatestSameMajor(name, version, registryUrl));\n const outdated = await findOutdatedPackages(config.packages, resolve);\n if (outdated.length === 0) {\n console.log(chalk.dim(\"\\nInstalled packages are up to date.\"));\n return [];\n }\n\n const toUpdate = auto\n ? outdated\n : await (prompt ?? promptForUpdates)(outdated);\n if (toUpdate.length === 0) {\n console.log(chalk.dim(\"No packages updated.\"));\n return [];\n }\n\n for (const pkg of toUpdate) {\n console.log(\n chalk.green(` ↻ ${pkg.name} ${pkg.currentVersion} → ${pkg.newVersion}`),\n );\n }\n\n applyVersionBumps(config, toUpdate);\n writeFileSync(configPath, JSON.stringify(config, null, 2));\n\n const localBumped = toUpdate\n .filter((pkg) => pkg.provider === \"local\")\n .map((pkg) => pkg.name);\n if (localBumped.length > 0 && !skipInstall && packageManager) {\n console.log(\n chalk.cyan(\n `\\nUpdating local package(s) with \\`${packageManager.agent}\\`...`,\n ),\n );\n run(`${packageManager.agent} update ${localBumped.join(\" \")}`);\n }\n\n return localBumped;\n}\n"],"names":[],"mappings":"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","debug_id":"9f4ee2ee-1b16-5029-9264-fd743423f35c"}
@@ -0,0 +1,173 @@
1
+
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="467e2f81-5d30-5dda-8f13-1fab828d106d")}catch(e){}}();
3
+ import semver from "semver";
4
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
5
+ import { homedir } from "node:os";
6
+ import { dirname, join } from "node:path";
7
+ //#region src/utils/version-check.ts
8
+ /**
9
+ * The release streams `ph self-update` knows about. The running build's
10
+ * stream is derived from its own version (see `getStream`); users can
11
+ * override it with `--tag`.
12
+ */
13
+ const PH_CMD_STREAMS = ["latest", "dev"];
14
+ /**
15
+ * Which release stream a version belongs to: stable versions (no semver
16
+ * prerelease tag) live on `latest`, everything else (dev, staging, rc,
17
+ * test builds) on `dev` — the active development stream. A dev build must
18
+ * not be nagged toward an older stable release. Unparseable versions fall
19
+ * back to `latest` so a broken version string can never trigger a dev
20
+ * target.
21
+ */
22
+ function getStream(version) {
23
+ const parsed = semver.parse(version);
24
+ if (!parsed) return "latest";
25
+ return parsed.prerelease.length > 0 ? "dev" : "latest";
26
+ }
27
+ /**
28
+ * Whether the user should be nudged: true only when both versions parse
29
+ * AND the stream target sorts strictly above the running version (semver
30
+ * ordering, so a dev build correctly compares below its own release and
31
+ * below newer dev builds). Never nags on broken data or downgrades.
32
+ */
33
+ function isOutdated(current, target) {
34
+ const currentParsed = semver.parse(current);
35
+ const targetParsed = semver.parse(target);
36
+ if (!currentParsed || !targetParsed) return false;
37
+ return semver.gt(targetParsed, currentParsed);
38
+ }
39
+ const NPM_REGISTRY_URL = "https://registry.npmjs.org";
40
+ const PACKAGE_NAME = "ph-cmd";
41
+ const FETCH_TIMEOUT_MS = 2e3;
42
+ function parseCache(raw) {
43
+ if (typeof raw !== "object" || raw === null) return null;
44
+ const obj = raw;
45
+ if (typeof obj.checkedAt !== "string" || !Number.isFinite(Date.parse(obj.checkedAt))) return null;
46
+ if (typeof obj.target !== "string" || !semver.valid(obj.target)) return null;
47
+ if (obj.stream !== "latest" && obj.stream !== "dev") return null;
48
+ return {
49
+ checkedAt: obj.checkedAt,
50
+ stream: obj.stream,
51
+ target: obj.target
52
+ };
53
+ }
54
+ async function readCache(deps) {
55
+ let raw;
56
+ try {
57
+ raw = await deps.readFile(deps.cachePath);
58
+ } catch {
59
+ return null;
60
+ }
61
+ try {
62
+ return parseCache(JSON.parse(raw));
63
+ } catch {
64
+ return null;
65
+ }
66
+ }
67
+ /**
68
+ * Resolve the newest published version on the running build's release
69
+ * stream, using a 24 h on-disk cache. Never throws: a missing/corrupt
70
+ * cache or a failed fetch degrades to the stale value (or no result), so
71
+ * the check can never break the wrapped command.
72
+ */
73
+ async function checkForNewerVersion(opts) {
74
+ const { deps } = opts;
75
+ const stream = getStream(opts.currentVersion);
76
+ const cached = await readCache(deps);
77
+ if (cached && cached.stream === stream && deps.now() - Date.parse(cached.checkedAt) < 864e5) return cached;
78
+ let target = null;
79
+ try {
80
+ const res = await deps.fetch(`${NPM_REGISTRY_URL}/${PACKAGE_NAME}/${stream}`, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });
81
+ if (res.ok) {
82
+ const body = await res.json();
83
+ if (typeof body.version === "string" && semver.valid(body.version)) target = body.version;
84
+ }
85
+ } catch {}
86
+ if (target) {
87
+ const checkedAt = new Date(deps.now()).toISOString();
88
+ try {
89
+ await deps.writeFile(deps.cachePath, JSON.stringify({
90
+ checkedAt,
91
+ stream,
92
+ target
93
+ }, null, 2));
94
+ } catch {}
95
+ return {
96
+ stream,
97
+ target,
98
+ checkedAt
99
+ };
100
+ }
101
+ return cached && cached.stream === stream ? cached : null;
102
+ }
103
+ /** The exact one-line notice printed to stderr when the CLI is outdated. */
104
+ function formatOutdatedNotice(current, target, stream) {
105
+ return `A new version of ${PACKAGE_NAME} is available: ${target} (you have ${current} — ${stream} stream). Run 'ph self-update' to update.`;
106
+ }
107
+ /**
108
+ * Default deps for the bundled CLI: real registry fetch, wall clock, and
109
+ * the `~/.ph` cache file (the same directory telemetry bootstraps). Tests
110
+ * inject everything in `VersionCheckDeps` instead.
111
+ */
112
+ function defaultDeps() {
113
+ return {
114
+ fetch: (url, init) => globalThis.fetch(url, init),
115
+ now: () => Date.now(),
116
+ readFile: (p) => readFile(p, "utf-8"),
117
+ writeFile: async (p, contents) => {
118
+ await mkdir(dirname(p), { recursive: true });
119
+ await writeFile(p, contents, "utf-8");
120
+ },
121
+ cachePath: join(homedir(), ".ph", "ph-cmd-self-update.json")
122
+ };
123
+ }
124
+ /**
125
+ * The single entry point `cli.ts` calls on every invocation, before
126
+ * dispatch. Skips help/version/self-update invocations, CI, and an
127
+ * explicit `PH_NO_UPDATE_CHECK=1` opt-out; refreshes the 24 h cache when
128
+ * stale; and prints the one-line notice to stderr only when the running
129
+ * build is outdated AND stderr is a TTY. Never throws and never blocks
130
+ * the wrapped command for more than the bounded fetch timeout.
131
+ */
132
+ async function maybeNotifyOutdated(opts) {
133
+ const env = opts.env ?? process.env;
134
+ const first = opts.args[0];
135
+ if (opts.args.length === 0) return;
136
+ if (first === "--help" || first === "-h" || first === "--version" || first === "-v") return;
137
+ if (first === "self-update") return;
138
+ if (env.CI === "1" || env.PH_NO_UPDATE_CHECK === "1") return;
139
+ const deps = {
140
+ ...defaultDeps(),
141
+ ...opts.deps
142
+ };
143
+ const result = await checkForNewerVersion({
144
+ currentVersion: opts.currentVersion,
145
+ deps
146
+ }).catch(() => null);
147
+ if (!result || !isOutdated(opts.currentVersion, result.target)) return;
148
+ if (opts.stderrIsTty !== true) return;
149
+ (opts.writeStderr ?? ((line) => process.stderr.write(`${line}\n`)))(formatOutdatedNotice(opts.currentVersion, result.target, result.stream));
150
+ }
151
+ /**
152
+ * Record a version as current so the next run's check is quiet (used by
153
+ * `ph self-update` right after a successful update: target == new current,
154
+ * so the outdated notice stops).
155
+ */
156
+ async function setCacheCurrent(version, deps) {
157
+ const full = {
158
+ ...defaultDeps(),
159
+ ...deps
160
+ };
161
+ try {
162
+ await full.writeFile(full.cachePath, JSON.stringify({
163
+ checkedAt: new Date(full.now()).toISOString(),
164
+ stream: getStream(version),
165
+ target: version
166
+ }, null, 2));
167
+ } catch {}
168
+ }
169
+ //#endregion
170
+ export { setCacheCurrent as i, getStream as n, maybeNotifyOutdated as r, PH_CMD_STREAMS as t };
171
+
172
+ //# sourceMappingURL=version-check-BxMITre2.mjs.map
173
+ //# debugId=467e2f81-5d30-5dda-8f13-1fab828d106d
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-check-BxMITre2.mjs","sources":["../src/utils/version-check.ts"],"sourcesContent":["import semver from \"semver\";\nimport {\n mkdir,\n readFile as readFileAsync,\n writeFile as writeFileAsync,\n} from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\n/**\n * The release streams `ph self-update` knows about. The running build's\n * stream is derived from its own version (see `getStream`); users can\n * override it with `--tag`.\n */\nexport const PH_CMD_STREAMS = [\"latest\", \"dev\"] as const;\nexport type PhCmdStream = (typeof PH_CMD_STREAMS)[number];\n\n/**\n * Which release stream a version belongs to: stable versions (no semver\n * prerelease tag) live on `latest`, everything else (dev, staging, rc,\n * test builds) on `dev` — the active development stream. A dev build must\n * not be nagged toward an older stable release. Unparseable versions fall\n * back to `latest` so a broken version string can never trigger a dev\n * target.\n */\nexport function getStream(version: string): PhCmdStream {\n const parsed = semver.parse(version);\n if (!parsed) return \"latest\";\n return parsed.prerelease.length > 0 ? \"dev\" : \"latest\";\n}\n\n/**\n * Whether the user should be nudged: true only when both versions parse\n * AND the stream target sorts strictly above the running version (semver\n * ordering, so a dev build correctly compares below its own release and\n * below newer dev builds). Never nags on broken data or downgrades.\n */\nexport function isOutdated(current: string, target: string): boolean {\n const currentParsed = semver.parse(current);\n const targetParsed = semver.parse(target);\n if (!currentParsed || !targetParsed) return false;\n return semver.gt(targetParsed, currentParsed);\n}\n\nconst NPM_REGISTRY_URL = \"https://registry.npmjs.org\";\nconst PACKAGE_NAME = \"ph-cmd\";\nexport const CACHE_TTL_MS = 24 * 60 * 60 * 1000;\nconst FETCH_TIMEOUT_MS = 2000;\n\n/**\n * Injected for tests; the defaults below use the real registry, clock and\n * `~/.ph` cache file.\n */\nexport type VersionCheckDeps = {\n fetch: (url: string, init?: { signal?: AbortSignal }) => Promise<Response>;\n now: () => number;\n readFile: (path: string) => Promise<string>;\n writeFile: (path: string, contents: string) => Promise<void>;\n cachePath: string;\n};\n\nexport type VersionCheckResult = {\n stream: PhCmdStream;\n target: string;\n checkedAt: string;\n};\n\nfunction parseCache(raw: unknown): VersionCheckResult | null {\n if (typeof raw !== \"object\" || raw === null) return null;\n const obj = raw as Record<string, unknown>;\n if (\n typeof obj.checkedAt !== \"string\" ||\n !Number.isFinite(Date.parse(obj.checkedAt))\n )\n return null;\n if (typeof obj.target !== \"string\" || !semver.valid(obj.target)) return null;\n if (obj.stream !== \"latest\" && obj.stream !== \"dev\") return null;\n return { checkedAt: obj.checkedAt, stream: obj.stream, target: obj.target };\n}\n\nasync function readCache(\n deps: VersionCheckDeps,\n): Promise<VersionCheckResult | null> {\n let raw: string;\n try {\n raw = await deps.readFile(deps.cachePath);\n } catch {\n return null;\n }\n try {\n return parseCache(JSON.parse(raw));\n } catch {\n return null;\n }\n}\n\n/**\n * Resolve the newest published version on the running build's release\n * stream, using a 24 h on-disk cache. Never throws: a missing/corrupt\n * cache or a failed fetch degrades to the stale value (or no result), so\n * the check can never break the wrapped command.\n */\nexport async function checkForNewerVersion(opts: {\n currentVersion: string;\n deps: VersionCheckDeps;\n}): Promise<VersionCheckResult | null> {\n const { deps } = opts;\n const stream = getStream(opts.currentVersion);\n const cached = await readCache(deps);\n if (\n cached &&\n cached.stream === stream &&\n deps.now() - Date.parse(cached.checkedAt) < CACHE_TTL_MS\n ) {\n return cached;\n }\n let target: string | null = null;\n try {\n const res = await deps.fetch(\n `${NPM_REGISTRY_URL}/${PACKAGE_NAME}/${stream}`,\n {\n signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n },\n );\n if (res.ok) {\n const body = (await res.json()) as { version?: unknown };\n if (typeof body.version === \"string\" && semver.valid(body.version)) {\n target = body.version;\n }\n }\n } catch {\n // offline / timeout — keep whatever we had\n }\n if (target) {\n const checkedAt = new Date(deps.now()).toISOString();\n try {\n await deps.writeFile(\n deps.cachePath,\n JSON.stringify({ checkedAt, stream, target }, null, 2),\n );\n } catch {\n // a failed cache write must not fail the check\n }\n return { stream, target, checkedAt };\n }\n return cached && cached.stream === stream ? cached : null;\n}\n\n/** The exact one-line notice printed to stderr when the CLI is outdated. */\nexport function formatOutdatedNotice(\n current: string,\n target: string,\n stream: PhCmdStream,\n): string {\n return `A new version of ${PACKAGE_NAME} is available: ${target} (you have ${current} — ${stream} stream). Run 'ph self-update' to update.`;\n}\n\n/**\n * Default deps for the bundled CLI: real registry fetch, wall clock, and\n * the `~/.ph` cache file (the same directory telemetry bootstraps). Tests\n * inject everything in `VersionCheckDeps` instead.\n */\nfunction defaultDeps(): VersionCheckDeps {\n return {\n fetch: (url, init) => globalThis.fetch(url, init),\n now: () => Date.now(),\n readFile: (p) => readFileAsync(p, \"utf-8\"),\n writeFile: async (p, contents) => {\n await mkdir(dirname(p), { recursive: true });\n await writeFileAsync(p, contents, \"utf-8\");\n },\n cachePath: join(homedir(), \".ph\", \"ph-cmd-self-update.json\"),\n };\n}\n\nexport type MaybeNotifyOptions = {\n /** process argv without the node + script entries. */\n args: string[];\n /** the running build's version (getVersion()). */\n currentVersion: string;\n /** true when stderr is interactive; non-TTY runs refresh but stay silent. */\n stderrIsTty?: boolean;\n /** injected for tests; defaults to process.env. */\n env?: Record<string, string | undefined>;\n /** partial deps for tests; defaults to the real registry + `~/.ph`. */\n deps?: Partial<VersionCheckDeps>;\n /** stderr sink for tests; defaults to process.stderr. */\n writeStderr?: (line: string) => void;\n};\n\n/**\n * The single entry point `cli.ts` calls on every invocation, before\n * dispatch. Skips help/version/self-update invocations, CI, and an\n * explicit `PH_NO_UPDATE_CHECK=1` opt-out; refreshes the 24 h cache when\n * stale; and prints the one-line notice to stderr only when the running\n * build is outdated AND stderr is a TTY. Never throws and never blocks\n * the wrapped command for more than the bounded fetch timeout.\n */\nexport async function maybeNotifyOutdated(\n opts: MaybeNotifyOptions,\n): Promise<void> {\n const env = opts.env ?? process.env;\n const first = opts.args[0];\n if (opts.args.length === 0) return;\n if (\n first === \"--help\" ||\n first === \"-h\" ||\n first === \"--version\" ||\n first === \"-v\"\n )\n return;\n if (first === \"self-update\") return;\n if (env.CI === \"1\" || env.PH_NO_UPDATE_CHECK === \"1\") return;\n\n const deps: VersionCheckDeps = { ...defaultDeps(), ...opts.deps };\n const result = await checkForNewerVersion({\n currentVersion: opts.currentVersion,\n deps,\n }).catch(() => null);\n if (!result || !isOutdated(opts.currentVersion, result.target)) return;\n if (opts.stderrIsTty !== true) return;\n const writeStderr =\n opts.writeStderr ?? ((line: string) => process.stderr.write(`${line}\\n`));\n writeStderr(\n formatOutdatedNotice(opts.currentVersion, result.target, result.stream),\n );\n}\n\n/**\n * Record a version as current so the next run's check is quiet (used by\n * `ph self-update` right after a successful update: target == new current,\n * so the outdated notice stops).\n */\nexport async function setCacheCurrent(\n version: string,\n deps?: Partial<VersionCheckDeps>,\n): Promise<void> {\n const full: VersionCheckDeps = { ...defaultDeps(), ...deps };\n try {\n await full.writeFile(\n full.cachePath,\n JSON.stringify(\n {\n checkedAt: new Date(full.now()).toISOString(),\n stream: getStream(version),\n target: version,\n },\n null,\n 2,\n ),\n );\n } catch {\n // best effort — the notice logic tolerates a missing cache\n }\n}\n"],"names":["readFileAsync","writeFileAsync"],"mappings":"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","debug_id":"467e2f81-5d30-5dda-8f13-1fab828d106d"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ph-cmd",
3
- "version": "6.2.3-dev.0",
3
+ "version": "6.2.3-dev.2",
4
4
  "description": "Powerhouse CLI — create Vetra projects, generate document models and editors, run local dev environments, and publish packages.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "type": "module",
@@ -35,7 +35,7 @@
35
35
  "author": "",
36
36
  "dependencies": {
37
37
  "cross-spawn": "7.0.6",
38
- "@powerhousedao/shared": "6.2.3-dev.0",
38
+ "@powerhousedao/shared": "6.2.3-dev.2",
39
39
  "@sentry/node-core": "^10.52.0",
40
40
  "chalk": "5.6.2",
41
41
  "cmd-ts": "0.15.0",
@@ -46,7 +46,7 @@
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/cross-spawn": "6.0.6",
49
- "@powerhousedao/codegen": "6.2.3-dev.0",
49
+ "@powerhousedao/codegen": "6.2.3-dev.2",
50
50
  "tsdown": "0.21.1",
51
51
  "vitest": "4.1.1"
52
52
  },
@@ -1,4 +0,0 @@
1
- import { t as delegateInit } from "./delegate-init-B3_b7484.mjs";
2
- export { delegateInit };
3
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="123d8778-b655-50a0-8338-1999423f6be7")}catch(e){}}();
4
- //# debugId=123d8778-b655-50a0-8338-1999423f6be7
@@ -1 +0,0 @@
1
- {"version":3,"file":"run-DX-j7-DZ.mjs","sources":["../src/commands/init.ts","../src/commands/setup-globals.ts","../src/commands/update.ts","../src/commands/use-local.ts","../src/commands/use.ts","../src/commands/ph.ts","../src/run.ts"],"sourcesContent":["import { initArgs } from \"@powerhousedao/shared/clis/args\";\nimport { command } from \"cmd-ts\";\nimport { delegateInit } from \"../utils/delegate-init.js\";\n\n/**\n * Delegates `ph init` to the appropriate version of `@powerhousedao/ph-cli`.\n * This ensures the init logic (boilerplate, codegen) always matches the\n * ph-cli version being installed in the new project.\n */\nexport const init = command({\n name: \"init\",\n description: \"Initialize a new project\",\n args: initArgs,\n handler: async (args) => {\n if (args.debug) {\n console.log({ args });\n }\n await delegateInit(args);\n process.exit(0);\n },\n});\n","import { initArgs } from \"@powerhousedao/shared/clis/args\";\nimport { command } from \"cmd-ts\";\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\nconst PH_GLOBAL_PACKAGE_NAME = \"ph-global\";\n\n/**\n * `ph setup-globals` bootstraps the `~/.ph` project. It's the same flow as\n * `ph init` with `--name .ph` from the user's home directory, plus a\n * post-step that renames the package.json to `ph-global` (since `.ph` is\n * an invalid npm name).\n */\nexport const setupGlobals = command({\n name: \"setup-globals\",\n description: \"Initialize a new global project\",\n args: initArgs,\n handler: async (args) => {\n if (args.debug) {\n console.log({ args });\n }\n\n const { HOME_DIR, PH_GLOBAL_DIR_NAME, POWERHOUSE_GLOBAL_DIR } =\n await import(\"@powerhousedao/shared/clis\");\n\n /**\n * Fix the package.json `name` field for the global project — `.ph` is a\n * valid directory name but not a valid npm package name (vite + npm\n * reject names starting with a dot). We let `ph init` create the project\n * as `.ph` and then rename it here to `ph-global`.\n */\n const fixGlobalPackageName = (): void => {\n const packageJsonPath = path.join(POWERHOUSE_GLOBAL_DIR, \"package.json\");\n if (!existsSync(packageJsonPath)) return;\n try {\n const packageJson = JSON.parse(\n readFileSync(packageJsonPath, \"utf-8\"),\n ) as { name?: string };\n if (packageJson.name?.startsWith(\".\")) {\n packageJson.name = PH_GLOBAL_PACKAGE_NAME;\n writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));\n }\n } catch {\n // Ignore parse/write failures — leaves the file untouched.\n }\n };\n\n // The directory itself can exist without the project being bootstrapped —\n // telemetry writes `~/.ph/telemetry.json` early on. Use the presence of\n // `package.json` as the real \"is initialized\" signal.\n const globalPackageJson = path.join(POWERHOUSE_GLOBAL_DIR, \"package.json\");\n if (existsSync(globalPackageJson)) {\n // Repair-in-place: an older bootstrap may have left `name: \".ph\"` in\n // package.json, which breaks vite/npm. Fix it on every invocation.\n fixGlobalPackageName();\n console.log(`📦 Using global project: ${POWERHOUSE_GLOBAL_DIR}`);\n process.exit(0);\n }\n\n console.log(\"📦 Initializing global project...\");\n process.chdir(HOME_DIR);\n const { delegateInit } = await import(\"../utils/delegate-init.js\");\n await delegateInit(args, [\"--name\", PH_GLOBAL_DIR_NAME]);\n fixGlobalPackageName();\n console.log(\n `🚀 Global project initialized successfully: ${POWERHOUSE_GLOBAL_DIR}`,\n );\n process.exit(0);\n },\n});\n","import { debugArgs } from \"@powerhousedao/shared/clis/args\";\nimport { ALL_POWERHOUSE_DEPENDENCIES } from \"@powerhousedao/shared/constants\";\nimport { boolean, command, flag, optional } from \"cmd-ts\";\n\nexport const update = command({\n name: \"update\",\n description:\n \"Update your powerhouse dependencies to their latest tagged version\",\n args: {\n skipInstall: flag({\n type: optional(boolean),\n long: \"skip-install\",\n short: \"s\",\n description: \"Skip running `install` with your package manager\",\n }),\n ...debugArgs,\n },\n handler: async (args) => {\n const { skipInstall, debug } = args;\n if (debug) {\n console.log({ args });\n }\n console.log(`\\n▶️ Updating Powerhouse dependencies...\\n`);\n const [\n { default: chalk },\n { readPackage },\n { writePackage },\n { getTagFromVersion, logVersionUpdate, parsePackageVersion, runCmd },\n ] = await Promise.all([\n import(\"chalk\"),\n import(\"read-pkg\"),\n import(\"write-package\"),\n import(\"@powerhousedao/shared/clis\"),\n ]);\n const packageJson = await readPackage();\n\n if (packageJson.dependencies) {\n for (const [name, version] of Object.entries(packageJson.dependencies)) {\n if (version && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {\n const tag = getTagFromVersion(version);\n const newVersion = await parsePackageVersion({ name, tag });\n packageJson.dependencies[name] = newVersion;\n logVersionUpdate({\n name,\n version,\n newVersion,\n });\n }\n }\n }\n\n if (packageJson.devDependencies) {\n for (const [name, version] of Object.entries(\n packageJson.devDependencies,\n )) {\n if (version && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {\n const tag = getTagFromVersion(version);\n const newVersion = await parsePackageVersion({ name, tag });\n packageJson.devDependencies[name] = newVersion;\n logVersionUpdate({\n name,\n version,\n newVersion,\n });\n }\n }\n }\n\n if (packageJson.optionalDependencies) {\n for (const [name, version] of Object.entries(\n packageJson.optionalDependencies,\n )) {\n if (version && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {\n const tag = getTagFromVersion(version);\n const newVersion = await parsePackageVersion({ name, tag });\n packageJson.optionalDependencies[name] = newVersion;\n logVersionUpdate({\n name,\n version,\n newVersion,\n });\n }\n }\n }\n\n if (packageJson.peerDependencies) {\n for (const [name, version] of Object.entries(\n packageJson.peerDependencies,\n )) {\n if (version && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {\n const tag = getTagFromVersion(version);\n const newVersion = await parsePackageVersion({ name, tag });\n packageJson.peerDependencies[name] = newVersion;\n logVersionUpdate({\n name,\n version,\n newVersion,\n });\n }\n }\n }\n\n await writePackage(packageJson);\n\n console.log(chalk.green(`\\n✅ Project updated successfully\\n`));\n\n if (skipInstall) return;\n\n const { detect } = await import(\"package-manager-detector/detect\");\n const packageManager = await detect();\n\n if (!packageManager) {\n throw new Error(\n `❌ Failed to detect your package manager. Run install manually.`,\n );\n }\n console.log(\n `▶️ Installing updated dependencies with \\`${packageManager.agent}\\`\\n`,\n );\n runCmd(`${packageManager.agent} install`);\n process.exit(0);\n },\n});\n","import { debugArgs } from \"@powerhousedao/shared/clis/args\";\nimport {\n boolean,\n command,\n flag,\n option,\n optional,\n positional,\n string,\n} from \"cmd-ts\";\n\nexport const useLocal = command({\n name: \"use-local\",\n description:\n \"Use your local `powerhouse` monorepo dependencies the current project.\",\n args: {\n monorepoPathPositional: positional({\n type: optional(string),\n displayName: \"monorepo path\",\n description:\n \"Path to your local powerhouse monorepo relative to this project\",\n }),\n monorepoPathOption: option({\n type: optional(string),\n long: \"path\",\n short: \"p\",\n description:\n \"Path to your local powerhouse monorepo relative to this project\",\n }),\n skipInstall: flag({\n type: optional(boolean),\n long: \"skip-install\",\n short: \"s\",\n description: \"Skip running `install` with `pnpm`\",\n }),\n ...debugArgs,\n },\n handler: async (args) => {\n const { monorepoPathPositional, monorepoPathOption, skipInstall, debug } =\n args;\n if (debug) {\n console.log({ args });\n }\n const monorepoPath = monorepoPathPositional ?? monorepoPathOption;\n\n if (!monorepoPath) {\n throw new Error(\n \"❌ Please provide the path to your local powerhouse monorepo.\",\n );\n }\n\n const { runUseLocal } = await import(\"@powerhousedao/shared/clis\");\n await runUseLocal(monorepoPath, skipInstall);\n process.exit(0);\n },\n});\n","import { debugArgs } from \"@powerhousedao/shared/clis/args\";\nimport { ALL_POWERHOUSE_DEPENDENCIES } from \"@powerhousedao/shared/constants\";\nimport {\n boolean,\n command,\n flag,\n oneOf,\n option,\n optional,\n positional,\n run,\n string,\n} from \"cmd-ts\";\n\nexport const use = command({\n name: \"use\",\n description: \"Specify the release version of Powerhouse dependencies to use.\",\n args: {\n tagPositional: positional({\n type: optional(oneOf([\"latest\", \"staging\", \"dev\", \"rc\"])),\n displayName: \"tag\",\n description: `Specify the release tag to use for your project. Can be one of: \"latest\", \"staging\", \"dev\", or \"rc\".`,\n }),\n tagOption: option({\n type: optional(oneOf([\"latest\", \"staging\", \"dev\", \"rc\"])),\n long: \"tag\",\n short: \"t\",\n description: `Specify the release tag to use for your project. Can be one of: \"latest\", \"staging\", \"dev\", or \"rc\".`,\n }),\n version: option({\n type: optional(string),\n long: \"version\",\n short: \"v\",\n description:\n \"Specify the exact semver release version to use for your project.\",\n }),\n skipInstall: flag({\n type: optional(boolean),\n long: \"skip-install\",\n short: \"s\",\n description: \"Skip running `install` with your package manager\",\n }),\n ...debugArgs,\n },\n handler: async (args) => {\n const { tagPositional, tagOption, version, skipInstall, debug } = args;\n if (debug) {\n console.log({ args });\n }\n const tag = tagPositional ?? tagOption;\n const {\n handleMutuallyExclusiveOptions,\n logVersionUpdate,\n parsePackageVersion,\n runCmd,\n } = await import(\"@powerhousedao/shared/clis\");\n handleMutuallyExclusiveOptions({ tag, version }, \"versioning strategy\");\n\n if (!tag && !version) {\n throw new Error(\n \"Please specify either a release tag or a version to use.\",\n );\n }\n\n const [\n { default: chalk },\n { readPackage },\n { writePackage },\n { clean, valid },\n ] = await Promise.all([\n import(\"chalk\"),\n import(\"read-pkg\"),\n import(\"write-package\"),\n import(\"semver\"),\n ]);\n\n if (version && !valid(clean(version))) {\n throw new Error(`❌ Invalid version: ${chalk.bold(version)}`);\n }\n\n console.log(\n `▶️ Updating project to use ${chalk.bold(version ?? tag)}...\\n`,\n );\n\n const packageJson = await readPackage();\n\n if (packageJson.dependencies) {\n for (const [name, existingVersion] of Object.entries(\n packageJson.dependencies,\n )) {\n if (existingVersion && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {\n const newVersion = await parsePackageVersion({ name, tag, version });\n packageJson.dependencies[name] = newVersion;\n logVersionUpdate({\n name,\n version: existingVersion,\n newVersion,\n });\n }\n }\n }\n\n if (packageJson.devDependencies) {\n for (const [name, existingVersion] of Object.entries(\n packageJson.devDependencies,\n )) {\n if (existingVersion && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {\n const newVersion = await parsePackageVersion({ name, tag, version });\n packageJson.devDependencies[name] = newVersion;\n logVersionUpdate({\n name,\n version: existingVersion,\n newVersion,\n });\n }\n }\n }\n\n if (packageJson.optionalDependencies) {\n for (const [name, existingVersion] of Object.entries(\n packageJson.optionalDependencies,\n )) {\n if (existingVersion && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {\n const newVersion = await parsePackageVersion({ name, tag, version });\n packageJson.optionalDependencies[name] = newVersion;\n logVersionUpdate({\n name,\n version: existingVersion,\n newVersion,\n });\n }\n }\n }\n\n if (packageJson.peerDependencies) {\n for (const [name, existingVersion] of Object.entries(\n packageJson.peerDependencies,\n )) {\n if (existingVersion && ALL_POWERHOUSE_DEPENDENCIES.includes(name)) {\n const newVersion = await parsePackageVersion({ name, tag, version });\n packageJson.peerDependencies[name] = newVersion;\n logVersionUpdate({\n name,\n version: existingVersion,\n newVersion,\n });\n }\n }\n }\n\n await writePackage(packageJson);\n\n console.log(\n chalk.green(\n `\\n✅ Project updated to use ${chalk.bold(version ?? tag)}\\n`,\n ),\n );\n\n if (!skipInstall) {\n const { detect } = await import(\"package-manager-detector/detect\");\n const packageManager = await detect();\n if (!packageManager) {\n throw new Error(\n `❌ Failed to detect your package manager. Run install manually.`,\n );\n }\n console.log(\n `▶️ Installing updated dependencies with \\`${packageManager.agent}\\`\\n`,\n );\n runCmd(`${packageManager.agent} install`);\n }\n\n process.exit(0);\n },\n});\n\nexport async function runUse(args: string[]) {\n await run(use, args);\n}\n","import { phCliHelpCommands } from \"@powerhousedao/shared/clis/args\";\nimport { subcommands } from \"cmd-ts\";\nimport { getVersion } from \"../get-version.js\";\nimport { init } from \"./init.js\";\nimport { setupGlobals } from \"./setup-globals.js\";\nimport { update } from \"./update.js\";\nimport { useLocal } from \"./use-local.js\";\nimport { use } from \"./use.js\";\n\n// `--version` is intercepted in cli.ts before the subcommand tree is\n// constructed, so cmd-ts only needs the bare version string here. The\n// rich version output (with project info, package manager, etc.) is\n// produced by `getPhCmdVersionInfo` along that short-circuit path.\nexport const ph = subcommands({\n name: \"ph\",\n version: getVersion(),\n description:\n \"The Powerhouse CLI (ph-cmd) is a command-line interface tool that provides essential commands for managing Powerhouse projects.\\nThe tool and it's commands are fundamental for creating, building, and running Document Models as a builder in studio mode.\",\n cmds: {\n init,\n use,\n update,\n \"setup-globals\": setupGlobals,\n \"use-local\": useLocal,\n ...phCliHelpCommands,\n },\n});\n","import { run as runCmdTs } from \"cmd-ts\";\nimport { ph } from \"./commands/ph.js\";\n\nexport async function run(args: string[]) {\n return await runCmdTs(ph, args);\n}\n"],"names":["runCmdTs"],"mappings":"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","debug_id":"8fd02ae1-0c73-50f0-847b-abb14891c6f3"}