@shopify/cli-kit 3.94.2 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/dist/private/node/api/headers.js +1 -1
  2. package/dist/private/node/api/headers.js.map +1 -1
  3. package/dist/private/node/conf-store.d.ts +3 -2
  4. package/dist/private/node/conf-store.js +3 -2
  5. package/dist/private/node/conf-store.js.map +1 -1
  6. package/dist/private/node/constants.d.ts +2 -1
  7. package/dist/private/node/constants.js +2 -1
  8. package/dist/private/node/constants.js.map +1 -1
  9. package/dist/private/node/ui/components/Alert.test.js +29 -0
  10. package/dist/private/node/ui/components/Alert.test.js.map +1 -1
  11. package/dist/private/node/ui/components/AutocompletePrompt.d.ts +8 -1
  12. package/dist/private/node/ui/components/AutocompletePrompt.js +3 -2
  13. package/dist/private/node/ui/components/AutocompletePrompt.js.map +1 -1
  14. package/dist/private/node/ui/components/AutocompletePrompt.test.js +16 -0
  15. package/dist/private/node/ui/components/AutocompletePrompt.test.js.map +1 -1
  16. package/dist/private/node/ui/components/FatalError.js +6 -1
  17. package/dist/private/node/ui/components/FatalError.js.map +1 -1
  18. package/dist/private/node/ui/components/FatalError.test.js +28 -0
  19. package/dist/private/node/ui/components/FatalError.test.js.map +1 -1
  20. package/dist/private/node/ui/components/Link.js +8 -4
  21. package/dist/private/node/ui/components/Link.js.map +1 -1
  22. package/dist/private/node/ui/components/Link.test.js +45 -0
  23. package/dist/private/node/ui/components/Link.test.js.map +1 -1
  24. package/dist/private/node/ui/components/TokenizedText.js +61 -2
  25. package/dist/private/node/ui/components/TokenizedText.js.map +1 -1
  26. package/dist/private/node/ui/components/TokenizedText.test.js +109 -2
  27. package/dist/private/node/ui/components/TokenizedText.test.js.map +1 -1
  28. package/dist/public/common/string.js +15 -19
  29. package/dist/public/common/string.js.map +1 -1
  30. package/dist/public/common/version.d.ts +1 -1
  31. package/dist/public/common/version.js +1 -1
  32. package/dist/public/common/version.js.map +1 -1
  33. package/dist/public/node/base-command.js +23 -14
  34. package/dist/public/node/base-command.js.map +1 -1
  35. package/dist/public/node/cli-launcher.d.ts +2 -0
  36. package/dist/public/node/cli-launcher.js +7 -3
  37. package/dist/public/node/cli-launcher.js.map +1 -1
  38. package/dist/public/node/cli.d.ts +5 -1
  39. package/dist/public/node/cli.js +3 -3
  40. package/dist/public/node/cli.js.map +1 -1
  41. package/dist/public/node/context/local.d.ts +8 -8
  42. package/dist/public/node/context/local.js +25 -15
  43. package/dist/public/node/context/local.js.map +1 -1
  44. package/dist/public/node/custom-oclif-loader.d.ts +31 -0
  45. package/dist/public/node/custom-oclif-loader.js +45 -0
  46. package/dist/public/node/custom-oclif-loader.js.map +1 -0
  47. package/dist/public/node/error.d.ts +1 -1
  48. package/dist/public/node/error.js +1 -1
  49. package/dist/public/node/error.js.map +1 -1
  50. package/dist/public/node/fs.js +12 -16
  51. package/dist/public/node/fs.js.map +1 -1
  52. package/dist/public/node/git.js +1 -2
  53. package/dist/public/node/git.js.map +1 -1
  54. package/dist/public/node/hooks/postrun.d.ts +15 -0
  55. package/dist/public/node/hooks/postrun.js +75 -14
  56. package/dist/public/node/hooks/postrun.js.map +1 -1
  57. package/dist/public/node/hooks/prerun.d.ts +1 -1
  58. package/dist/public/node/hooks/prerun.js +17 -10
  59. package/dist/public/node/hooks/prerun.js.map +1 -1
  60. package/dist/public/node/is-global.d.ts +1 -1
  61. package/dist/public/node/is-global.js +27 -11
  62. package/dist/public/node/is-global.js.map +1 -1
  63. package/dist/public/node/monorail.d.ts +2 -1
  64. package/dist/public/node/monorail.js +1 -1
  65. package/dist/public/node/monorail.js.map +1 -1
  66. package/dist/public/node/node-package-manager.d.ts +2 -2
  67. package/dist/public/node/node-package-manager.js +10 -10
  68. package/dist/public/node/node-package-manager.js.map +1 -1
  69. package/dist/public/node/notifications-system.d.ts +6 -6
  70. package/dist/public/node/output.js.map +1 -1
  71. package/dist/public/node/path.js +0 -2
  72. package/dist/public/node/path.js.map +1 -1
  73. package/dist/public/node/session.d.ts +6 -0
  74. package/dist/public/node/session.js +8 -0
  75. package/dist/public/node/session.js.map +1 -1
  76. package/dist/public/node/system.js +20 -3
  77. package/dist/public/node/system.js.map +1 -1
  78. package/dist/public/node/tree-kill.js +17 -5
  79. package/dist/public/node/tree-kill.js.map +1 -1
  80. package/dist/public/node/ui.js +6 -0
  81. package/dist/public/node/ui.js.map +1 -1
  82. package/dist/public/node/upgrade.d.ts +27 -8
  83. package/dist/public/node/upgrade.js +50 -21
  84. package/dist/public/node/upgrade.js.map +1 -1
  85. package/dist/tsconfig.tsbuildinfo +1 -1
  86. package/package.json +2 -2
@@ -1,12 +1,8 @@
1
- import { postrun as deprecationsHook } from './deprecations.js';
2
- import { reportAnalyticsEvent } from '../analytics.js';
3
- import { outputDebug, outputWarn } from '../output.js';
4
- import { getOutputUpdateCLIReminder, runCLIUpgrade, versionToAutoUpgrade, warnIfUpgradeAvailable } from '../upgrade.js';
5
- import { inferPackageManagerForGlobalCLI } from '../is-global.js';
6
- import * as metadata from '../metadata.js';
7
- import { runAtMinimumInterval } from '../../../private/node/conf-store.js';
8
- import { CLI_KIT_VERSION } from '../../common/version.js';
9
- import { isMajorVersionChange } from '../version.js';
1
+ /**
2
+ * Postrun hook uses dynamic imports to avoid loading heavy modules (base-command, analytics)
3
+ * at module evaluation time. These are only needed after the command has already finished.
4
+ */
5
+ import { treeKill } from '../tree-kill.js';
10
6
  let postRunHookCompleted = false;
11
7
  /**
12
8
  * Check if post run hook has completed.
@@ -16,16 +12,54 @@ let postRunHookCompleted = false;
16
12
  export function postRunHookHasCompleted() {
17
13
  return postRunHookCompleted;
18
14
  }
15
+ /**
16
+ * Wait for the postrun hook to finish (so auto-upgrade has a chance to run) and then
17
+ * tree-kill the current process tree before exiting.
18
+ *
19
+ * Long-running interactive commands like `app dev` need this when the user terminates
20
+ * the command via `q` or Ctrl+C. The dev sub-processes such as servers and watchers keep
21
+ * the event loop alive, so even after oclif's postrun hook completes the node process
22
+ * won't exit on its own and we have to `treeKill` the process tree. We must not do that
23
+ * before the postrun hook has actually finished running auto-upgrade, otherwise we would
24
+ * kill the upgrade mid-way while `npm install` is still running.
25
+ *
26
+ * The flag `postRunHookCompleted` is flipped at the very end of the hook after
27
+ * `autoUpgradeIfNeeded` resolves, so polling it here is safe.
28
+ */
29
+ export function waitForPostRunHookAndExit() {
30
+ const pollIntervalMs = 100;
31
+ // Auto-upgrade can take a while (npm/pnpm/yarn install). Cap the wait generously so
32
+ // a stuck upgrade still terminates the process eventually.
33
+ const maxWaitMs = 120000;
34
+ let elapsed = 0;
35
+ let terminating = false;
36
+ const handle = setInterval(() => {
37
+ if (terminating)
38
+ return;
39
+ if (postRunHookHasCompleted() || elapsed >= maxWaitMs) {
40
+ terminating = true;
41
+ clearInterval(handle);
42
+ treeKill(process.pid, 'SIGINT', false, () => {
43
+ process.exit(0);
44
+ });
45
+ return;
46
+ }
47
+ elapsed += pollIntervalMs;
48
+ }, pollIntervalMs);
49
+ }
19
50
  // This hook is called after each successful command run. More info: https://oclif.io/docs/hooks
20
51
  export const hook = async ({ config, Command }) => {
21
52
  await detectStopCommand(Command);
53
+ const { reportAnalyticsEvent } = await import('../analytics.js');
22
54
  await reportAnalyticsEvent({ config, exitMode: 'ok' });
55
+ const { postrun: deprecationsHook } = await import('./deprecations.js');
23
56
  deprecationsHook(Command);
57
+ const { outputDebug } = await import('../output.js');
24
58
  const command = Command.id.replace(/:/g, ' ');
25
59
  outputDebug(`Completed command ${command}`);
26
- postRunHookCompleted = true;
27
60
  if (!command.includes('notifications') && !command.includes('upgrade'))
28
61
  await autoUpgradeIfNeeded();
62
+ postRunHookCompleted = true;
29
63
  };
30
64
  /**
31
65
  * Auto-upgrades the CLI after a command completes, if a newer version is available.
@@ -34,6 +68,7 @@ export const hook = async ({ config, Command }) => {
34
68
  * @returns Resolves when the upgrade attempt (or fallback warning) is complete.
35
69
  */
36
70
  export async function autoUpgradeIfNeeded() {
71
+ const { versionToAutoUpgrade, warnIfUpgradeAvailable } = await import('../upgrade.js');
37
72
  const newerVersion = versionToAutoUpgrade();
38
73
  if (!newerVersion) {
39
74
  await warnIfUpgradeAvailable();
@@ -45,6 +80,7 @@ export async function autoUpgradeIfNeeded() {
45
80
  await performAutoUpgrade(newerVersion);
46
81
  }
47
82
  else {
83
+ const { runAtMinimumInterval } = await import('../../../private/node/conf-store.js');
48
84
  // Rate-limit the entire upgrade flow to once per day to avoid repeated attempts and major-version warnings.
49
85
  await runAtMinimumInterval('auto-upgrade', { days: 1 }, async () => {
50
86
  await performAutoUpgrade(newerVersion);
@@ -52,6 +88,13 @@ export async function autoUpgradeIfNeeded() {
52
88
  }
53
89
  }
54
90
  async function performAutoUpgrade(newerVersion) {
91
+ const [{ CLI_KIT_VERSION }, { isMajorVersionChange }, { outputWarn, outputDebug }, { getOutputUpdateCLIReminder, runCLIUpgrade, hasBlockingAutoUpgradeNotification }, metadata,] = await Promise.all([
92
+ import('../../common/version.js'),
93
+ import('../version.js'),
94
+ import('../output.js'),
95
+ import('../upgrade.js'),
96
+ import('../metadata.js'),
97
+ ]);
55
98
  if (isMajorVersionChange(CLI_KIT_VERSION, newerVersion)) {
56
99
  outputWarn(getOutputUpdateCLIReminder(newerVersion, true));
57
100
  await metadata.addPublicMetadata(() => ({
@@ -59,8 +102,18 @@ async function performAutoUpgrade(newerVersion) {
59
102
  }));
60
103
  return;
61
104
  }
105
+ // Notification kill switch: an `error`-type notification on the `autoupgrade` surface
106
+ // silently disables auto-upgrade. Checked last — after every other gate, including the
107
+ // daily rate limit and the major-version check — so the network fetch only happens when
108
+ // we're about to actually run the upgrade.
109
+ if (await hasBlockingAutoUpgradeNotification()) {
110
+ await metadata.addPublicMetadata(() => ({
111
+ env_auto_upgrade_skipped_reason: 'blocked_by_notification',
112
+ }));
113
+ return;
114
+ }
62
115
  try {
63
- await runCLIUpgrade();
116
+ await runCLIUpgrade({ autoupgrade: true });
64
117
  await metadata.addPublicMetadata(() => ({ env_auto_upgrade_success: true }));
65
118
  // eslint-disable-next-line no-catch-all/no-catch-all
66
119
  }
@@ -70,7 +123,10 @@ async function performAutoUpgrade(newerVersion) {
70
123
  outputWarn(getOutputUpdateCLIReminder(newerVersion));
71
124
  await metadata.addPublicMetadata(() => ({ env_auto_upgrade_success: false }));
72
125
  // Report to Observe as a handled error without showing anything extra to the user
73
- const { sendErrorToBugsnag } = await import('../error-handler.js');
126
+ const [{ sendErrorToBugsnag }, { inferPackageManagerForGlobalCLI }] = await Promise.all([
127
+ import('../error-handler.js'),
128
+ import('../is-global.js'),
129
+ ]);
74
130
  const enrichedError = Object.assign(new Error(errorMessage), {
75
131
  packageManager: inferPackageManagerForGlobalCLI(),
76
132
  platform: process.platform,
@@ -82,13 +138,18 @@ async function performAutoUpgrade(newerVersion) {
82
138
  /**
83
139
  * Override the command name with the stop one for analytics purposes.
84
140
  *
85
- * @param commandClass - Oclif command class.
141
+ * @param commandClass - Command.Class.
86
142
  */
87
143
  async function detectStopCommand(commandClass) {
88
144
  const currentTime = new Date().getTime();
89
- if (commandClass && Object.prototype.hasOwnProperty.call(commandClass, 'analyticsStopCommand')) {
145
+ // Check for analyticsStopCommand without importing BaseCommand
146
+ if (commandClass &&
147
+ 'analyticsStopCommand' in commandClass &&
148
+ typeof commandClass.analyticsStopCommand === 'function') {
149
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
90
150
  const stopCommand = commandClass.analyticsStopCommand();
91
151
  if (stopCommand) {
152
+ const metadata = await import('../metadata.js');
92
153
  const { commandStartOptions } = metadata.getAllSensitiveMetadata();
93
154
  if (!commandStartOptions)
94
155
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"postrun.js","sourceRoot":"","sources":["../../../../src/public/node/hooks/postrun.ts"],"names":[],"mappings":"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","sourcesContent":["import {postrun as deprecationsHook} from './deprecations.js'\nimport {reportAnalyticsEvent} from '../analytics.js'\nimport {outputDebug, outputWarn} from '../output.js'\nimport {getOutputUpdateCLIReminder, runCLIUpgrade, versionToAutoUpgrade, warnIfUpgradeAvailable} from '../upgrade.js'\nimport {inferPackageManagerForGlobalCLI} from '../is-global.js'\nimport BaseCommand from '../base-command.js'\nimport * as metadata from '../metadata.js'\nimport {runAtMinimumInterval} from '../../../private/node/conf-store.js'\nimport {CLI_KIT_VERSION} from '../../common/version.js'\nimport {isMajorVersionChange} from '../version.js'\nimport {Command, Hook} from '@oclif/core'\n\nlet postRunHookCompleted = false\n\n/**\n * Check if post run hook has completed.\n *\n * @returns Whether post run hook has completed.\n */\nexport function postRunHookHasCompleted(): boolean {\n return postRunHookCompleted\n}\n\n// This hook is called after each successful command run. More info: https://oclif.io/docs/hooks\nexport const hook: Hook.Postrun = async ({config, Command}) => {\n await detectStopCommand(Command as unknown as typeof Command)\n await reportAnalyticsEvent({config, exitMode: 'ok'})\n deprecationsHook(Command)\n\n const command = Command.id.replace(/:/g, ' ')\n outputDebug(`Completed command ${command}`)\n postRunHookCompleted = true\n\n if (!command.includes('notifications') && !command.includes('upgrade')) await autoUpgradeIfNeeded()\n}\n\n/**\n * Auto-upgrades the CLI after a command completes, if a newer version is available.\n * The entire flow is rate-limited to once per day unless forced via SHOPIFY_CLI_FORCE_AUTO_UPGRADE.\n *\n * @returns Resolves when the upgrade attempt (or fallback warning) is complete.\n */\nexport async function autoUpgradeIfNeeded(): Promise<void> {\n const newerVersion = versionToAutoUpgrade()\n if (!newerVersion) {\n await warnIfUpgradeAvailable()\n return\n }\n\n const forced = process.env.SHOPIFY_CLI_FORCE_AUTO_UPGRADE === '1'\n\n // SHOPIFY_CLI_FORCE_AUTO_UPGRADE bypasses the daily rate limit so tests and intentional upgrades always run.\n if (forced) {\n await performAutoUpgrade(newerVersion)\n } else {\n // Rate-limit the entire upgrade flow to once per day to avoid repeated attempts and major-version warnings.\n await runAtMinimumInterval('auto-upgrade', {days: 1}, async () => {\n await performAutoUpgrade(newerVersion)\n })\n }\n}\n\nasync function performAutoUpgrade(newerVersion: string): Promise<void> {\n if (isMajorVersionChange(CLI_KIT_VERSION, newerVersion)) {\n outputWarn(getOutputUpdateCLIReminder(newerVersion, true))\n await metadata.addPublicMetadata(() => ({\n env_auto_upgrade_skipped_reason: 'major_version',\n }))\n return\n }\n\n try {\n await runCLIUpgrade()\n await metadata.addPublicMetadata(() => ({env_auto_upgrade_success: true}))\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n const errorMessage = `Auto-upgrade failed: ${error}`\n outputDebug(errorMessage)\n outputWarn(getOutputUpdateCLIReminder(newerVersion))\n await metadata.addPublicMetadata(() => ({env_auto_upgrade_success: false}))\n // Report to Observe as a handled error without showing anything extra to the user\n const {sendErrorToBugsnag} = await import('../error-handler.js')\n const enrichedError = Object.assign(new Error(errorMessage), {\n packageManager: inferPackageManagerForGlobalCLI(),\n platform: process.platform,\n cliVersion: CLI_KIT_VERSION,\n })\n await sendErrorToBugsnag(enrichedError, 'expected_error')\n }\n}\n\n/**\n * Override the command name with the stop one for analytics purposes.\n *\n * @param commandClass - Oclif command class.\n */\nasync function detectStopCommand(commandClass: Command.Class | typeof BaseCommand): Promise<void> {\n const currentTime = new Date().getTime()\n if (commandClass && Object.prototype.hasOwnProperty.call(commandClass, 'analyticsStopCommand')) {\n const stopCommand = (commandClass as typeof BaseCommand).analyticsStopCommand()\n if (stopCommand) {\n const {commandStartOptions} = metadata.getAllSensitiveMetadata()\n if (!commandStartOptions) return\n await metadata.addSensitiveMetadata(() => ({\n commandStartOptions: {\n ...commandStartOptions,\n startTime: currentTime,\n startCommand: stopCommand,\n },\n }))\n }\n }\n}\n"]}
1
+ {"version":3,"file":"postrun.js","sourceRoot":"","sources":["../../../../src/public/node/hooks/postrun.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Postrun hook — uses dynamic imports to avoid loading heavy modules (base-command, analytics)\n * at module evaluation time. These are only needed after the command has already finished.\n */\nimport {treeKill} from '../tree-kill.js'\nimport {Command, Hook} from '@oclif/core'\n\nlet postRunHookCompleted = false\n\n/**\n * Check if post run hook has completed.\n *\n * @returns Whether post run hook has completed.\n */\nexport function postRunHookHasCompleted(): boolean {\n return postRunHookCompleted\n}\n\n/**\n * Wait for the postrun hook to finish (so auto-upgrade has a chance to run) and then\n * tree-kill the current process tree before exiting.\n *\n * Long-running interactive commands like `app dev` need this when the user terminates\n * the command via `q` or Ctrl+C. The dev sub-processes such as servers and watchers keep\n * the event loop alive, so even after oclif's postrun hook completes the node process\n * won't exit on its own and we have to `treeKill` the process tree. We must not do that\n * before the postrun hook has actually finished running auto-upgrade, otherwise we would\n * kill the upgrade mid-way while `npm install` is still running.\n *\n * The flag `postRunHookCompleted` is flipped at the very end of the hook after\n * `autoUpgradeIfNeeded` resolves, so polling it here is safe.\n */\nexport function waitForPostRunHookAndExit(): void {\n const pollIntervalMs = 100\n // Auto-upgrade can take a while (npm/pnpm/yarn install). Cap the wait generously so\n // a stuck upgrade still terminates the process eventually.\n const maxWaitMs = 120000\n\n let elapsed = 0\n let terminating = false\n const handle = setInterval(() => {\n if (terminating) return\n if (postRunHookHasCompleted() || elapsed >= maxWaitMs) {\n terminating = true\n clearInterval(handle)\n treeKill(process.pid, 'SIGINT', false, () => {\n process.exit(0)\n })\n return\n }\n elapsed += pollIntervalMs\n }, pollIntervalMs)\n}\n\n// This hook is called after each successful command run. More info: https://oclif.io/docs/hooks\nexport const hook: Hook.Postrun = async ({config, Command}) => {\n await detectStopCommand(Command as unknown as typeof Command)\n\n const {reportAnalyticsEvent} = await import('../analytics.js')\n await reportAnalyticsEvent({config, exitMode: 'ok'})\n\n const {postrun: deprecationsHook} = await import('./deprecations.js')\n deprecationsHook(Command)\n\n const {outputDebug} = await import('../output.js')\n const command = Command.id.replace(/:/g, ' ')\n outputDebug(`Completed command ${command}`)\n\n if (!command.includes('notifications') && !command.includes('upgrade')) await autoUpgradeIfNeeded()\n postRunHookCompleted = true\n}\n\n/**\n * Auto-upgrades the CLI after a command completes, if a newer version is available.\n * The entire flow is rate-limited to once per day unless forced via SHOPIFY_CLI_FORCE_AUTO_UPGRADE.\n *\n * @returns Resolves when the upgrade attempt (or fallback warning) is complete.\n */\nexport async function autoUpgradeIfNeeded(): Promise<void> {\n const {versionToAutoUpgrade, warnIfUpgradeAvailable} = await import('../upgrade.js')\n const newerVersion = versionToAutoUpgrade()\n if (!newerVersion) {\n await warnIfUpgradeAvailable()\n return\n }\n\n const forced = process.env.SHOPIFY_CLI_FORCE_AUTO_UPGRADE === '1'\n\n // SHOPIFY_CLI_FORCE_AUTO_UPGRADE bypasses the daily rate limit so tests and intentional upgrades always run.\n if (forced) {\n await performAutoUpgrade(newerVersion)\n } else {\n const {runAtMinimumInterval} = await import('../../../private/node/conf-store.js')\n // Rate-limit the entire upgrade flow to once per day to avoid repeated attempts and major-version warnings.\n await runAtMinimumInterval('auto-upgrade', {days: 1}, async () => {\n await performAutoUpgrade(newerVersion)\n })\n }\n}\n\nasync function performAutoUpgrade(newerVersion: string): Promise<void> {\n const [\n {CLI_KIT_VERSION},\n {isMajorVersionChange},\n {outputWarn, outputDebug},\n {getOutputUpdateCLIReminder, runCLIUpgrade, hasBlockingAutoUpgradeNotification},\n metadata,\n ] = await Promise.all([\n import('../../common/version.js'),\n import('../version.js'),\n import('../output.js'),\n import('../upgrade.js'),\n import('../metadata.js'),\n ])\n\n if (isMajorVersionChange(CLI_KIT_VERSION, newerVersion)) {\n outputWarn(getOutputUpdateCLIReminder(newerVersion, true))\n await metadata.addPublicMetadata(() => ({\n env_auto_upgrade_skipped_reason: 'major_version',\n }))\n return\n }\n\n // Notification kill switch: an `error`-type notification on the `autoupgrade` surface\n // silently disables auto-upgrade. Checked last — after every other gate, including the\n // daily rate limit and the major-version check — so the network fetch only happens when\n // we're about to actually run the upgrade.\n if (await hasBlockingAutoUpgradeNotification()) {\n await metadata.addPublicMetadata(() => ({\n env_auto_upgrade_skipped_reason: 'blocked_by_notification',\n }))\n return\n }\n\n try {\n await runCLIUpgrade({autoupgrade: true})\n await metadata.addPublicMetadata(() => ({env_auto_upgrade_success: true}))\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n const errorMessage = `Auto-upgrade failed: ${error}`\n outputDebug(errorMessage)\n outputWarn(getOutputUpdateCLIReminder(newerVersion))\n await metadata.addPublicMetadata(() => ({env_auto_upgrade_success: false}))\n // Report to Observe as a handled error without showing anything extra to the user\n const [{sendErrorToBugsnag}, {inferPackageManagerForGlobalCLI}] = await Promise.all([\n import('../error-handler.js'),\n import('../is-global.js'),\n ])\n const enrichedError = Object.assign(new Error(errorMessage), {\n packageManager: inferPackageManagerForGlobalCLI(),\n platform: process.platform,\n cliVersion: CLI_KIT_VERSION,\n })\n await sendErrorToBugsnag(enrichedError, 'expected_error')\n }\n}\n\n/**\n * Override the command name with the stop one for analytics purposes.\n *\n * @param commandClass - Command.Class.\n */\nasync function detectStopCommand(commandClass: Command.Class): Promise<void> {\n const currentTime = new Date().getTime()\n // Check for analyticsStopCommand without importing BaseCommand\n if (\n commandClass &&\n 'analyticsStopCommand' in commandClass &&\n typeof commandClass.analyticsStopCommand === 'function'\n ) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const stopCommand = (commandClass as any).analyticsStopCommand()\n if (stopCommand) {\n const metadata = await import('../metadata.js')\n const {commandStartOptions} = metadata.getAllSensitiveMetadata()\n if (!commandStartOptions) return\n await metadata.addSensitiveMetadata(() => ({\n commandStartOptions: {\n ...commandStartOptions,\n startTime: currentTime,\n startCommand: stopCommand,\n },\n }))\n }\n }\n}\n"]}
@@ -14,4 +14,4 @@ export declare function parseCommandContent(cmdInfo: {
14
14
  * Triggers a background check for a newer CLI version (non-blocking).
15
15
  * The result is cached and consumed by the postrun hook for auto-upgrade.
16
16
  */
17
- export declare function checkForNewVersionInBackground(): void;
17
+ export declare function checkForNewVersionInBackground(): Promise<void>;
@@ -1,9 +1,3 @@
1
- import { CLI_KIT_VERSION } from '../../common/version.js';
2
- import { isPreReleaseVersion } from '../version.js';
3
- import { checkForNewVersion } from '../node-package-manager.js';
4
- import { startAnalytics } from '../../../private/node/analytics.js';
5
- import { outputDebug } from '../output.js';
6
- import { fetchNotificationsInBackground } from '../notifications-system.js';
7
1
  // This hook is called before each command run. More info: https://oclif.io/docs/hooks
8
2
  export const hook = async (options) => {
9
3
  const commandContent = parseCommandContent({
@@ -12,10 +6,18 @@ export const hook = async (options) => {
12
6
  pluginAlias: options.Command.plugin?.alias,
13
7
  });
14
8
  const args = options.argv;
15
- checkForNewVersionInBackground();
9
+ // Load heavy modules in parallel
10
+ const [{ outputDebug }, analyticsMod, notificationsMod] = await Promise.all([
11
+ import('../output.js'),
12
+ import('../../../private/node/analytics.js'),
13
+ import('../notifications-system.js'),
14
+ ]);
15
+ // Fire upgrade check in background (non-blocking)
16
+ // eslint-disable-next-line no-void
17
+ void checkForNewVersionInBackground();
16
18
  outputDebug(`Running command ${commandContent.command}`);
17
- await startAnalytics({ commandContent, args, commandClass: options.Command });
18
- fetchNotificationsInBackground(options.Command.id);
19
+ await analyticsMod.startAnalytics({ commandContent, args, commandClass: options.Command });
20
+ notificationsMod.fetchNotificationsInBackground(options.Command.id);
19
21
  };
20
22
  export function parseCommandContent(cmdInfo) {
21
23
  let commandContent = parseCreateCommand(cmdInfo.pluginAlias);
@@ -71,7 +73,12 @@ function findAlias(aliases) {
71
73
  * Triggers a background check for a newer CLI version (non-blocking).
72
74
  * The result is cached and consumed by the postrun hook for auto-upgrade.
73
75
  */
74
- export function checkForNewVersionInBackground() {
76
+ export async function checkForNewVersionInBackground() {
77
+ const [{ CLI_KIT_VERSION }, { isPreReleaseVersion }, { checkForNewVersion }] = await Promise.all([
78
+ import('../../common/version.js'),
79
+ import('../version.js'),
80
+ import('../node-package-manager.js'),
81
+ ]);
75
82
  const currentVersion = CLI_KIT_VERSION;
76
83
  if (isPreReleaseVersion(currentVersion)) {
77
84
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"prerun.js","sourceRoot":"","sources":["../../../../src/public/node/hooks/prerun.ts"],"names":[],"mappings":"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","sourcesContent":["import {CLI_KIT_VERSION} from '../../common/version.js'\nimport {isPreReleaseVersion} from '../version.js'\nimport {checkForNewVersion} from '../node-package-manager.js'\nimport {startAnalytics} from '../../../private/node/analytics.js'\nimport {outputDebug} from '../output.js'\nimport Command from '../base-command.js'\nimport {fetchNotificationsInBackground} from '../notifications-system.js'\nimport {Hook} from '@oclif/core'\n\nexport declare interface CommandContent {\n command: string\n topic?: string\n alias?: string\n}\n// This hook is called before each command run. More info: https://oclif.io/docs/hooks\nexport const hook: Hook.Prerun = async (options) => {\n const commandContent = parseCommandContent({\n id: options.Command.id,\n aliases: options.Command.aliases,\n pluginAlias: options.Command.plugin?.alias,\n })\n const args = options.argv\n checkForNewVersionInBackground()\n outputDebug(`Running command ${commandContent.command}`)\n await startAnalytics({commandContent, args, commandClass: options.Command as unknown as typeof Command})\n fetchNotificationsInBackground(options.Command.id)\n}\n\nexport function parseCommandContent(cmdInfo: {id: string; aliases: string[]; pluginAlias?: string}): CommandContent {\n let commandContent = parseCreateCommand(cmdInfo.pluginAlias)\n commandContent ??= parseNormalCommand(cmdInfo.id, cmdInfo.aliases)\n return commandContent\n}\n\nfunction parseNormalCommand(id: string, aliases: string[]): CommandContent {\n return {\n command: id.replace(/:/g, ' '),\n topic: parseTopic(id),\n alias: findAlias(aliases),\n }\n}\n\n/**\n * Create commands implement Init by default, so the name of the command must be extracted from\n * the plugin/module name. Neither alias or topic are supported\n *\n * @param commandClass - Oclif command configuration\n * @returns Command content with the name of the command or undefined otherwise\n */\nfunction parseCreateCommand(pluginAlias?: string): CommandContent | undefined {\n if (!pluginAlias?.startsWith('@shopify/create-')) {\n return undefined\n }\n\n return {command: pluginAlias.substring(pluginAlias.indexOf('/') + 1)}\n}\n\n/**\n * Commands use this pattern topic:subtopic1:...:subtopicN:command. This method extract the topic and subtopic\n * information replacing the ':' separator with one space\n *\n * @param cmd - Complete command string to extract the topic information\n * @returns The topic name or undefined otherwise\n */\nfunction parseTopic(cmd: string) {\n if (cmd.lastIndexOf(':') === -1) {\n return\n }\n return cmd.slice(0, cmd.lastIndexOf(':')).replace(/:/g, ' ')\n}\n\n/**\n * Identifies if the command was launched using an alias instead of the oficial command name\n *\n * @param aliases - List of possible alias a command has\n * @returns The alias used or undefined otherwise\n */\nfunction findAlias(aliases: string[]) {\n const existingAlias = aliases.find((alias) =>\n alias.split(':').every((aliasToken) => process.argv.includes(aliasToken)),\n )\n if (existingAlias) {\n return existingAlias.replace(/:/g, ' ')\n }\n}\n\n/**\n * Triggers a background check for a newer CLI version (non-blocking).\n * The result is cached and consumed by the postrun hook for auto-upgrade.\n */\nexport function checkForNewVersionInBackground(): void {\n const currentVersion = CLI_KIT_VERSION\n if (isPreReleaseVersion(currentVersion)) {\n return\n }\n // eslint-disable-next-line no-void\n void checkForNewVersion('@shopify/cli', currentVersion, {cacheExpiryInHours: 24})\n}\n"]}
1
+ {"version":3,"file":"prerun.js","sourceRoot":"","sources":["../../../../src/public/node/hooks/prerun.ts"],"names":[],"mappings":"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","sourcesContent":["import {Hook} from '@oclif/core'\n\nexport declare interface CommandContent {\n command: string\n topic?: string\n alias?: string\n}\n\n// This hook is called before each command run. More info: https://oclif.io/docs/hooks\nexport const hook: Hook.Prerun = async (options) => {\n const commandContent = parseCommandContent({\n id: options.Command.id,\n aliases: options.Command.aliases,\n pluginAlias: options.Command.plugin?.alias,\n })\n const args = options.argv\n\n // Load heavy modules in parallel\n const [{outputDebug}, analyticsMod, notificationsMod] = await Promise.all([\n import('../output.js'),\n import('../../../private/node/analytics.js'),\n import('../notifications-system.js'),\n ])\n\n // Fire upgrade check in background (non-blocking)\n // eslint-disable-next-line no-void\n void checkForNewVersionInBackground()\n\n outputDebug(`Running command ${commandContent.command}`)\n await analyticsMod.startAnalytics({commandContent, args, commandClass: options.Command})\n notificationsMod.fetchNotificationsInBackground(options.Command.id)\n}\n\nexport function parseCommandContent(cmdInfo: {id: string; aliases: string[]; pluginAlias?: string}): CommandContent {\n let commandContent = parseCreateCommand(cmdInfo.pluginAlias)\n commandContent ??= parseNormalCommand(cmdInfo.id, cmdInfo.aliases)\n return commandContent\n}\n\nfunction parseNormalCommand(id: string, aliases: string[]): CommandContent {\n return {\n command: id.replace(/:/g, ' '),\n topic: parseTopic(id),\n alias: findAlias(aliases),\n }\n}\n\n/**\n * Create commands implement Init by default, so the name of the command must be extracted from\n * the plugin/module name. Neither alias or topic are supported\n *\n * @param commandClass - Oclif command configuration\n * @returns Command content with the name of the command or undefined otherwise\n */\nfunction parseCreateCommand(pluginAlias?: string): CommandContent | undefined {\n if (!pluginAlias?.startsWith('@shopify/create-')) {\n return undefined\n }\n\n return {command: pluginAlias.substring(pluginAlias.indexOf('/') + 1)}\n}\n\n/**\n * Commands use this pattern topic:subtopic1:...:subtopicN:command. This method extract the topic and subtopic\n * information replacing the ':' separator with one space\n *\n * @param cmd - Complete command string to extract the topic information\n * @returns The topic name or undefined otherwise\n */\nfunction parseTopic(cmd: string) {\n if (cmd.lastIndexOf(':') === -1) {\n return\n }\n return cmd.slice(0, cmd.lastIndexOf(':')).replace(/:/g, ' ')\n}\n\n/**\n * Identifies if the command was launched using an alias instead of the oficial command name\n *\n * @param aliases - List of possible alias a command has\n * @returns The alias used or undefined otherwise\n */\nfunction findAlias(aliases: string[]) {\n const existingAlias = aliases.find((alias) =>\n alias.split(':').every((aliasToken) => process.argv.includes(aliasToken)),\n )\n if (existingAlias) {\n return existingAlias.replace(/:/g, ' ')\n }\n}\n\n/**\n * Triggers a background check for a newer CLI version (non-blocking).\n * The result is cached and consumed by the postrun hook for auto-upgrade.\n */\nexport async function checkForNewVersionInBackground(): Promise<void> {\n const [{CLI_KIT_VERSION}, {isPreReleaseVersion}, {checkForNewVersion}] = await Promise.all([\n import('../../common/version.js'),\n import('../version.js'),\n import('../node-package-manager.js'),\n ])\n const currentVersion = CLI_KIT_VERSION\n if (isPreReleaseVersion(currentVersion)) {\n return\n }\n // eslint-disable-next-line no-void\n void checkForNewVersion('@shopify/cli', currentVersion, {cacheExpiryInHours: 24})\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { PackageManager } from './node-package-manager.js';
1
+ import type { PackageManager } from './node-package-manager.js';
2
2
  /**
3
3
  * Returns true if the current process is running in a global context.
4
4
  *
@@ -1,8 +1,4 @@
1
- import { outputInfo } from './output.js';
2
- import { cwd, dirname, joinPath, sniffForPath } from './path.js';
3
- import { exec, terminalSupportsPrompting } from './system.js';
4
- import { renderSelectPrompt } from './ui.js';
5
- import { globalCLIVersion } from './version.js';
1
+ import { cwd, dirname, isSubpath, joinPath, sniffForPath } from './path.js';
6
2
  import { isUnitTest } from './context/local.js';
7
3
  import { findPathUpSync, globSync } from './fs.js';
8
4
  import { realpathSync } from 'fs';
@@ -26,8 +22,16 @@ export function currentProcessIsGlobal(argv = process.argv) {
26
22
  }
27
23
  // From node docs: "The second element [of the array] will be the path to the JavaScript file being executed"
28
24
  const binDir = argv[1] ?? '';
29
- // If binDir starts with projectDir, then we are running a local CLI
30
- const isLocal = binDir.startsWith(projectDir.trim());
25
+ if (!binDir) {
26
+ return true;
27
+ }
28
+ // If binDir lives inside projectDir, we are running a local CLI.
29
+ // Use isSubpath (pathe.relative under the hood) instead of a raw
30
+ // string startsWith: projectDir flows through normalizePath and is
31
+ // forward-slash on every platform, while argv[1] is OS-native, so on
32
+ // Windows it arrives backslash-separated and a naive startsWith would
33
+ // misclassify a local install as global.
34
+ const isLocal = isSubpath(projectDir.trim(), binDir);
31
35
  _isGlobal = !isLocal;
32
36
  return _isGlobal;
33
37
  // eslint-disable-next-line no-catch-all/no-catch-all
@@ -42,6 +46,8 @@ export function currentProcessIsGlobal(argv = process.argv) {
42
46
  * @param packageManager - The package manager to use.
43
47
  */
44
48
  export async function installGlobalShopifyCLI(packageManager) {
49
+ const { outputInfo } = await import('./output.js');
50
+ const { exec } = await import('./system.js');
45
51
  const args = packageManager === 'yarn' ? ['global', 'add', '@shopify/cli@latest'] : ['install', '-g', '@shopify/cli@latest'];
46
52
  outputInfo(`Running ${packageManager} ${args.join(' ')}...`);
47
53
  await exec(packageManager, args, { stdio: 'inherit' });
@@ -52,11 +58,14 @@ export async function installGlobalShopifyCLI(packageManager) {
52
58
  * @returns `true` if the user has installed the global CLI.
53
59
  */
54
60
  export async function installGlobalCLIPrompt() {
61
+ const { terminalSupportsPrompting } = await import('./system.js');
55
62
  if (!terminalSupportsPrompting())
56
63
  return { install: false, alreadyInstalled: false };
64
+ const { globalCLIVersion } = await import('./version.js');
57
65
  if (await globalCLIVersion()) {
58
66
  return { install: false, alreadyInstalled: true };
59
67
  }
68
+ const { renderSelectPrompt } = await import('./ui.js');
60
69
  const result = await renderSelectPrompt({
61
70
  message: 'We recommend installing Shopify CLI globally in your system. Would you like to install it now?',
62
71
  choices: [
@@ -81,8 +90,9 @@ export function inferPackageManagerForGlobalCLI(argv = process.argv, env = proce
81
90
  return 'homebrew';
82
91
  }
83
92
  const processArgv = argv[1] ?? '';
93
+ const symlinkPath = processArgv.toLowerCase();
84
94
  // Resolve symlinks to get the real path of the binary.
85
- let realPath = processArgv.toLowerCase();
95
+ let realPath = symlinkPath;
86
96
  try {
87
97
  realPath = realpathSync(processArgv).toLowerCase();
88
98
  // eslint-disable-next-line no-catch-all/no-catch-all
@@ -90,11 +100,17 @@ export function inferPackageManagerForGlobalCLI(argv = process.argv, env = proce
90
100
  catch (error) {
91
101
  // fall back to using the original path for detection
92
102
  }
93
- if (realPath.includes('yarn'))
103
+ // Inspect both the (unresolved) symlink path and the resolved real path. Some
104
+ // package managers — notably bun (`~/.bun/bin/<name>`) — install global binaries
105
+ // as symlinks pointing into a generic `node_modules` directory whose real path
106
+ // no longer contains the package manager name. The original symlink under the
107
+ // PM's bin dir is the most reliable signal in that case.
108
+ const matches = (needle) => realPath.includes(needle) || symlinkPath.includes(needle);
109
+ if (matches('yarn'))
94
110
  return 'yarn';
95
- if (realPath.includes('pnpm'))
111
+ if (matches('pnpm'))
96
112
  return 'pnpm';
97
- if (realPath.includes('bun'))
113
+ if (matches('bun'))
98
114
  return 'bun';
99
115
  // Check for Homebrew via Cellar path (resolved symlink)
100
116
  if (realPath.includes('/cellar/'))
@@ -1 +1 @@
1
- {"version":3,"file":"is-global.js","sourceRoot":"","sources":["../../../src/public/node/is-global.ts"],"names":[],"mappings":"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","sourcesContent":["import {PackageManager} from './node-package-manager.js'\nimport {outputInfo} from './output.js'\nimport {cwd, dirname, joinPath, sniffForPath} from './path.js'\nimport {exec, terminalSupportsPrompting} from './system.js'\nimport {renderSelectPrompt} from './ui.js'\nimport {globalCLIVersion} from './version.js'\nimport {isUnitTest} from './context/local.js'\nimport {findPathUpSync, globSync} from './fs.js'\nimport {realpathSync} from 'fs'\n\nlet _isGlobal: boolean | undefined\n\n/**\n * Returns true if the current process is running in a global context.\n *\n * @param argv - The arguments passed to the process.\n * @returns `true` if the current process is running in a global context.\n */\nexport function currentProcessIsGlobal(argv = process.argv): boolean {\n // If we are running tests, we need to disable the cache\n try {\n if (_isGlobal !== undefined && !isUnitTest()) return _isGlobal\n\n // Path where the current project is (app/hydrogen)\n const path = sniffForPath() ?? cwd()\n\n const projectDir = getProjectDir(path)\n if (!projectDir) {\n return true\n }\n\n // From node docs: \"The second element [of the array] will be the path to the JavaScript file being executed\"\n const binDir = argv[1] ?? ''\n\n // If binDir starts with projectDir, then we are running a local CLI\n const isLocal = binDir.startsWith(projectDir.trim())\n\n _isGlobal = !isLocal\n return _isGlobal\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n return false\n }\n}\n\n/**\n * Installs the global Shopify CLI, using the provided package manager.\n *\n * @param packageManager - The package manager to use.\n */\nexport async function installGlobalShopifyCLI(packageManager: PackageManager): Promise<void> {\n const args =\n packageManager === 'yarn' ? ['global', 'add', '@shopify/cli@latest'] : ['install', '-g', '@shopify/cli@latest']\n outputInfo(`Running ${packageManager} ${args.join(' ')}...`)\n await exec(packageManager, args, {stdio: 'inherit'})\n}\n\nexport interface InstallGlobalCLIPromptResult {\n install: boolean\n alreadyInstalled: boolean\n}\n/**\n * Prompts the user to install the global CLI.\n *\n * @returns `true` if the user has installed the global CLI.\n */\nexport async function installGlobalCLIPrompt(): Promise<InstallGlobalCLIPromptResult> {\n if (!terminalSupportsPrompting()) return {install: false, alreadyInstalled: false}\n if (await globalCLIVersion()) {\n return {install: false, alreadyInstalled: true}\n }\n const result = await renderSelectPrompt({\n message: 'We recommend installing Shopify CLI globally in your system. Would you like to install it now?',\n choices: [\n {value: 'yes', label: 'Yes'},\n {value: 'no', label: 'No, just for this project'},\n ],\n })\n\n return {install: result === 'yes', alreadyInstalled: false}\n}\n\n/**\n * Infers the package manager used by the global CLI.\n *\n * @param argv - The arguments passed to the process.\n * @param env - The environment variables of the process.\n * @returns The package manager used by the global CLI.\n */\nexport function inferPackageManagerForGlobalCLI(argv = process.argv, env = process.env): PackageManager {\n if (!currentProcessIsGlobal(argv)) return 'unknown'\n\n // Check for Homebrew first (most reliable via environment variable)\n if (env.SHOPIFY_HOMEBREW_FORMULA) {\n return 'homebrew'\n }\n\n const processArgv = argv[1] ?? ''\n\n // Resolve symlinks to get the real path of the binary.\n let realPath = processArgv.toLowerCase()\n try {\n realPath = realpathSync(processArgv).toLowerCase()\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n // fall back to using the original path for detection\n }\n\n if (realPath.includes('yarn')) return 'yarn'\n if (realPath.includes('pnpm')) return 'pnpm'\n if (realPath.includes('bun')) return 'bun'\n\n // Check for Homebrew via Cellar path (resolved symlink)\n if (realPath.includes('/cellar/')) return 'homebrew'\n\n return 'npm'\n}\n\n/**\n * Returns the project directory for the given path.\n *\n * @param directory - The path to search upward from.\n * @returns The project root directory, or undefined if not found.\n */\nexport function getProjectDir(directory: string): string | undefined {\n const configFiles = ['shopify.app{,.*}.toml', 'hydrogen.config.js', 'hydrogen.config.ts']\n const existsConfigFile = (directory: string) => {\n const configPaths = globSync(configFiles.map((file) => joinPath(directory, file)))\n return configPaths.length > 0 ? configPaths[0] : undefined\n }\n try {\n const configFile = findPathUpSync(existsConfigFile, {\n cwd: directory,\n type: 'file',\n })\n if (configFile) return dirname(configFile)\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n return undefined\n }\n}\n"]}
1
+ {"version":3,"file":"is-global.js","sourceRoot":"","sources":["../../../src/public/node/is-global.ts"],"names":[],"mappings":"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","sourcesContent":["import {cwd, dirname, isSubpath, joinPath, sniffForPath} from './path.js'\nimport {isUnitTest} from './context/local.js'\nimport {findPathUpSync, globSync} from './fs.js'\nimport {realpathSync} from 'fs'\nimport type {PackageManager} from './node-package-manager.js'\n\nlet _isGlobal: boolean | undefined\n\n/**\n * Returns true if the current process is running in a global context.\n *\n * @param argv - The arguments passed to the process.\n * @returns `true` if the current process is running in a global context.\n */\nexport function currentProcessIsGlobal(argv = process.argv): boolean {\n // If we are running tests, we need to disable the cache\n try {\n if (_isGlobal !== undefined && !isUnitTest()) return _isGlobal\n\n // Path where the current project is (app/hydrogen)\n const path = sniffForPath() ?? cwd()\n\n const projectDir = getProjectDir(path)\n if (!projectDir) {\n return true\n }\n\n // From node docs: \"The second element [of the array] will be the path to the JavaScript file being executed\"\n const binDir = argv[1] ?? ''\n if (!binDir) {\n return true\n }\n\n // If binDir lives inside projectDir, we are running a local CLI.\n // Use isSubpath (pathe.relative under the hood) instead of a raw\n // string startsWith: projectDir flows through normalizePath and is\n // forward-slash on every platform, while argv[1] is OS-native, so on\n // Windows it arrives backslash-separated and a naive startsWith would\n // misclassify a local install as global.\n const isLocal = isSubpath(projectDir.trim(), binDir)\n\n _isGlobal = !isLocal\n return _isGlobal\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n return false\n }\n}\n\n/**\n * Installs the global Shopify CLI, using the provided package manager.\n *\n * @param packageManager - The package manager to use.\n */\nexport async function installGlobalShopifyCLI(packageManager: PackageManager): Promise<void> {\n const {outputInfo} = await import('./output.js')\n const {exec} = await import('./system.js')\n const args =\n packageManager === 'yarn' ? ['global', 'add', '@shopify/cli@latest'] : ['install', '-g', '@shopify/cli@latest']\n outputInfo(`Running ${packageManager} ${args.join(' ')}...`)\n await exec(packageManager, args, {stdio: 'inherit'})\n}\n\nexport interface InstallGlobalCLIPromptResult {\n install: boolean\n alreadyInstalled: boolean\n}\n/**\n * Prompts the user to install the global CLI.\n *\n * @returns `true` if the user has installed the global CLI.\n */\nexport async function installGlobalCLIPrompt(): Promise<InstallGlobalCLIPromptResult> {\n const {terminalSupportsPrompting} = await import('./system.js')\n if (!terminalSupportsPrompting()) return {install: false, alreadyInstalled: false}\n const {globalCLIVersion} = await import('./version.js')\n if (await globalCLIVersion()) {\n return {install: false, alreadyInstalled: true}\n }\n const {renderSelectPrompt} = await import('./ui.js')\n const result = await renderSelectPrompt({\n message: 'We recommend installing Shopify CLI globally in your system. Would you like to install it now?',\n choices: [\n {value: 'yes', label: 'Yes'},\n {value: 'no', label: 'No, just for this project'},\n ],\n })\n\n return {install: result === 'yes', alreadyInstalled: false}\n}\n\n/**\n * Infers the package manager used by the global CLI.\n *\n * @param argv - The arguments passed to the process.\n * @param env - The environment variables of the process.\n * @returns The package manager used by the global CLI.\n */\nexport function inferPackageManagerForGlobalCLI(argv = process.argv, env = process.env): PackageManager {\n if (!currentProcessIsGlobal(argv)) return 'unknown'\n\n // Check for Homebrew first (most reliable via environment variable)\n if (env.SHOPIFY_HOMEBREW_FORMULA) {\n return 'homebrew'\n }\n\n const processArgv = argv[1] ?? ''\n const symlinkPath = processArgv.toLowerCase()\n\n // Resolve symlinks to get the real path of the binary.\n let realPath = symlinkPath\n try {\n realPath = realpathSync(processArgv).toLowerCase()\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n // fall back to using the original path for detection\n }\n\n // Inspect both the (unresolved) symlink path and the resolved real path. Some\n // package managers — notably bun (`~/.bun/bin/<name>`) — install global binaries\n // as symlinks pointing into a generic `node_modules` directory whose real path\n // no longer contains the package manager name. The original symlink under the\n // PM's bin dir is the most reliable signal in that case.\n const matches = (needle: string) => realPath.includes(needle) || symlinkPath.includes(needle)\n\n if (matches('yarn')) return 'yarn'\n if (matches('pnpm')) return 'pnpm'\n if (matches('bun')) return 'bun'\n\n // Check for Homebrew via Cellar path (resolved symlink)\n if (realPath.includes('/cellar/')) return 'homebrew'\n\n return 'npm'\n}\n\n/**\n * Returns the project directory for the given path.\n *\n * @param directory - The path to search upward from.\n * @returns The project root directory, or undefined if not found.\n */\nexport function getProjectDir(directory: string): string | undefined {\n const configFiles = ['shopify.app{,.*}.toml', 'hydrogen.config.js', 'hydrogen.config.ts']\n const existsConfigFile = (directory: string) => {\n const configPaths = globSync(configFiles.map((file) => joinPath(directory, file)))\n return configPaths.length > 0 ? configPaths[0] : undefined\n }\n try {\n const configFile = findPathUpSync(existsConfigFile, {\n cwd: directory,\n type: 'file',\n })\n if (configFile) return dirname(configFile)\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n return undefined\n }\n}\n"]}
@@ -2,7 +2,7 @@ import { JsonMap } from '../../private/common/json.js';
2
2
  import { DeepRequired } from '../common/ts/deep-required.js';
3
3
  export { DeepRequired };
4
4
  type Optional<T> = T | null;
5
- export declare const MONORAIL_COMMAND_TOPIC = "app_cli3_command/1.22";
5
+ export declare const MONORAIL_COMMAND_TOPIC = "app_cli3_command/1.24";
6
6
  export interface Schemas {
7
7
  [MONORAIL_COMMAND_TOPIC]: {
8
8
  sensitive: {
@@ -32,6 +32,7 @@ export interface Schemas {
32
32
  node_version: string;
33
33
  is_employee: boolean;
34
34
  store_fqdn_hash?: Optional<string>;
35
+ store_fqdn_validated?: Optional<boolean>;
35
36
  user_id: string;
36
37
  cmd_all_alias_used?: Optional<string>;
37
38
  cmd_all_launcher?: Optional<string>;
@@ -2,7 +2,7 @@ import { fetch } from './http.js';
2
2
  import { outputDebug, outputContent, outputToken } from './output.js';
3
3
  const url = 'https://monorail-edge.shopifysvc.com/v1/produce';
4
4
  // This is the topic name of the main event we log to Monorail, the command tracker
5
- export const MONORAIL_COMMAND_TOPIC = 'app_cli3_command/1.22';
5
+ export const MONORAIL_COMMAND_TOPIC = 'app_cli3_command/1.24';
6
6
  const publishedCommandNames = new Set();
7
7
  /**
8
8
  * Publishes an event to Monorail.
@@ -1 +1 @@
1
- {"version":3,"file":"monorail.js","sourceRoot":"","sources":["../../../src/public/node/monorail.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,WAAW,CAAA;AAC/B,OAAO,EAAC,WAAW,EAAE,aAAa,EAAE,WAAW,EAAC,MAAM,aAAa,CAAA;AAMnE,MAAM,GAAG,GAAG,iDAAiD,CAAA;AAI7D,mFAAmF;AACnF,MAAM,CAAC,MAAM,sBAAsB,GAAG,uBAAuB,CAAA;AAkL7D,MAAM,qBAAqB,GAAG,IAAI,GAAG,EAAU,CAAA;AAE/C;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,QAAmB,EACnB,UAA8B,EAC9B,aAAoC;IAEpC,qHAAqH;IACrH,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,CAAA;IACtC,IAAI,WAAW,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;QACnD,IAAI,qBAAqB,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YAC3C,OAAO,EAAC,IAAI,EAAE,IAAI,EAAC,CAAA;QACrB,CAAC;QACD,qBAAqB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IACxC,CAAC;IAED,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAA;QACxC,MAAM,OAAO,GAAG,EAAC,GAAG,UAAU,EAAE,GAAG,aAAa,EAAC,CAAA;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAC,CAAC,CAAA;QAC3D,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,CAAC,CAAA;QAEzC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAC,EAAE,cAAc,CAAC,CAAA;QAElF,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,WAAW,CAAC,aAAa,CAAA,yBAAyB,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAA;YAC/F,OAAO,EAAC,IAAI,EAAE,IAAI,EAAC,CAAA;QACrB,CAAC;aAAM,CAAC;YACN,WAAW,CAAC,qCAAqC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAA;YACvE,OAAO,EAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,UAAU,EAAC,CAAA;QACtD,CAAC;QACD,qDAAqD;IACvD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,OAAO,GAAG,kCAAkC,CAAA;QAChD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;QAChD,CAAC;QACD,WAAW,CAAC,OAAO,CAAC,CAAA;QACpB,OAAO,EAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAC,CAAA;IACjC,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,eAAe,CAAmB,OAAU;IACnD,MAAM,MAAM,GAAG,EAAC,GAAG,OAAO,EAAC,CAAA;IAC3B,IAAI,SAAS,IAAI,MAAM,EAAE,CAAC;QACxB,MAAM,CAAC,OAAO,GAAG,MAAM,CAAA;IACzB,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,YAAY,GAAG,CAAC,WAAmB,EAAE,EAAE;IAC3C,OAAO;QACL,cAAc,EAAE,iCAAiC;QACjD,qCAAqC,EAAE,WAAW,CAAC,QAAQ,EAAE;QAC7D,kCAAkC,EAAE,WAAW,CAAC,QAAQ,EAAE;KAC3D,CAAA;AACH,CAAC,CAAA","sourcesContent":["import {fetch} from './http.js'\nimport {outputDebug, outputContent, outputToken} from './output.js'\nimport {JsonMap} from '../../private/common/json.js'\nimport {DeepRequired} from '../common/ts/deep-required.js'\n\nexport {DeepRequired}\n\nconst url = 'https://monorail-edge.shopifysvc.com/v1/produce'\n\ntype Optional<T> = T | null\n\n// This is the topic name of the main event we log to Monorail, the command tracker\nexport const MONORAIL_COMMAND_TOPIC = 'app_cli3_command/1.22'\n\nexport interface Schemas {\n [MONORAIL_COMMAND_TOPIC]: {\n sensitive: {\n args: string\n error_message?: Optional<string>\n app_name?: Optional<string>\n metadata?: Optional<string>\n store_fqdn?: Optional<string>\n cmd_all_environment_flags?: Optional<string>\n\n // Dev related commands\n cmd_dev_tunnel_custom?: Optional<string>\n\n // Environment\n env_plugin_installed_all?: Optional<string>\n env_shopify_variables?: Optional<string>\n }\n public: {\n business_platform_id?: Optional<number>\n partner_id?: Optional<number>\n command: string\n project_type?: Optional<string>\n time_start: number\n time_end: number\n total_time: number\n success: boolean\n api_key?: Optional<string>\n cli_version: string\n uname: string\n ruby_version: string\n node_version: string\n is_employee: boolean\n store_fqdn_hash?: Optional<string>\n user_id: string\n\n // Any and all commands\n cmd_all_alias_used?: Optional<string>\n cmd_all_launcher?: Optional<string>\n cmd_all_path_override?: Optional<boolean>\n cmd_all_path_override_hash?: Optional<string>\n cmd_all_plugin?: Optional<string>\n cmd_all_topic?: Optional<string>\n cmd_all_verbose?: Optional<boolean>\n cmd_all_exit?: Optional<string>\n cmd_all_force?: Optional<boolean>\n cmd_all_last_graphql_request_id?: Optional<string>\n\n cmd_all_timing_network_ms?: Optional<number>\n cmd_all_timing_prompts_ms?: Optional<number>\n cmd_all_timing_active_ms?: Optional<number>\n\n // Auto-upgrade\n env_auto_upgrade_enabled?: Optional<boolean>\n env_auto_upgrade_accepted?: Optional<boolean>\n env_auto_upgrade_skipped_reason?: Optional<string>\n env_auto_upgrade_success?: Optional<boolean>\n\n // Any extension related command\n cmd_extensions_binary_from_source?: Optional<boolean>\n\n // Scaffolding related commands\n cmd_scaffold_required_auth?: Optional<boolean>\n cmd_scaffold_template_custom?: Optional<boolean>\n cmd_scaffold_template_flavor?: Optional<string>\n cmd_scaffold_type?: Optional<string>\n cmd_scaffold_type_category?: Optional<string>\n cmd_scaffold_type_gated?: Optional<boolean>\n cmd_scaffold_type_owner?: Optional<string>\n cmd_scaffold_used_prompts_for_type?: Optional<boolean>\n\n // Used in several but not all commands\n cmd_app_dependency_installation_skipped?: Optional<boolean>\n cmd_app_reset_used?: Optional<boolean>\n cmd_app_linked_config_used?: Optional<boolean>\n cmd_app_linked_config_name?: Optional<string>\n cmd_app_linked_config_git_tracked?: Optional<boolean>\n cmd_app_all_configs_any?: Optional<boolean>\n cmd_app_all_configs_clients?: Optional<string>\n cmd_app_linked_config_source?: Optional<string>\n cmd_app_linked_config_uses_cli_managed_urls?: Optional<boolean>\n cmd_app_warning_api_key_deprecation_displayed?: Optional<boolean>\n cmd_app_deployment_mode?: Optional<string>\n cmd_app_validate_json?: Optional<boolean>\n cmd_app_validate_valid?: Optional<boolean>\n cmd_app_validate_issue_count?: Optional<number>\n cmd_app_validate_file_count?: Optional<number>\n\n // Dev related commands\n cmd_dev_tunnel_type?: Optional<string>\n cmd_dev_tunnel_custom_hash?: Optional<string>\n cmd_dev_urls_updated?: Optional<boolean>\n cmd_dev_preview_url_opened?: Optional<boolean>\n cmd_dev_graphiql_opened?: Optional<boolean>\n cmd_dev_dev_preview_toggle_used?: Optional<boolean>\n\n // Create-app related commands\n cmd_create_app_template?: Optional<string>\n cmd_create_app_template_url?: Optional<string>\n\n // Deploy related commands\n cmd_deploy_flag_message_used?: Optional<boolean>\n cmd_deploy_flag_version_used?: Optional<boolean>\n cmd_deploy_flag_source_url_used?: Optional<boolean>\n cmd_deploy_confirm_new_registrations?: Optional<number>\n cmd_deploy_confirm_updated_registrations?: Optional<number>\n cmd_deploy_confirm_removed_registrations?: Optional<number>\n cmd_deploy_confirm_cancelled?: Optional<boolean>\n cmd_deploy_confirm_time_to_complete_ms?: Optional<number>\n cmd_deploy_prompt_upgrade_to_unified_displayed?: Optional<boolean>\n cmd_deploy_prompt_upgrade_to_unified_response?: Optional<string>\n cmd_deploy_confirm_include_config_used?: Optional<boolean>\n cmd_deploy_include_config_used?: Optional<boolean>\n cmd_deploy_config_modules_breakdown?: Optional<string>\n cmd_deploy_config_modules_updated?: Optional<string>\n cmd_deploy_config_modules_added?: Optional<string>\n cmd_deploy_config_modules_deleted?: Optional<string>\n\n // Release related commands\n cmd_release_confirm_cancelled?: Optional<boolean>\n\n // App setup\n app_extensions_any?: Optional<boolean>\n app_extensions_breakdown?: Optional<string>\n app_extensions_count?: Optional<number>\n app_extensions_custom_layout?: Optional<boolean>\n app_extensions_function_any?: Optional<boolean>\n app_extensions_function_count?: Optional<number>\n app_extensions_function_custom_layout?: Optional<boolean>\n app_extensions_theme_any?: Optional<boolean>\n app_extensions_theme_count?: Optional<number>\n app_extensions_theme_custom_layout?: Optional<boolean>\n app_extensions_ui_any?: Optional<boolean>\n app_extensions_ui_count?: Optional<number>\n app_extensions_ui_custom_layout?: Optional<boolean>\n app_name_hash?: Optional<string>\n app_path_hash?: Optional<string>\n app_scopes?: Optional<string>\n app_web_backend_any?: Optional<boolean>\n app_web_backend_count?: Optional<number>\n app_web_custom_layout?: Optional<boolean>\n app_web_framework?: Optional<string>\n app_web_frontend_any?: Optional<boolean>\n app_web_frontend_count?: Optional<number>\n\n // Theme related commands\n cmd_theme_timings?: Optional<string>\n cmd_theme_errors?: Optional<string>\n cmd_theme_retries?: Optional<string>\n cmd_theme_events?: Optional<string>\n\n // Environment\n env_ci?: Optional<boolean>\n env_ci_platform?: Optional<string>\n env_device_id?: Optional<string>\n env_package_manager?: Optional<string>\n env_install_package_manager?: Optional<string>\n env_package_manager_workspaces?: Optional<boolean>\n env_plugin_installed_any_custom?: Optional<boolean>\n env_plugin_installed_shopify?: Optional<string>\n env_shell?: Optional<string>\n env_web_ide?: Optional<string>\n env_cloud?: Optional<string>\n env_is_global?: Optional<boolean>\n env_auth_method?: Optional<string>\n }\n }\n [schemaId: string]: {sensitive: JsonMap; public: JsonMap}\n}\n\n// In reality, we're normally most interested in just this from Schemas, so export it for ease of use.\n// The monorail schema itself has lots of optional values as it must be backwards-compatible. For our schema we want mandatory values instead.\nexport type MonorailEventPublic = DeepRequired<Schemas[typeof MONORAIL_COMMAND_TOPIC]['public']>\nexport type MonorailEventSensitive = Schemas[typeof MONORAIL_COMMAND_TOPIC]['sensitive']\n\ntype MonorailResult = {type: 'ok'} | {type: 'error'; message: string}\n\nconst publishedCommandNames = new Set<string>()\n\n/**\n * Publishes an event to Monorail.\n *\n * @param schemaId - The schema ID of the event to publish.\n * @param publicData - The public data to publish.\n * @param sensitiveData - The sensitive data to publish.\n * @returns A result indicating whether the event was successfully published.\n */\nexport async function publishMonorailEvent<TSchemaId extends keyof Schemas, TPayload extends Schemas[TSchemaId]>(\n schemaId: TSchemaId,\n publicData: TPayload['public'],\n sensitiveData: TPayload['sensitive'],\n): Promise<MonorailResult> {\n // If a command has already been logged, never re-log it. This is to prevent duplication caused by unexpected errors.\n const commandName = publicData.command\n if (commandName && typeof commandName === 'string') {\n if (publishedCommandNames.has(commandName)) {\n return {type: 'ok'}\n }\n publishedCommandNames.add(commandName)\n }\n\n try {\n const currentTime = new Date().getTime()\n const payload = {...publicData, ...sensitiveData}\n const body = JSON.stringify({schema_id: schemaId, payload})\n const headers = buildHeaders(currentTime)\n\n const response = await fetch(url, {method: 'POST', body, headers}, 'non-blocking')\n\n if (response.status === 200) {\n outputDebug(outputContent`Analytics event sent: ${outputToken.json(sanitizePayload(payload))}`)\n return {type: 'ok'}\n } else {\n outputDebug(`Failed to report usage analytics: ${response.statusText}`)\n return {type: 'error', message: response.statusText}\n }\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n let message = 'Failed to report usage analytics'\n if (error instanceof Error) {\n message = message.concat(`: ${error.message}`)\n }\n outputDebug(message)\n return {type: 'error', message}\n }\n}\n\n/**\n * Sanitizies the api_key from the payload and returns a new hash.\n *\n * @param payload - The public and sensitive data.\n * @returns A copy of the payload with the api_key sanitized.\n */\nfunction sanitizePayload<T extends object>(payload: T): T {\n const result = {...payload}\n if ('api_key' in result) {\n result.api_key = '****'\n }\n\n return result\n}\n\nconst buildHeaders = (currentTime: number) => {\n return {\n 'Content-Type': 'application/json; charset=utf-8',\n 'X-Monorail-Edge-Event-Created-At-Ms': currentTime.toString(),\n 'X-Monorail-Edge-Event-Sent-At-Ms': currentTime.toString(),\n }\n}\n"]}
1
+ {"version":3,"file":"monorail.js","sourceRoot":"","sources":["../../../src/public/node/monorail.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,WAAW,CAAA;AAC/B,OAAO,EAAC,WAAW,EAAE,aAAa,EAAE,WAAW,EAAC,MAAM,aAAa,CAAA;AAMnE,MAAM,GAAG,GAAG,iDAAiD,CAAA;AAI7D,mFAAmF;AACnF,MAAM,CAAC,MAAM,sBAAsB,GAAG,uBAAuB,CAAA;AAmL7D,MAAM,qBAAqB,GAAG,IAAI,GAAG,EAAU,CAAA;AAE/C;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,QAAmB,EACnB,UAA8B,EAC9B,aAAoC;IAEpC,qHAAqH;IACrH,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,CAAA;IACtC,IAAI,WAAW,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;QACnD,IAAI,qBAAqB,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YAC3C,OAAO,EAAC,IAAI,EAAE,IAAI,EAAC,CAAA;QACrB,CAAC;QACD,qBAAqB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IACxC,CAAC;IAED,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAA;QACxC,MAAM,OAAO,GAAG,EAAC,GAAG,UAAU,EAAE,GAAG,aAAa,EAAC,CAAA;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAC,CAAC,CAAA;QAC3D,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,CAAC,CAAA;QAEzC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAC,EAAE,cAAc,CAAC,CAAA;QAElF,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,WAAW,CAAC,aAAa,CAAA,yBAAyB,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAA;YAC/F,OAAO,EAAC,IAAI,EAAE,IAAI,EAAC,CAAA;QACrB,CAAC;aAAM,CAAC;YACN,WAAW,CAAC,qCAAqC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAA;YACvE,OAAO,EAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,UAAU,EAAC,CAAA;QACtD,CAAC;QACD,qDAAqD;IACvD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,OAAO,GAAG,kCAAkC,CAAA;QAChD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;QAChD,CAAC;QACD,WAAW,CAAC,OAAO,CAAC,CAAA;QACpB,OAAO,EAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAC,CAAA;IACjC,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,eAAe,CAAmB,OAAU;IACnD,MAAM,MAAM,GAAG,EAAC,GAAG,OAAO,EAAC,CAAA;IAC3B,IAAI,SAAS,IAAI,MAAM,EAAE,CAAC;QACxB,MAAM,CAAC,OAAO,GAAG,MAAM,CAAA;IACzB,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,YAAY,GAAG,CAAC,WAAmB,EAAE,EAAE;IAC3C,OAAO;QACL,cAAc,EAAE,iCAAiC;QACjD,qCAAqC,EAAE,WAAW,CAAC,QAAQ,EAAE;QAC7D,kCAAkC,EAAE,WAAW,CAAC,QAAQ,EAAE;KAC3D,CAAA;AACH,CAAC,CAAA","sourcesContent":["import {fetch} from './http.js'\nimport {outputDebug, outputContent, outputToken} from './output.js'\nimport {JsonMap} from '../../private/common/json.js'\nimport {DeepRequired} from '../common/ts/deep-required.js'\n\nexport {DeepRequired}\n\nconst url = 'https://monorail-edge.shopifysvc.com/v1/produce'\n\ntype Optional<T> = T | null\n\n// This is the topic name of the main event we log to Monorail, the command tracker\nexport const MONORAIL_COMMAND_TOPIC = 'app_cli3_command/1.24'\n\nexport interface Schemas {\n [MONORAIL_COMMAND_TOPIC]: {\n sensitive: {\n args: string\n error_message?: Optional<string>\n app_name?: Optional<string>\n metadata?: Optional<string>\n store_fqdn?: Optional<string>\n cmd_all_environment_flags?: Optional<string>\n\n // Dev related commands\n cmd_dev_tunnel_custom?: Optional<string>\n\n // Environment\n env_plugin_installed_all?: Optional<string>\n env_shopify_variables?: Optional<string>\n }\n public: {\n business_platform_id?: Optional<number>\n partner_id?: Optional<number>\n command: string\n project_type?: Optional<string>\n time_start: number\n time_end: number\n total_time: number\n success: boolean\n api_key?: Optional<string>\n cli_version: string\n uname: string\n ruby_version: string\n node_version: string\n is_employee: boolean\n store_fqdn_hash?: Optional<string>\n store_fqdn_validated?: Optional<boolean>\n user_id: string\n\n // Any and all commands\n cmd_all_alias_used?: Optional<string>\n cmd_all_launcher?: Optional<string>\n cmd_all_path_override?: Optional<boolean>\n cmd_all_path_override_hash?: Optional<string>\n cmd_all_plugin?: Optional<string>\n cmd_all_topic?: Optional<string>\n cmd_all_verbose?: Optional<boolean>\n cmd_all_exit?: Optional<string>\n cmd_all_force?: Optional<boolean>\n cmd_all_last_graphql_request_id?: Optional<string>\n\n cmd_all_timing_network_ms?: Optional<number>\n cmd_all_timing_prompts_ms?: Optional<number>\n cmd_all_timing_active_ms?: Optional<number>\n\n // Auto-upgrade\n env_auto_upgrade_enabled?: Optional<boolean>\n env_auto_upgrade_accepted?: Optional<boolean>\n env_auto_upgrade_skipped_reason?: Optional<string>\n env_auto_upgrade_success?: Optional<boolean>\n\n // Any extension related command\n cmd_extensions_binary_from_source?: Optional<boolean>\n\n // Scaffolding related commands\n cmd_scaffold_required_auth?: Optional<boolean>\n cmd_scaffold_template_custom?: Optional<boolean>\n cmd_scaffold_template_flavor?: Optional<string>\n cmd_scaffold_type?: Optional<string>\n cmd_scaffold_type_category?: Optional<string>\n cmd_scaffold_type_gated?: Optional<boolean>\n cmd_scaffold_type_owner?: Optional<string>\n cmd_scaffold_used_prompts_for_type?: Optional<boolean>\n\n // Used in several but not all commands\n cmd_app_dependency_installation_skipped?: Optional<boolean>\n cmd_app_reset_used?: Optional<boolean>\n cmd_app_linked_config_used?: Optional<boolean>\n cmd_app_linked_config_name?: Optional<string>\n cmd_app_linked_config_git_tracked?: Optional<boolean>\n cmd_app_all_configs_any?: Optional<boolean>\n cmd_app_all_configs_clients?: Optional<string>\n cmd_app_linked_config_source?: Optional<string>\n cmd_app_linked_config_uses_cli_managed_urls?: Optional<boolean>\n cmd_app_warning_api_key_deprecation_displayed?: Optional<boolean>\n cmd_app_deployment_mode?: Optional<string>\n cmd_app_validate_json?: Optional<boolean>\n cmd_app_validate_valid?: Optional<boolean>\n cmd_app_validate_issue_count?: Optional<number>\n cmd_app_validate_file_count?: Optional<number>\n\n // Dev related commands\n cmd_dev_tunnel_type?: Optional<string>\n cmd_dev_tunnel_custom_hash?: Optional<string>\n cmd_dev_urls_updated?: Optional<boolean>\n cmd_dev_preview_url_opened?: Optional<boolean>\n cmd_dev_graphiql_opened?: Optional<boolean>\n cmd_dev_dev_preview_toggle_used?: Optional<boolean>\n\n // Create-app related commands\n cmd_create_app_template?: Optional<string>\n cmd_create_app_template_url?: Optional<string>\n\n // Deploy related commands\n cmd_deploy_flag_message_used?: Optional<boolean>\n cmd_deploy_flag_version_used?: Optional<boolean>\n cmd_deploy_flag_source_url_used?: Optional<boolean>\n cmd_deploy_confirm_new_registrations?: Optional<number>\n cmd_deploy_confirm_updated_registrations?: Optional<number>\n cmd_deploy_confirm_removed_registrations?: Optional<number>\n cmd_deploy_confirm_cancelled?: Optional<boolean>\n cmd_deploy_confirm_time_to_complete_ms?: Optional<number>\n cmd_deploy_prompt_upgrade_to_unified_displayed?: Optional<boolean>\n cmd_deploy_prompt_upgrade_to_unified_response?: Optional<string>\n cmd_deploy_confirm_include_config_used?: Optional<boolean>\n cmd_deploy_include_config_used?: Optional<boolean>\n cmd_deploy_config_modules_breakdown?: Optional<string>\n cmd_deploy_config_modules_updated?: Optional<string>\n cmd_deploy_config_modules_added?: Optional<string>\n cmd_deploy_config_modules_deleted?: Optional<string>\n\n // Release related commands\n cmd_release_confirm_cancelled?: Optional<boolean>\n\n // App setup\n app_extensions_any?: Optional<boolean>\n app_extensions_breakdown?: Optional<string>\n app_extensions_count?: Optional<number>\n app_extensions_custom_layout?: Optional<boolean>\n app_extensions_function_any?: Optional<boolean>\n app_extensions_function_count?: Optional<number>\n app_extensions_function_custom_layout?: Optional<boolean>\n app_extensions_theme_any?: Optional<boolean>\n app_extensions_theme_count?: Optional<number>\n app_extensions_theme_custom_layout?: Optional<boolean>\n app_extensions_ui_any?: Optional<boolean>\n app_extensions_ui_count?: Optional<number>\n app_extensions_ui_custom_layout?: Optional<boolean>\n app_name_hash?: Optional<string>\n app_path_hash?: Optional<string>\n app_scopes?: Optional<string>\n app_web_backend_any?: Optional<boolean>\n app_web_backend_count?: Optional<number>\n app_web_custom_layout?: Optional<boolean>\n app_web_framework?: Optional<string>\n app_web_frontend_any?: Optional<boolean>\n app_web_frontend_count?: Optional<number>\n\n // Theme related commands\n cmd_theme_timings?: Optional<string>\n cmd_theme_errors?: Optional<string>\n cmd_theme_retries?: Optional<string>\n cmd_theme_events?: Optional<string>\n\n // Environment\n env_ci?: Optional<boolean>\n env_ci_platform?: Optional<string>\n env_device_id?: Optional<string>\n env_package_manager?: Optional<string>\n env_install_package_manager?: Optional<string>\n env_package_manager_workspaces?: Optional<boolean>\n env_plugin_installed_any_custom?: Optional<boolean>\n env_plugin_installed_shopify?: Optional<string>\n env_shell?: Optional<string>\n env_web_ide?: Optional<string>\n env_cloud?: Optional<string>\n env_is_global?: Optional<boolean>\n env_auth_method?: Optional<string>\n }\n }\n [schemaId: string]: {sensitive: JsonMap; public: JsonMap}\n}\n\n// In reality, we're normally most interested in just this from Schemas, so export it for ease of use.\n// The monorail schema itself has lots of optional values as it must be backwards-compatible. For our schema we want mandatory values instead.\nexport type MonorailEventPublic = DeepRequired<Schemas[typeof MONORAIL_COMMAND_TOPIC]['public']>\nexport type MonorailEventSensitive = Schemas[typeof MONORAIL_COMMAND_TOPIC]['sensitive']\n\ntype MonorailResult = {type: 'ok'} | {type: 'error'; message: string}\n\nconst publishedCommandNames = new Set<string>()\n\n/**\n * Publishes an event to Monorail.\n *\n * @param schemaId - The schema ID of the event to publish.\n * @param publicData - The public data to publish.\n * @param sensitiveData - The sensitive data to publish.\n * @returns A result indicating whether the event was successfully published.\n */\nexport async function publishMonorailEvent<TSchemaId extends keyof Schemas, TPayload extends Schemas[TSchemaId]>(\n schemaId: TSchemaId,\n publicData: TPayload['public'],\n sensitiveData: TPayload['sensitive'],\n): Promise<MonorailResult> {\n // If a command has already been logged, never re-log it. This is to prevent duplication caused by unexpected errors.\n const commandName = publicData.command\n if (commandName && typeof commandName === 'string') {\n if (publishedCommandNames.has(commandName)) {\n return {type: 'ok'}\n }\n publishedCommandNames.add(commandName)\n }\n\n try {\n const currentTime = new Date().getTime()\n const payload = {...publicData, ...sensitiveData}\n const body = JSON.stringify({schema_id: schemaId, payload})\n const headers = buildHeaders(currentTime)\n\n const response = await fetch(url, {method: 'POST', body, headers}, 'non-blocking')\n\n if (response.status === 200) {\n outputDebug(outputContent`Analytics event sent: ${outputToken.json(sanitizePayload(payload))}`)\n return {type: 'ok'}\n } else {\n outputDebug(`Failed to report usage analytics: ${response.statusText}`)\n return {type: 'error', message: response.statusText}\n }\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n let message = 'Failed to report usage analytics'\n if (error instanceof Error) {\n message = message.concat(`: ${error.message}`)\n }\n outputDebug(message)\n return {type: 'error', message}\n }\n}\n\n/**\n * Sanitizies the api_key from the payload and returns a new hash.\n *\n * @param payload - The public and sensitive data.\n * @returns A copy of the payload with the api_key sanitized.\n */\nfunction sanitizePayload<T extends object>(payload: T): T {\n const result = {...payload}\n if ('api_key' in result) {\n result.api_key = '****'\n }\n\n return result\n}\n\nconst buildHeaders = (currentTime: number) => {\n return {\n 'Content-Type': 'application/json; charset=utf-8',\n 'X-Monorail-Edge-Event-Created-At-Ms': currentTime.toString(),\n 'X-Monorail-Edge-Event-Sent-At-Ms': currentTime.toString(),\n }\n}\n"]}
@@ -13,8 +13,8 @@ export declare const bunLockfile = "bun.lockb";
13
13
  export declare const pnpmWorkspaceFile = "pnpm-workspace.yaml";
14
14
  /** An array containing the lockfiles from all the package managers */
15
15
  export declare const lockfiles: Lockfile[];
16
- export declare const lockfilesByManager: Record<PackageManager, Lockfile | undefined>;
17
- export type Lockfile = 'yarn.lock' | 'package-lock.json' | 'pnpm-lock.yaml' | 'bun.lockb';
16
+ export declare const lockfilesByManager: Record<PackageManager, Lockfile[]>;
17
+ export type Lockfile = 'yarn.lock' | 'package-lock.json' | 'pnpm-lock.yaml' | 'bun.lockb' | 'bun.lock';
18
18
  /**
19
19
  * A union type that represents the type of dependencies in the package.json
20
20
  * - dev: devDependencies
@@ -8,7 +8,6 @@ import { inferPackageManagerForGlobalCLI } from './is-global.js';
8
8
  import { outputToken, outputContent, outputDebug } from './output.js';
9
9
  import { cacheRetrieve, cacheRetrieveOrRepopulate } from '../../private/node/conf-store.js';
10
10
  import { parseJSON } from '../common/json.js';
11
- import latestVersion from 'latest-version';
12
11
  import { SemVer, satisfies as semverSatisfies } from 'semver';
13
12
  /** The name of the Yarn lock file */
14
13
  export const yarnLockfile = 'yarn.lock';
@@ -22,14 +21,14 @@ const modernBunLockfile = 'bun.lock';
22
21
  /** The name of the pnpm workspace file */
23
22
  export const pnpmWorkspaceFile = 'pnpm-workspace.yaml';
24
23
  /** An array containing the lockfiles from all the package managers */
25
- export const lockfiles = [yarnLockfile, pnpmLockfile, npmLockfile, bunLockfile];
24
+ export const lockfiles = [yarnLockfile, pnpmLockfile, npmLockfile, bunLockfile, modernBunLockfile];
26
25
  export const lockfilesByManager = {
27
- yarn: yarnLockfile,
28
- npm: npmLockfile,
29
- pnpm: pnpmLockfile,
30
- bun: bunLockfile,
31
- homebrew: undefined,
32
- unknown: undefined,
26
+ yarn: [yarnLockfile],
27
+ npm: [npmLockfile],
28
+ pnpm: [pnpmLockfile],
29
+ bun: [bunLockfile, modernBunLockfile],
30
+ homebrew: [],
31
+ unknown: [],
33
32
  };
34
33
  /**
35
34
  * A union that represents the package managers available.
@@ -337,7 +336,7 @@ export async function addNPMDependencies(dependencies, options) {
337
336
  const dependenciesWithVersion = dependencies.map((dep) => {
338
337
  return dep.version ? `${dep.name}@${dep.version}` : dep.name;
339
338
  });
340
- options.stdout?.write(`Installing ${[dependenciesWithVersion].join(' ')} with ${options.packageManager}`);
339
+ options.stdout?.write(`Installing ${dependenciesWithVersion.join(' ')} with ${options.packageManager}`);
341
340
  switch (options.packageManager) {
342
341
  case 'npm':
343
342
  // npm isn't too smart when resolving the dependency tree. For example, admin ui extensions include react as
@@ -518,7 +517,8 @@ export async function addResolutionOrOverride(directory, dependencies) {
518
517
  */
519
518
  async function getLatestNPMPackageVersion(name) {
520
519
  outputDebug(outputContent `Getting the latest version of NPM package: ${outputToken.raw(name)}`);
521
- return runWithTimer('cmd_all_timing_network_ms')(() => {
520
+ return runWithTimer('cmd_all_timing_network_ms')(async () => {
521
+ const { default: latestVersion } = await import('latest-version');
522
522
  return latestVersion(name);
523
523
  });
524
524
  }