@shopify/cli-kit 4.8.5 → 4.9.1

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 (147) hide show
  1. package/dist/private/node/analytics.js +5 -3
  2. package/dist/private/node/analytics.js.map +1 -1
  3. package/dist/private/node/api/status-checks.d.ts +7 -0
  4. package/dist/private/node/api/status-checks.js +11 -0
  5. package/dist/private/node/api/status-checks.js.map +1 -0
  6. package/dist/private/node/api.d.ts +15 -0
  7. package/dist/private/node/api.js +28 -0
  8. package/dist/private/node/api.js.map +1 -1
  9. package/dist/private/node/command-event-context.d.ts +29 -0
  10. package/dist/private/node/command-event-context.js +43 -0
  11. package/dist/private/node/command-event-context.js.map +1 -0
  12. package/dist/private/node/command-event-output.d.ts +7 -0
  13. package/dist/private/node/command-event-output.js +16 -0
  14. package/dist/private/node/command-event-output.js.map +1 -0
  15. package/dist/private/node/command-json-schema.d.ts +10 -0
  16. package/dist/private/node/command-json-schema.js +38 -0
  17. package/dist/private/node/command-json-schema.js.map +1 -0
  18. package/dist/private/node/context/agent.d.ts +1 -0
  19. package/dist/private/node/context/agent.js +44 -0
  20. package/dist/private/node/context/agent.js.map +1 -0
  21. package/dist/private/node/json-error.d.ts +23 -0
  22. package/dist/private/node/json-error.js +123 -0
  23. package/dist/private/node/json-error.js.map +1 -0
  24. package/dist/private/node/output.js +3 -1
  25. package/dist/private/node/output.js.map +1 -1
  26. package/dist/private/node/output.test.d.ts +1 -0
  27. package/dist/private/node/output.test.js +74 -0
  28. package/dist/private/node/output.test.js.map +1 -0
  29. package/dist/private/node/session/device-authorization.js +49 -15
  30. package/dist/private/node/session/device-authorization.js.map +1 -1
  31. package/dist/private/node/session/validate.js +9 -22
  32. package/dist/private/node/session/validate.js.map +1 -1
  33. package/dist/private/node/ui/alert.d.ts +1 -1
  34. package/dist/private/node/ui/alert.js +29 -3
  35. package/dist/private/node/ui/alert.js.map +1 -1
  36. package/dist/private/node/ui/components/ConcurrentOutput.d.ts +8 -1
  37. package/dist/private/node/ui/components/ConcurrentOutput.js +54 -0
  38. package/dist/private/node/ui/components/ConcurrentOutput.js.map +1 -1
  39. package/dist/private/node/ui/components/DangerousConfirmationPrompt.js +3 -3
  40. package/dist/private/node/ui/components/DangerousConfirmationPrompt.js.map +1 -1
  41. package/dist/private/node/ui/components/DangerousConfirmationPrompt.test.js +16 -1
  42. package/dist/private/node/ui/components/DangerousConfirmationPrompt.test.js.map +1 -1
  43. package/dist/private/node/ui/components/Prompts/PromptLayout.js +3 -2
  44. package/dist/private/node/ui/components/Prompts/PromptLayout.js.map +1 -1
  45. package/dist/private/node/ui/components/Prompts/PromptLayout.test.js +20 -1
  46. package/dist/private/node/ui/components/Prompts/PromptLayout.test.js.map +1 -1
  47. package/dist/private/node/ui/components/Tasks.d.ts +2 -9
  48. package/dist/private/node/ui/components/Tasks.js +5 -44
  49. package/dist/private/node/ui/components/Tasks.js.map +1 -1
  50. package/dist/private/node/ui/components/TextPrompt.js +3 -3
  51. package/dist/private/node/ui/components/TextPrompt.js.map +1 -1
  52. package/dist/private/node/ui/components/TextPrompt.test.js +15 -1
  53. package/dist/private/node/ui/components/TextPrompt.test.js.map +1 -1
  54. package/dist/private/node/ui/components/token-item.d.ts +2 -0
  55. package/dist/private/node/ui/components/token-item.js +26 -0
  56. package/dist/private/node/ui/components/token-item.js.map +1 -1
  57. package/dist/private/node/ui/hooks/use-async-and-unmount.d.ts +3 -3
  58. package/dist/private/node/ui/hooks/use-async-and-unmount.js +2 -2
  59. package/dist/private/node/ui/hooks/use-async-and-unmount.js.map +1 -1
  60. package/dist/private/node/ui/tasks.d.ts +10 -0
  61. package/dist/private/node/ui/tasks.js +68 -0
  62. package/dist/private/node/ui/tasks.js.map +1 -0
  63. package/dist/public/common/command-events.d.ts +125 -0
  64. package/dist/public/common/command-events.js +54 -0
  65. package/dist/public/common/command-events.js.map +1 -0
  66. package/dist/public/common/json-output-schema.d.ts +10 -0
  67. package/dist/public/common/json-output-schema.js +17 -0
  68. package/dist/public/common/json-output-schema.js.map +1 -0
  69. package/dist/public/common/version.d.ts +1 -1
  70. package/dist/public/common/version.js +1 -1
  71. package/dist/public/common/version.js.map +1 -1
  72. package/dist/public/node/api/admin.js +18 -1
  73. package/dist/public/node/api/admin.js.map +1 -1
  74. package/dist/public/node/api/app-management.d.ts +1 -0
  75. package/dist/public/node/api/app-management.js +4 -0
  76. package/dist/public/node/api/app-management.js.map +1 -1
  77. package/dist/public/node/api/bulk-operations/download-bulk-operation-results.d.ts +3 -3
  78. package/dist/public/node/api/bulk-operations/download-bulk-operation-results.js +5 -3
  79. package/dist/public/node/api/bulk-operations/download-bulk-operation-results.js.map +1 -1
  80. package/dist/public/node/base-command.d.ts +6 -0
  81. package/dist/public/node/base-command.js +34 -5
  82. package/dist/public/node/base-command.js.map +1 -1
  83. package/dist/public/node/cli-launcher.js +20 -2
  84. package/dist/public/node/cli-launcher.js.map +1 -1
  85. package/dist/public/node/cli.d.ts +1 -0
  86. package/dist/public/node/cli.js +2 -0
  87. package/dist/public/node/cli.js.map +1 -1
  88. package/dist/public/node/command-events.d.ts +65 -0
  89. package/dist/public/node/command-events.js +71 -0
  90. package/dist/public/node/command-events.js.map +1 -0
  91. package/dist/public/node/context/local.d.ts +6 -0
  92. package/dist/public/node/context/local.js +10 -1
  93. package/dist/public/node/context/local.js.map +1 -1
  94. package/dist/public/node/custom-oclif-loader.d.ts +6 -0
  95. package/dist/public/node/custom-oclif-loader.js +45 -19
  96. package/dist/public/node/custom-oclif-loader.js.map +1 -1
  97. package/dist/public/node/environment.d.ts +2 -1
  98. package/dist/public/node/environment.js +3 -2
  99. package/dist/public/node/environment.js.map +1 -1
  100. package/dist/public/node/error/index.d.ts +91 -0
  101. package/dist/public/node/error/index.js +266 -0
  102. package/dist/public/node/error/index.js.map +1 -0
  103. package/dist/public/node/error/schema.d.ts +472 -0
  104. package/dist/public/node/error/schema.js +54 -0
  105. package/dist/public/node/error/schema.js.map +1 -0
  106. package/dist/public/node/error/types.d.ts +9 -0
  107. package/dist/public/node/error/types.js +2 -0
  108. package/dist/public/node/error/types.js.map +1 -0
  109. package/dist/public/node/error.d.ts +1 -87
  110. package/dist/public/node/error.js +1 -252
  111. package/dist/public/node/error.js.map +1 -1
  112. package/dist/public/node/fs.d.ts +17 -3
  113. package/dist/public/node/fs.js +7 -5
  114. package/dist/public/node/fs.js.map +1 -1
  115. package/dist/public/node/json-output-schema.d.ts +26 -0
  116. package/dist/public/node/json-output-schema.js +30 -0
  117. package/dist/public/node/json-output-schema.js.map +1 -0
  118. package/dist/public/node/local-storage.d.ts +1 -0
  119. package/dist/public/node/local-storage.js +54 -21
  120. package/dist/public/node/local-storage.js.map +1 -1
  121. package/dist/public/node/monorail.d.ts +3 -1
  122. package/dist/public/node/monorail.js +1 -1
  123. package/dist/public/node/monorail.js.map +1 -1
  124. package/dist/public/node/multiple-installation-warning.d.ts +1 -1
  125. package/dist/public/node/multiple-installation-warning.js +2 -3
  126. package/dist/public/node/multiple-installation-warning.js.map +1 -1
  127. package/dist/public/node/no-input.d.ts +11 -0
  128. package/dist/public/node/no-input.js +19 -0
  129. package/dist/public/node/no-input.js.map +1 -0
  130. package/dist/public/node/output.d.ts +6 -0
  131. package/dist/public/node/output.js +40 -0
  132. package/dist/public/node/output.js.map +1 -1
  133. package/dist/public/node/path.js +3 -1
  134. package/dist/public/node/path.js.map +1 -1
  135. package/dist/public/node/system.d.ts +2 -2
  136. package/dist/public/node/system.js +8 -4
  137. package/dist/public/node/system.js.map +1 -1
  138. package/dist/public/node/testing/output.d.ts +30 -0
  139. package/dist/public/node/testing/output.js +83 -0
  140. package/dist/public/node/testing/output.js.map +1 -1
  141. package/dist/public/node/ui.d.ts +5 -1
  142. package/dist/public/node/ui.js +89 -5
  143. package/dist/public/node/ui.js.map +1 -1
  144. package/dist/public/node/upgrade.js +17 -2
  145. package/dist/public/node/upgrade.js.map +1 -1
  146. package/dist/tsconfig.tsbuildinfo +1 -1
  147. package/package.json +4 -2
@@ -1,5 +1,6 @@
1
1
  import { getLastSeenAuthMethod } from './session.js';
2
2
  import { getAutoUpgradeEnabled } from './conf-store.js';
3
+ import { detectedAgentEnvironmentVariables } from './context/agent.js';
3
4
  import { hashString } from '../../public/node/crypto.js';
4
5
  import { getPackageManager, packageManagerFromUserAgent } from '../../public/node/node-package-manager.js';
5
6
  import * as metadata from '../../public/node/metadata.js';
@@ -70,11 +71,12 @@ export async function getEnvironmentData(config) {
70
71
  export async function getSensitiveEnvironmentData(config) {
71
72
  return {
72
73
  env_plugin_installed_all: JSON.stringify(getPluginNames(config)),
73
- env_shopify_variables: JSON.stringify(getShopifyEnvironmentVariables()),
74
+ env_shopify_variables: JSON.stringify(await getShopifyEnvironmentVariables()),
74
75
  };
75
76
  }
76
- function getShopifyEnvironmentVariables() {
77
- return Object.fromEntries(Object.entries(process.env).filter(([key]) => allowedShopifyEnvironmentVariableNames.has(key)));
77
+ async function getShopifyEnvironmentVariables(env = process.env) {
78
+ const declaredVariables = Object.fromEntries(Object.entries(env).filter(([key]) => allowedShopifyEnvironmentVariableNames.has(key)));
79
+ return { ...declaredVariables, ...(await detectedAgentEnvironmentVariables(env)) };
78
80
  }
79
81
  function getPluginNames(config) {
80
82
  const pluginNames = [...config.plugins.keys()];
@@ -1 +1 @@
1
- {"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../../src/private/node/analytics.ts"],"names":[],"mappings":"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","sourcesContent":["import {getLastSeenAuthMethod} from './session.js'\nimport {getAutoUpgradeEnabled} from './conf-store.js'\nimport {hashString} from '../../public/node/crypto.js'\nimport {getPackageManager, packageManagerFromUserAgent} from '../../public/node/node-package-manager.js'\nimport BaseCommand from '../../public/node/base-command.js'\nimport {CommandContent} from '../../public/node/hooks/prerun.js'\nimport * as metadata from '../../public/node/metadata.js'\nimport {platformAndArch} from '../../public/node/os.js'\nimport {ciPlatform, cloudEnvironment, macAddress} from '../../public/node/context/local.js'\nimport {cwd} from '../../public/node/path.js'\nimport {currentProcessIsGlobal, inferPackageManagerForGlobalCLI} from '../../public/node/is-global.js'\nimport {isWsl} from '../../public/node/system.js'\n\nimport {Command, Interfaces} from '@oclif/core'\n\ninterface StartOptions {\n commandContent: CommandContent\n args: string[]\n currentTime?: number\n commandClass?: Command.Class | typeof BaseCommand\n}\n\nexport async function startAnalytics({\n commandContent,\n args,\n currentTime = new Date().getTime(),\n commandClass,\n}: StartOptions): Promise<void> {\n let startCommand: string = commandContent.command\n if (commandClass && Object.prototype.hasOwnProperty.call(commandClass, 'analyticsNameOverride')) {\n startCommand = (commandClass as typeof BaseCommand).analyticsNameOverride() ?? commandContent.command\n }\n\n let pluginName = commandClass?.plugin?.name\n if (commandClass && 'customPluginName' in commandClass) {\n pluginName = commandClass.customPluginName as string\n }\n\n await metadata.addSensitiveMetadata(() => ({\n commandStartOptions: {\n startTime: currentTime,\n startCommand,\n startArgs: args,\n requiresSyncAnalytics: (commandClass as typeof BaseCommand | undefined)?.requiresSyncAnalytics ?? false,\n },\n }))\n\n await metadata.addPublicMetadata(() => ({\n cmd_all_launcher: packageManagerFromUserAgent(),\n cmd_all_alias_used: commandContent.alias,\n cmd_all_topic: commandContent.topic,\n cmd_all_plugin: pluginName,\n cmd_all_force: flagIncluded('force', commandClass) ? args.includes('--force') : undefined,\n }))\n}\n\ninterface EnvironmentData {\n uname: string\n env_ci: boolean\n env_ci_platform?: string\n env_plugin_installed_any_custom: boolean\n env_plugin_installed_shopify: string\n env_shell: string\n env_web_ide: string | undefined\n env_device_id: string\n env_cloud: string\n env_package_manager: string\n env_install_package_manager: string\n env_is_global: boolean\n env_auth_method: string\n env_is_wsl: boolean\n env_build_repository: string\n env_auto_upgrade_enabled: boolean | null\n}\n\nconst allowedShopifyEnvironmentVariableNames = new Set([\n 'SHOPIFY_INVOKED_BY',\n 'SHOPIFY_CLI_AGENT',\n 'SHOPIFY_CLI_AGENT_INFO',\n 'SHOPIFY_CLI_AGENT_IDS',\n 'SHOPIFY_CLI_AGENT_VERSION',\n 'SHOPIFY_CLI_AGENT_RUN_ID',\n 'SHOPIFY_CLI_AGENT_SESSION_ID',\n 'SHOPIFY_CLI_AGENT_PROVIDER',\n])\n\nexport async function getEnvironmentData(config: Interfaces.Config): Promise<EnvironmentData> {\n const ciplatform = ciPlatform()\n\n const pluginNames = getPluginNames(config)\n const shopifyPlugins = pluginNames.filter((plugin) => plugin.startsWith('@shopify/'))\n\n const {platform, arch} = platformAndArch()\n\n return {\n uname: `${platform} ${arch}`,\n env_ci: ciplatform.isCI,\n env_ci_platform: ciplatform.name,\n env_plugin_installed_any_custom: pluginNames.length !== shopifyPlugins.length,\n env_plugin_installed_shopify: JSON.stringify(shopifyPlugins),\n env_shell: config.shell,\n env_web_ide: cloudEnvironment().editor ? cloudEnvironment().platform : undefined,\n env_device_id: hashString(await macAddress()),\n env_cloud: cloudEnvironment().platform,\n env_package_manager: await getPackageManager(cwd()),\n env_install_package_manager: inferPackageManagerForGlobalCLI(),\n env_is_global: currentProcessIsGlobal(),\n env_auth_method: await getLastSeenAuthMethod(),\n env_is_wsl: await isWsl(),\n env_build_repository: process.env.SHOPIFY_CLI_BUILD_REPO ?? 'unknown',\n env_auto_upgrade_enabled: getAutoUpgradeEnabled() ?? null,\n }\n}\n\nexport async function getSensitiveEnvironmentData(config: Interfaces.Config) {\n return {\n env_plugin_installed_all: JSON.stringify(getPluginNames(config)),\n env_shopify_variables: JSON.stringify(getShopifyEnvironmentVariables()),\n }\n}\n\nfunction getShopifyEnvironmentVariables() {\n return Object.fromEntries(\n Object.entries(process.env).filter(([key]) => allowedShopifyEnvironmentVariableNames.has(key)),\n )\n}\n\nfunction getPluginNames(config: Interfaces.Config) {\n const pluginNames = [...config.plugins.keys()]\n return pluginNames.sort().filter((plugin) => !plugin.startsWith('@oclif/'))\n}\n\nfunction flagIncluded(flag: string, commandClass?: Command.Class | typeof BaseCommand) {\n if (!commandClass) return false\n\n const commandFlags = commandClass.flags ?? {}\n return Object.keys(commandFlags).includes(flag)\n}\n"]}
1
+ {"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../../src/private/node/analytics.ts"],"names":[],"mappings":"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","sourcesContent":["import {getLastSeenAuthMethod} from './session.js'\nimport {getAutoUpgradeEnabled} from './conf-store.js'\nimport {detectedAgentEnvironmentVariables} from './context/agent.js'\nimport {hashString} from '../../public/node/crypto.js'\nimport {getPackageManager, packageManagerFromUserAgent} from '../../public/node/node-package-manager.js'\nimport BaseCommand from '../../public/node/base-command.js'\nimport {CommandContent} from '../../public/node/hooks/prerun.js'\nimport * as metadata from '../../public/node/metadata.js'\nimport {platformAndArch} from '../../public/node/os.js'\nimport {ciPlatform, cloudEnvironment, macAddress} from '../../public/node/context/local.js'\nimport {cwd} from '../../public/node/path.js'\nimport {currentProcessIsGlobal, inferPackageManagerForGlobalCLI} from '../../public/node/is-global.js'\nimport {isWsl} from '../../public/node/system.js'\n\nimport {Command, Interfaces} from '@oclif/core'\n\ninterface StartOptions {\n commandContent: CommandContent\n args: string[]\n currentTime?: number\n commandClass?: Command.Class | typeof BaseCommand\n}\n\nexport async function startAnalytics({\n commandContent,\n args,\n currentTime = new Date().getTime(),\n commandClass,\n}: StartOptions): Promise<void> {\n let startCommand: string = commandContent.command\n if (commandClass && Object.prototype.hasOwnProperty.call(commandClass, 'analyticsNameOverride')) {\n startCommand = (commandClass as typeof BaseCommand).analyticsNameOverride() ?? commandContent.command\n }\n\n let pluginName = commandClass?.plugin?.name\n if (commandClass && 'customPluginName' in commandClass) {\n pluginName = commandClass.customPluginName as string\n }\n\n await metadata.addSensitiveMetadata(() => ({\n commandStartOptions: {\n startTime: currentTime,\n startCommand,\n startArgs: args,\n requiresSyncAnalytics: (commandClass as typeof BaseCommand | undefined)?.requiresSyncAnalytics ?? false,\n },\n }))\n\n await metadata.addPublicMetadata(() => ({\n cmd_all_launcher: packageManagerFromUserAgent(),\n cmd_all_alias_used: commandContent.alias,\n cmd_all_topic: commandContent.topic,\n cmd_all_plugin: pluginName,\n cmd_all_force: flagIncluded('force', commandClass) ? args.includes('--force') : undefined,\n }))\n}\n\ninterface EnvironmentData {\n uname: string\n env_ci: boolean\n env_ci_platform?: string\n env_plugin_installed_any_custom: boolean\n env_plugin_installed_shopify: string\n env_shell: string\n env_web_ide: string | undefined\n env_device_id: string\n env_cloud: string\n env_package_manager: string\n env_install_package_manager: string\n env_is_global: boolean\n env_auth_method: string\n env_is_wsl: boolean\n env_build_repository: string\n env_auto_upgrade_enabled: boolean | null\n}\n\nconst allowedShopifyEnvironmentVariableNames = new Set([\n 'SHOPIFY_INVOKED_BY',\n 'SHOPIFY_CLI_AGENT',\n 'SHOPIFY_CLI_AGENT_INFO',\n 'SHOPIFY_CLI_AGENT_IDS',\n 'SHOPIFY_CLI_AGENT_VERSION',\n 'SHOPIFY_CLI_AGENT_RUN_ID',\n 'SHOPIFY_CLI_AGENT_SESSION_ID',\n 'SHOPIFY_CLI_AGENT_PROVIDER',\n])\n\nexport async function getEnvironmentData(config: Interfaces.Config): Promise<EnvironmentData> {\n const ciplatform = ciPlatform()\n\n const pluginNames = getPluginNames(config)\n const shopifyPlugins = pluginNames.filter((plugin) => plugin.startsWith('@shopify/'))\n\n const {platform, arch} = platformAndArch()\n\n return {\n uname: `${platform} ${arch}`,\n env_ci: ciplatform.isCI,\n env_ci_platform: ciplatform.name,\n env_plugin_installed_any_custom: pluginNames.length !== shopifyPlugins.length,\n env_plugin_installed_shopify: JSON.stringify(shopifyPlugins),\n env_shell: config.shell,\n env_web_ide: cloudEnvironment().editor ? cloudEnvironment().platform : undefined,\n env_device_id: hashString(await macAddress()),\n env_cloud: cloudEnvironment().platform,\n env_package_manager: await getPackageManager(cwd()),\n env_install_package_manager: inferPackageManagerForGlobalCLI(),\n env_is_global: currentProcessIsGlobal(),\n env_auth_method: await getLastSeenAuthMethod(),\n env_is_wsl: await isWsl(),\n env_build_repository: process.env.SHOPIFY_CLI_BUILD_REPO ?? 'unknown',\n env_auto_upgrade_enabled: getAutoUpgradeEnabled() ?? null,\n }\n}\n\nexport async function getSensitiveEnvironmentData(config: Interfaces.Config) {\n return {\n env_plugin_installed_all: JSON.stringify(getPluginNames(config)),\n env_shopify_variables: JSON.stringify(await getShopifyEnvironmentVariables()),\n }\n}\n\nasync function getShopifyEnvironmentVariables(env: NodeJS.ProcessEnv = process.env) {\n const declaredVariables = Object.fromEntries(\n Object.entries(env).filter(([key]) => allowedShopifyEnvironmentVariableNames.has(key)),\n )\n\n return {...declaredVariables, ...(await detectedAgentEnvironmentVariables(env))}\n}\n\nfunction getPluginNames(config: Interfaces.Config) {\n const pluginNames = [...config.plugins.keys()]\n return pluginNames.sort().filter((plugin) => !plugin.startsWith('@oclif/'))\n}\n\nfunction flagIncluded(flag: string, commandClass?: Command.Class | typeof BaseCommand) {\n if (!commandClass) return false\n\n const commandFlags = commandClass.flags ?? {}\n return Object.keys(commandFlags).includes(flag)\n}\n"]}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Checks whether an HTTP status indicates a gateway-level failure.
3
+ *
4
+ * @param status - The HTTP status to check.
5
+ * @returns Whether the status is 502, 503, or 504.
6
+ */
7
+ export declare function isGatewayErrorStatus(status: number | undefined): boolean;
@@ -0,0 +1,11 @@
1
+ const GATEWAY_ERROR_STATUSES = new Set([502, 503, 504]);
2
+ /**
3
+ * Checks whether an HTTP status indicates a gateway-level failure.
4
+ *
5
+ * @param status - The HTTP status to check.
6
+ * @returns Whether the status is 502, 503, or 504.
7
+ */
8
+ export function isGatewayErrorStatus(status) {
9
+ return status !== undefined && GATEWAY_ERROR_STATUSES.has(status);
10
+ }
11
+ //# sourceMappingURL=status-checks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-checks.js","sourceRoot":"","sources":["../../../../src/private/node/api/status-checks.ts"],"names":[],"mappings":"AAAA,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAA;AAEvD;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAA0B;IAC7D,OAAO,MAAM,KAAK,SAAS,IAAI,sBAAsB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;AACnE,CAAC","sourcesContent":["const GATEWAY_ERROR_STATUSES = new Set([502, 503, 504])\n\n/**\n * Checks whether an HTTP status indicates a gateway-level failure.\n *\n * @param status - The HTTP status to check.\n * @returns Whether the status is 502, 503, or 504.\n */\nexport function isGatewayErrorStatus(status: number | undefined): boolean {\n return status !== undefined && GATEWAY_ERROR_STATUSES.has(status)\n}\n"]}
@@ -37,6 +37,21 @@ export declare function isTransientNetworkError(error: unknown): boolean;
37
37
  * - Permanent: certificate validation failures, misconfigured SSL
38
38
  */
39
39
  export declare function isNetworkError(error: unknown): boolean;
40
+ /**
41
+ * Checks if an error is an aborted request: a user cancelling the command, the host process
42
+ * cancelling it, or one of the CLI's own request timeouts firing.
43
+ *
44
+ * Not used by the retry logic, because a user-cancelled request must not be retried.
45
+ * `isTransientNetworkError` separately matches the CLI's own timeout message, so timeouts do
46
+ * still retry.
47
+ *
48
+ * The `name` check matches the `AbortError` shape that fetch throws, not cli-kit's own
49
+ * `AbortError`, which leaves `name` as 'Error'.
50
+ *
51
+ * @param error - Error to be checked.
52
+ * @returns A boolean indicating if the request was aborted.
53
+ */
54
+ export declare function isAbortedFetchError(error: unknown): boolean;
40
55
  export declare function simpleRequestWithDebugLog<T extends {
41
56
  headers: Headers;
42
57
  status: number;
@@ -80,6 +80,34 @@ export function isNetworkError(error) {
80
80
  }
81
81
  return false;
82
82
  }
83
+ /**
84
+ * Lower-cased substrings that mean a request was aborted rather than failing on its own.
85
+ * `node-fetch` says 'The user aborted a request.', undici says 'This operation was aborted', and
86
+ * cli-kit's own request timeout says 'The operation was aborted'.
87
+ */
88
+ const ABORTED_FETCH_MESSAGE_FRAGMENTS = ['the user aborted a request', 'operation was aborted'];
89
+ /**
90
+ * Checks if an error is an aborted request: a user cancelling the command, the host process
91
+ * cancelling it, or one of the CLI's own request timeouts firing.
92
+ *
93
+ * Not used by the retry logic, because a user-cancelled request must not be retried.
94
+ * `isTransientNetworkError` separately matches the CLI's own timeout message, so timeouts do
95
+ * still retry.
96
+ *
97
+ * The `name` check matches the `AbortError` shape that fetch throws, not cli-kit's own
98
+ * `AbortError`, which leaves `name` as 'Error'.
99
+ *
100
+ * @param error - Error to be checked.
101
+ * @returns A boolean indicating if the request was aborted.
102
+ */
103
+ export function isAbortedFetchError(error) {
104
+ if (!(error instanceof Error))
105
+ return false;
106
+ if (error.name === 'AbortError')
107
+ return true;
108
+ const errorMessage = error.message.toLowerCase();
109
+ return ABORTED_FETCH_MESSAGE_FRAGMENTS.some((fragment) => errorMessage.includes(fragment));
110
+ }
83
111
  async function runRequestWithNetworkLevelRetry(requestOptions) {
84
112
  if (!requestOptions.useNetworkLevelRetry) {
85
113
  return requestOptions.request();
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/private/node/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,sBAAsB,EAAC,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAA;AACzC,OAAO,EAAC,gBAAgB,EAAC,MAAM,oCAAoC,CAAA;AACnE,OAAO,EAAC,qBAAqB,EAAC,MAAM,yBAAyB,CAAA;AAC7D,OAAO,EAAC,WAAW,EAAC,MAAM,6BAA6B,CAAA;AACvD,OAAO,EAAC,WAAW,EAAC,MAAM,gCAAgC,CAAA;AAG1D,OAAO,EAAC,WAAW,EAAC,MAAM,iBAAiB,CAAA;AAE3C,OAAO,EAAC,WAAW,EAAC,MAAM,YAAY,CAAA;AAItC,MAAM,CAAC,MAAM,OAAO,GAAU,CAAC,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAE,mBAAmB,EAAE,gBAAgB,CAAC,CAAA;AAEjH,MAAM,sBAAsB,GAAG,IAAI,CAAA;AACnC,MAAM,mBAAmB,GAAG,EAAE,CAAA;AAkB9B,MAAM,0BAA0B,GAAG,IAAI,GAAG,CAAC;IACzC,eAAe;IACf,cAAc;IACd,MAAM;IACN,cAAc;IACd,eAAe;IACf,aAAa;CACd,CAAC,CAAA;AAEF,SAAS,2BAA2B,CAAC,MAAc;IACjD,OAAO,0BAA0B,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;AAC/C,CAAC;AA8BD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAc;IACpD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,MAAM,sBAAsB,GAAG;YAC7B,gBAAgB;YAChB,YAAY;YACZ,cAAc;YACd,WAAW;YACX,aAAa;YACb,6BAA6B;YAC7B,WAAW;YACX,cAAc;YACd,WAAW;YACX,OAAO;YACP,2BAA2B;YAC3B,SAAS;YACT,iBAAiB;YACjB,aAAa;SACd,CAAA;QACD,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,CAAA;QAChD,MAAM,UAAU,GAAG,sBAAsB,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAA;QACrG,MAAM,aAAa,GAAG,oCAAoC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;QAC7E,OAAO,UAAU,IAAI,aAAa,CAAA;IACpC,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,gDAAgD;IAChD,IAAI,uBAAuB,CAAC,KAAK,CAAC,EAAE,CAAC;QACnC,OAAO,IAAI,CAAA;IACb,CAAC;IAED,uEAAuE;IACvE,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,MAAM,6BAA6B,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC,CAAA;QACvF,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,CAAA;QAChD,OAAO,6BAA6B,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAA;IAClG,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AAED,KAAK,UAAU,+BAA+B,CAC5C,cAAiC;IAEjC,IAAI,CAAC,cAAc,CAAC,oBAAoB,EAAE,CAAC;QACzC,OAAO,cAAc,CAAC,OAAO,EAAE,CAAA;IACjC,CAAC;IAED,IAAI,aAAsB,CAAA;IAE1B,IAAI,KAAK,EAAE,MAAM,QAAQ,IAAI,qBAAqB,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,CAAC;QAClF,IAAI,CAAC;YACH,OAAO,MAAM,cAAc,CAAC,OAAO,EAAE,CAAA;QACvC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,aAAa,GAAG,GAAG,CAAA;YACnB,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,EAAE,CAAC;gBAClC,MAAM,GAAG,CAAA;YACX,CAAC;YAED,yBAAyB;YACzB,IAAI,cAAc,CAAC,oBAAoB,EAAE,CAAC;gBACxC,WAAW,CAAC,cAAc,CAAC,GAAG,EAAE,iBAAkB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAA;YAC5E,CAAC;YAED,WAAW,CAAC,uBAAuB,cAAc,CAAC,GAAG,yBAAyB,GAAG,EAAE,CAAC,CAAA;QACtF,CAAC;IACH,CAAC;IACD,MAAM,aAAa,CAAA;AACrB,CAAC;AAED,KAAK,UAAU,kBAAkB,CAC/B,cAAiC;IAEjC,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,CAAA;IAC5B,IAAI,QAAQ,GAAG,CAAC,CAAA;IAChB,MAAM,eAAe,GAA2B,EAAE,CAAA;IAClD,MAAM,YAAY,GAAG,WAAW,CAAC,cAAc,CAAC,GAAG,CAAC,CAAA;IACpD,IAAI,QAAQ,GAAM,EAAO,CAAA;IACzB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,+BAA+B,CAAC,cAAc,CAAC,CAAA;QAChE,8DAA8D;QAC9D,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAU,EAAE,GAAQ,EAAE,EAAE;YAChD,IAAI,2BAA2B,CAAC,GAAG,CAAC;gBAAE,eAAe,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;QACpE,CAAC,CAAC,CAAA;QACF,qDAAqD;IACvD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,CAAA;QAC5B,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,CAAA;QAE9B,IAAI,GAAG,YAAY,WAAW,EAAE,CAAC;YAC/B,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;gBACzB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAqC,EAAE,CAAC;oBAC9E,IAAI,2BAA2B,CAAC,GAAG,CAAC;wBAAE,eAAe,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;gBACpE,CAAC;YACH,CAAC;YACD,MAAM,gBAAgB,GAAG,sBAAsB,CAAC,eAAe,CAAC,CAAA;YAEhE,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrB,IAAI,OAA2B,CAAA;gBAE/B,IAAI,CAAC;oBACH,OAAO,GAAG,eAAe,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,aAAa,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;oBAC1G,qDAAqD;gBACvD,CAAC;gBAAC,MAAM,CAAC;oBACP,iDAAiD;gBACnD,CAAC;gBACD,OAAO;oBACL,MAAM,EAAE,WAAW;oBACnB,WAAW,EAAE,GAAG;oBAChB,QAAQ;oBACR,gBAAgB;oBAChB,YAAY;oBACZ,SAAS,EAAE,eAAe,CAAC,cAAc,CAAC;oBAC1C,OAAO;iBACR,CAAA;YACH,CAAC;iBAAM,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACvC,OAAO;oBACL,MAAM,EAAE,cAAc;oBACtB,WAAW,EAAE,GAAG;oBAChB,QAAQ;oBACR,gBAAgB;oBAChB,YAAY;oBACZ,SAAS,EAAE,eAAe,CAAC,cAAc,CAAC;oBAC1C,OAAO,EAAE,GAAG;iBACb,CAAA;YACH,CAAC;YAED,OAAO;gBACL,MAAM,EAAE,cAAc;gBACtB,WAAW,EAAE,GAAG;gBAChB,QAAQ;gBACR,gBAAgB;gBAChB,YAAY;gBACZ,SAAS,EAAE,eAAe,CAAC,cAAc,CAAC;aAC3C,CAAA;QACH,CAAC;QACD,OAAO;YACL,MAAM,EAAE,eAAe;YACvB,KAAK,EAAE,GAAG;YACV,QAAQ;YACR,gBAAgB,EAAE,sBAAsB,CAAC,eAAe,CAAC;YACzD,YAAY;YACZ,SAAS,EAAE,eAAe,CAAC,cAAc,CAAC;SAC3C,CAAA;IACH,CAAC;IACD,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,CAAA;IAC5B,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,CAAA;IAC9B,OAAO;QACL,MAAM,EAAE,IAAI;QACZ,QAAQ;QACR,QAAQ;QACR,gBAAgB,EAAE,sBAAsB,CAAC,eAAe,CAAC;QACzD,YAAY;QACZ,SAAS,EAAE,eAAe,CAAC,cAAc,CAAC;KAC3C,CAAA;AACH,CAAC;AAED,0EAA0E;AAC1E,uEAAuE;AACvE,wEAAwE;AACxE,mCAAmC;AACnC,SAAS,WAAW,CAAC,KAAkB;IACrC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAClC,OAAO,IAAI,CAAA;IACb,CAAC;IACD,OAAO,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;AAChD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,cAAiC,EACjC,YAAyE;IAEzE,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,cAAc,CAAC,CAAA;IAEvD,WAAW,CAAC,cAAc,MAAM,CAAC,YAAY,iBAAiB,MAAM,CAAC,QAAQ;;EAE7E,MAAM,CAAC,gBAAgB;KACpB,CAAC,CAAA;IAEJ,QAAQ,MAAM,CAAC,MAAM,EAAE,CAAC;QACtB,KAAK,IAAI,CAAC,CAAC,CAAC;YACV,OAAO,MAAM,CAAC,QAAQ,CAAA;QACxB,CAAC;QACD,KAAK,cAAc,CAAC,CAAC,CAAC;YACpB,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,YAAY,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;YAC1D,CAAC;iBAAM,CAAC;gBACN,MAAM,MAAM,CAAC,WAAW,CAAA;YAC1B,CAAC;QACH,CAAC;QACD,KAAK,eAAe,CAAC,CAAC,CAAC;YACrB,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,YAAY,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;YACpD,CAAC;iBAAM,CAAC;gBACN,MAAM,MAAM,CAAC,KAAK,CAAA;YACpB,CAAC;QACH,CAAC;QACD,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,YAAY,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;YAC1D,CAAC;iBAAM,CAAC;gBACN,MAAM,MAAM,CAAC,WAAW,CAAA;YAC1B,CAAC;QACH,CAAC;QACD,KAAK,cAAc,CAAC,CAAC,CAAC;YACpB,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,YAAY,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;YAC1D,CAAC;iBAAM,CAAC;gBACN,MAAM,MAAM,CAAC,WAAW,CAAA;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,cAAiC,EACjC,YAAyE,EACzE,eAII;IACF,aAAa,EAAE,UAAU;CAC1B;IAED,IAAI,WAAW,GAAG,CAAC,CAAA;IACnB,MAAM,cAAc,GAAG,YAAY,CAAC,cAAc,IAAI,mBAAmB,CAAA;IAEzE,IAAI,MAAM,GAAG,MAAM,kBAAkB,CAAC,cAAc,CAAC,CAAA;IAErD,WAAW,CAAC,cAAc,MAAM,CAAC,YAAY,iBAAiB,MAAM,CAAC,QAAQ;;EAE7E,MAAM,CAAC,gBAAgB;KACpB,CAAC,CAAA;IAEJ,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YAC3B,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;gBACpB,WAAW,CAAC,cAAc,MAAM,CAAC,YAAY,oBAAoB,WAAW,UAAU,CAAC,CAAA;YACzF,CAAC;YACD,OAAO,MAAM,CAAC,QAAQ,CAAA;QACxB,CAAC;aAAM,IAAI,MAAM,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;YAC5C,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,YAAY,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;YAC1D,CAAC;iBAAM,CAAC;gBACN,MAAM,MAAM,CAAC,WAAW,CAAA;YAC1B,CAAC;QACH,CAAC;aAAM,IAAI,MAAM,CAAC,MAAM,KAAK,eAAe,EAAE,CAAC;YAC7C,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,YAAY,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;YACpD,CAAC;iBAAM,CAAC;gBACN,MAAM,MAAM,CAAC,KAAK,CAAA;YACpB,CAAC;QACH,CAAC;aAAM,IAAI,MAAM,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;YAC5C,MAAM,MAAM,CAAC,WAAW,CAAA;QAC1B,CAAC;QAED,IAAI,cAAc,IAAI,WAAW,EAAE,CAAC;YAClC,WAAW,CAAC,GAAG,cAAc,qCAAqC,MAAM,CAAC,YAAY,EAAE,CAAC,CAAA;YACxF,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,YAAY,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;YAC1D,CAAC;iBAAM,CAAC;gBACN,MAAM,MAAM,CAAC,WAAW,CAAA;YAC1B,CAAC;QACH,CAAC;QACD,WAAW,IAAI,CAAC,CAAA;QAEhB,yBAAyB;QACzB,IAAI,cAAc,CAAC,oBAAoB,EAAE,CAAC;YACxC,WAAW,CAAC,cAAc,CAAC,GAAG,EAAE,cAAc,WAAW,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,CAAA;QAChF,CAAC;QAED,uGAAuG;QACvG,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,IAAI,YAAY,CAAC,cAAc,IAAI,sBAAsB,CAAA;QAC5F,WAAW,CAAC,6BAA6B,WAAW,OAAO,MAAM,CAAC,YAAY,OAAO,YAAY,KAAK,CAAC,CAAA;QAEvG,4CAA4C;QAC5C,MAAM,GAAG,MAAM,IAAI,OAAO,CAAqB,CAAC,OAAO,EAAE,EAAE;YACzD,YAAY,CAAC,aAAa,CAAC,GAAG,EAAE;gBAC9B,OAAO,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAC,CAAA;YAC7C,CAAC,EAAE,YAAY,CAAC,CAAA;QAClB,CAAC,CAAC,CAAA;IACJ,CAAC;AACH,CAAC","sourcesContent":["import {sanitizedHeadersOutput} from './api/headers.js'\nimport {sanitizeURL} from './api/urls.js'\nimport {hasRateLimitCode} from './analytics/graphql-error-codes.js'\nimport {sleepWithBackoffUntil} from './sleep-with-backoff.js'\nimport {outputDebug} from '../../public/node/output.js'\nimport {recordRetry} from '../../public/node/analytics.js'\n\nimport {Headers} from 'form-data'\nimport {ClientError} from 'graphql-request'\n\nimport {performance} from 'perf_hooks'\n\nexport type API = 'admin' | 'storefront-renderer' | 'partners' | 'business-platform' | 'app-management'\n\nexport const allAPIs: API[] = ['admin', 'storefront-renderer', 'partners', 'business-platform', 'app-management']\n\nconst DEFAULT_RETRY_DELAY_MS = 1000\nconst DEFAULT_RETRY_LIMIT = 10\n\nexport type NetworkRetryBehaviour =\n | {\n useNetworkLevelRetry: true\n maxRetryTimeMs: number\n recordCommandRetries?: boolean\n }\n | {\n useNetworkLevelRetry: false\n recordCommandRetries?: boolean\n }\n\ntype RequestOptions<T> = {\n request: () => Promise<T>\n url: string\n} & NetworkRetryBehaviour\n\nconst interestingResponseHeaders = new Set([\n 'cache-control',\n 'content-type',\n 'etag',\n 'x-request-id',\n 'server-timing',\n 'retry-after',\n])\n\nfunction responseHeaderIsInteresting(header: string): boolean {\n return interestingResponseHeaders.has(header)\n}\n\ninterface CommonResponse {\n duration: number\n sanitizedHeaders: string\n sanitizedUrl: string\n requestId?: string\n}\n\ntype OkResponse<T> = CommonResponse & {status: 'ok'; response: T}\ntype ClientErrorResponse = CommonResponse & {status: 'client-error'; clientError: ClientError}\ntype UnknownErrorResponse = CommonResponse & {status: 'unknown-error'; error: unknown}\ntype CanRetryErrorResponse = CommonResponse & {\n status: 'can-retry'\n clientError: ClientError\n delayMs: number | undefined\n}\ntype UnauthorizedErrorResponse = CommonResponse & {\n status: 'unauthorized'\n clientError: ClientError\n delayMs: number | undefined\n}\n\ntype VerboseResponse<T> =\n | OkResponse<T>\n | ClientErrorResponse\n | UnknownErrorResponse\n | CanRetryErrorResponse\n | UnauthorizedErrorResponse\n\n/**\n * Checks if an error is a transient network error that is likely to recover with retries.\n *\n * Use this function for retry logic. Use isNetworkError for error classification.\n *\n * Examples of transient errors (worth retrying):\n * - Connection timeouts, resets, and aborts\n * - DNS failures (enotfound, getaddrinfo, eai_again) - can be temporary\n * - Socket disconnects and hang ups\n * - Premature connection closes\n */\nexport function isTransientNetworkError(error: unknown): boolean {\n if (error instanceof Error) {\n const transientErrorMessages = [\n 'socket hang up',\n 'econnreset',\n 'econnaborted',\n 'enotfound',\n 'enetunreach',\n 'network socket disconnected',\n 'etimedout',\n 'econnrefused',\n 'eai_again',\n 'epipe',\n 'the operation was aborted',\n 'timeout',\n 'premature close',\n 'getaddrinfo',\n ]\n const errorMessage = error.message.toLowerCase()\n const anyMatches = transientErrorMessages.some((issueMessage) => errorMessage.includes(issueMessage))\n const missingReason = /^request to .* failed, reason:\\s*$/.test(errorMessage)\n return anyMatches || missingReason\n }\n return false\n}\n\n/**\n * Checks if an error is any kind of network-related error (connection issues, timeouts, DNS failures,\n * TLS/certificate errors, etc.) rather than an application logic error.\n *\n * These errors should be reported as user-facing errors (AbortError) rather than bugs (BugError),\n * regardless of whether they are transient or permanent.\n *\n * Examples include:\n * - Transient: connection timeouts, socket hang ups, temporary DNS failures\n * - Permanent: certificate validation failures, misconfigured SSL\n */\nexport function isNetworkError(error: unknown): boolean {\n // First check if it's a transient network error\n if (isTransientNetworkError(error)) {\n return true\n }\n\n // Then check for permanent network errors (SSL/TLS/certificate issues)\n if (error instanceof Error) {\n const permanentNetworkErrorMessages = ['certificate', 'cert', 'tls', 'ssl', 'altnames']\n const errorMessage = error.message.toLowerCase()\n return permanentNetworkErrorMessages.some((issueMessage) => errorMessage.includes(issueMessage))\n }\n\n return false\n}\n\nasync function runRequestWithNetworkLevelRetry<T extends {headers: Headers; status: number}>(\n requestOptions: RequestOptions<T>,\n): Promise<T> {\n if (!requestOptions.useNetworkLevelRetry) {\n return requestOptions.request()\n }\n\n let lastSeenError: unknown\n\n for await (const _delayMs of sleepWithBackoffUntil(requestOptions.maxRetryTimeMs)) {\n try {\n return await requestOptions.request()\n } catch (err) {\n lastSeenError = err\n if (!isTransientNetworkError(err)) {\n throw err\n }\n\n // Record command retries\n if (requestOptions.recordCommandRetries) {\n recordRetry(requestOptions.url, `network-retry:${(err as Error).message}`)\n }\n\n outputDebug(`Retrying request to ${requestOptions.url} due to network error ${err}`)\n }\n }\n throw lastSeenError\n}\n\nasync function makeVerboseRequest<T extends {headers: Headers; status: number}>(\n requestOptions: RequestOptions<T>,\n): Promise<VerboseResponse<T>> {\n const t0 = performance.now()\n let duration = 0\n const responseHeaders: Record<string, string> = {}\n const sanitizedUrl = sanitizeURL(requestOptions.url)\n let response: T = {} as T\n try {\n response = await runRequestWithNetworkLevelRetry(requestOptions)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n response.headers.forEach((value: any, key: any) => {\n if (responseHeaderIsInteresting(key)) responseHeaders[key] = value\n })\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (err) {\n const t1 = performance.now()\n duration = Math.round(t1 - t0)\n\n if (err instanceof ClientError) {\n if (err.response.headers) {\n for (const [key, value] of err.response.headers as Iterable<[string, string]>) {\n if (responseHeaderIsInteresting(key)) responseHeaders[key] = value\n }\n }\n const sanitizedHeaders = sanitizedHeadersOutput(responseHeaders)\n\n if (isThrottled(err)) {\n let delayMs: number | undefined\n\n try {\n delayMs = responseHeaders['retry-after'] ? Number.parseInt(responseHeaders['retry-after'], 10) : undefined\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch {\n // ignore errors in extracting retry-after header\n }\n return {\n status: 'can-retry',\n clientError: err,\n duration,\n sanitizedHeaders,\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n delayMs,\n }\n } else if (err.response.status === 401) {\n return {\n status: 'unauthorized',\n clientError: err,\n duration,\n sanitizedHeaders,\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n delayMs: 500,\n }\n }\n\n return {\n status: 'client-error',\n clientError: err,\n duration,\n sanitizedHeaders,\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n }\n }\n return {\n status: 'unknown-error',\n error: err,\n duration,\n sanitizedHeaders: sanitizedHeadersOutput(responseHeaders),\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n }\n }\n const t1 = performance.now()\n duration = Math.round(t1 - t0)\n return {\n status: 'ok',\n response,\n duration,\n sanitizedHeaders: sanitizedHeadersOutput(responseHeaders),\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n }\n}\n\n// Shopify GraphQL APIs signal rate limiting with `extensions.code` set to\n// `THROTTLED` (often on a 200 response) or `429` — the same codes that\n// crash-report suppression and analytics grouping already treat as rate\n// limiting via this shared helper.\nfunction isThrottled(error: ClientError): boolean {\n if (error.response.status === 429) {\n return true\n }\n return hasRateLimitCode(error.response.errors)\n}\n\nexport async function simpleRequestWithDebugLog<T extends {headers: Headers; status: number}>(\n requestOptions: RequestOptions<T>,\n errorHandler?: (error: unknown, requestId: string | undefined) => unknown,\n): Promise<T> {\n const result = await makeVerboseRequest(requestOptions)\n\n outputDebug(`Request to ${result.sanitizedUrl} completed in ${result.duration} ms\nWith response headers:\n${result.sanitizedHeaders}\n `)\n\n switch (result.status) {\n case 'ok': {\n return result.response\n }\n case 'client-error': {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n case 'unknown-error': {\n if (errorHandler) {\n throw errorHandler(result.error, result.requestId)\n } else {\n throw result.error\n }\n }\n case 'can-retry': {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n case 'unauthorized': {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n }\n}\n\n/**\n * Makes a HTTP request to some API, retrying if response headers indicate a retryable error.\n *\n * If a request fails with a 429, the retry-after header determines a delay before an automatic retry is performed.\n *\n * If unauthorizedHandler is provided, then it will be called in the case of a 401 and a retry performed. This allows\n * for a token refresh for instance.\n *\n * If there's a network error, e.g. DNS fails to resolve, then API calls are automatically retried.\n *\n * @param request - A function that returns a promise of the response\n * @param url - The URL to request\n * @param errorHandler - A function that handles errors\n * @param unauthorizedHandler - A function that handles unauthorized errors\n * @param retryOptions - Options for the retry\n * @returns The response from the request\n */\nexport async function retryAwareRequest<T extends {headers: Headers; status: number}>(\n requestOptions: RequestOptions<T>,\n errorHandler?: (error: unknown, requestId: string | undefined) => unknown,\n retryOptions: {\n limitRetriesTo?: number\n defaultDelayMs?: number\n scheduleDelay: (fn: () => void, delay: number) => void\n } = {\n scheduleDelay: setTimeout,\n },\n): Promise<T> {\n let retriesUsed = 0\n const limitRetriesTo = retryOptions.limitRetriesTo ?? DEFAULT_RETRY_LIMIT\n\n let result = await makeVerboseRequest(requestOptions)\n\n outputDebug(`Request to ${result.sanitizedUrl} completed in ${result.duration} ms\nWith response headers:\n${result.sanitizedHeaders}\n `)\n\n while (true) {\n if (result.status === 'ok') {\n if (retriesUsed > 0) {\n outputDebug(`Request to ${result.sanitizedUrl} succeeded after ${retriesUsed} retries`)\n }\n return result.response\n } else if (result.status === 'client-error') {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n } else if (result.status === 'unknown-error') {\n if (errorHandler) {\n throw errorHandler(result.error, result.requestId)\n } else {\n throw result.error\n }\n } else if (result.status === 'unauthorized') {\n throw result.clientError\n }\n\n if (limitRetriesTo <= retriesUsed) {\n outputDebug(`${limitRetriesTo} retries exhausted for request to ${result.sanitizedUrl}`)\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n retriesUsed += 1\n\n // Record command retries\n if (requestOptions.recordCommandRetries) {\n recordRetry(requestOptions.url, `http-retry-${retriesUsed}:${result.status}:`)\n }\n\n // prefer to wait based on a header if given; the caller's preference if not; and a default if neither.\n const retryDelayMs = result.delayMs ?? retryOptions.defaultDelayMs ?? DEFAULT_RETRY_DELAY_MS\n outputDebug(`Scheduling retry request #${retriesUsed} to ${result.sanitizedUrl} in ${retryDelayMs} ms`)\n\n // eslint-disable-next-line no-await-in-loop\n result = await new Promise<VerboseResponse<T>>((resolve) => {\n retryOptions.scheduleDelay(() => {\n resolve(makeVerboseRequest(requestOptions))\n }, retryDelayMs)\n })\n }\n}\n"]}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/private/node/api.ts"],"names":[],"mappings":"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","sourcesContent":["import {sanitizedHeadersOutput} from './api/headers.js'\nimport {sanitizeURL} from './api/urls.js'\nimport {hasRateLimitCode} from './analytics/graphql-error-codes.js'\nimport {sleepWithBackoffUntil} from './sleep-with-backoff.js'\nimport {outputDebug} from '../../public/node/output.js'\nimport {recordRetry} from '../../public/node/analytics.js'\n\nimport {Headers} from 'form-data'\nimport {ClientError} from 'graphql-request'\n\nimport {performance} from 'perf_hooks'\n\nexport type API = 'admin' | 'storefront-renderer' | 'partners' | 'business-platform' | 'app-management'\n\nexport const allAPIs: API[] = ['admin', 'storefront-renderer', 'partners', 'business-platform', 'app-management']\n\nconst DEFAULT_RETRY_DELAY_MS = 1000\nconst DEFAULT_RETRY_LIMIT = 10\n\nexport type NetworkRetryBehaviour =\n | {\n useNetworkLevelRetry: true\n maxRetryTimeMs: number\n recordCommandRetries?: boolean\n }\n | {\n useNetworkLevelRetry: false\n recordCommandRetries?: boolean\n }\n\ntype RequestOptions<T> = {\n request: () => Promise<T>\n url: string\n} & NetworkRetryBehaviour\n\nconst interestingResponseHeaders = new Set([\n 'cache-control',\n 'content-type',\n 'etag',\n 'x-request-id',\n 'server-timing',\n 'retry-after',\n])\n\nfunction responseHeaderIsInteresting(header: string): boolean {\n return interestingResponseHeaders.has(header)\n}\n\ninterface CommonResponse {\n duration: number\n sanitizedHeaders: string\n sanitizedUrl: string\n requestId?: string\n}\n\ntype OkResponse<T> = CommonResponse & {status: 'ok'; response: T}\ntype ClientErrorResponse = CommonResponse & {status: 'client-error'; clientError: ClientError}\ntype UnknownErrorResponse = CommonResponse & {status: 'unknown-error'; error: unknown}\ntype CanRetryErrorResponse = CommonResponse & {\n status: 'can-retry'\n clientError: ClientError\n delayMs: number | undefined\n}\ntype UnauthorizedErrorResponse = CommonResponse & {\n status: 'unauthorized'\n clientError: ClientError\n delayMs: number | undefined\n}\n\ntype VerboseResponse<T> =\n | OkResponse<T>\n | ClientErrorResponse\n | UnknownErrorResponse\n | CanRetryErrorResponse\n | UnauthorizedErrorResponse\n\n/**\n * Checks if an error is a transient network error that is likely to recover with retries.\n *\n * Use this function for retry logic. Use isNetworkError for error classification.\n *\n * Examples of transient errors (worth retrying):\n * - Connection timeouts, resets, and aborts\n * - DNS failures (enotfound, getaddrinfo, eai_again) - can be temporary\n * - Socket disconnects and hang ups\n * - Premature connection closes\n */\nexport function isTransientNetworkError(error: unknown): boolean {\n if (error instanceof Error) {\n const transientErrorMessages = [\n 'socket hang up',\n 'econnreset',\n 'econnaborted',\n 'enotfound',\n 'enetunreach',\n 'network socket disconnected',\n 'etimedout',\n 'econnrefused',\n 'eai_again',\n 'epipe',\n 'the operation was aborted',\n 'timeout',\n 'premature close',\n 'getaddrinfo',\n ]\n const errorMessage = error.message.toLowerCase()\n const anyMatches = transientErrorMessages.some((issueMessage) => errorMessage.includes(issueMessage))\n const missingReason = /^request to .* failed, reason:\\s*$/.test(errorMessage)\n return anyMatches || missingReason\n }\n return false\n}\n\n/**\n * Checks if an error is any kind of network-related error (connection issues, timeouts, DNS failures,\n * TLS/certificate errors, etc.) rather than an application logic error.\n *\n * These errors should be reported as user-facing errors (AbortError) rather than bugs (BugError),\n * regardless of whether they are transient or permanent.\n *\n * Examples include:\n * - Transient: connection timeouts, socket hang ups, temporary DNS failures\n * - Permanent: certificate validation failures, misconfigured SSL\n */\nexport function isNetworkError(error: unknown): boolean {\n // First check if it's a transient network error\n if (isTransientNetworkError(error)) {\n return true\n }\n\n // Then check for permanent network errors (SSL/TLS/certificate issues)\n if (error instanceof Error) {\n const permanentNetworkErrorMessages = ['certificate', 'cert', 'tls', 'ssl', 'altnames']\n const errorMessage = error.message.toLowerCase()\n return permanentNetworkErrorMessages.some((issueMessage) => errorMessage.includes(issueMessage))\n }\n\n return false\n}\n\n/**\n * Lower-cased substrings that mean a request was aborted rather than failing on its own.\n * `node-fetch` says 'The user aborted a request.', undici says 'This operation was aborted', and\n * cli-kit's own request timeout says 'The operation was aborted'.\n */\nconst ABORTED_FETCH_MESSAGE_FRAGMENTS = ['the user aborted a request', 'operation was aborted'] as const\n\n/**\n * Checks if an error is an aborted request: a user cancelling the command, the host process\n * cancelling it, or one of the CLI's own request timeouts firing.\n *\n * Not used by the retry logic, because a user-cancelled request must not be retried.\n * `isTransientNetworkError` separately matches the CLI's own timeout message, so timeouts do\n * still retry.\n *\n * The `name` check matches the `AbortError` shape that fetch throws, not cli-kit's own\n * `AbortError`, which leaves `name` as 'Error'.\n *\n * @param error - Error to be checked.\n * @returns A boolean indicating if the request was aborted.\n */\nexport function isAbortedFetchError(error: unknown): boolean {\n if (!(error instanceof Error)) return false\n if (error.name === 'AbortError') return true\n const errorMessage = error.message.toLowerCase()\n return ABORTED_FETCH_MESSAGE_FRAGMENTS.some((fragment) => errorMessage.includes(fragment))\n}\n\nasync function runRequestWithNetworkLevelRetry<T extends {headers: Headers; status: number}>(\n requestOptions: RequestOptions<T>,\n): Promise<T> {\n if (!requestOptions.useNetworkLevelRetry) {\n return requestOptions.request()\n }\n\n let lastSeenError: unknown\n\n for await (const _delayMs of sleepWithBackoffUntil(requestOptions.maxRetryTimeMs)) {\n try {\n return await requestOptions.request()\n } catch (err) {\n lastSeenError = err\n if (!isTransientNetworkError(err)) {\n throw err\n }\n\n // Record command retries\n if (requestOptions.recordCommandRetries) {\n recordRetry(requestOptions.url, `network-retry:${(err as Error).message}`)\n }\n\n outputDebug(`Retrying request to ${requestOptions.url} due to network error ${err}`)\n }\n }\n throw lastSeenError\n}\n\nasync function makeVerboseRequest<T extends {headers: Headers; status: number}>(\n requestOptions: RequestOptions<T>,\n): Promise<VerboseResponse<T>> {\n const t0 = performance.now()\n let duration = 0\n const responseHeaders: Record<string, string> = {}\n const sanitizedUrl = sanitizeURL(requestOptions.url)\n let response: T = {} as T\n try {\n response = await runRequestWithNetworkLevelRetry(requestOptions)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n response.headers.forEach((value: any, key: any) => {\n if (responseHeaderIsInteresting(key)) responseHeaders[key] = value\n })\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (err) {\n const t1 = performance.now()\n duration = Math.round(t1 - t0)\n\n if (err instanceof ClientError) {\n if (err.response.headers) {\n for (const [key, value] of err.response.headers as Iterable<[string, string]>) {\n if (responseHeaderIsInteresting(key)) responseHeaders[key] = value\n }\n }\n const sanitizedHeaders = sanitizedHeadersOutput(responseHeaders)\n\n if (isThrottled(err)) {\n let delayMs: number | undefined\n\n try {\n delayMs = responseHeaders['retry-after'] ? Number.parseInt(responseHeaders['retry-after'], 10) : undefined\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch {\n // ignore errors in extracting retry-after header\n }\n return {\n status: 'can-retry',\n clientError: err,\n duration,\n sanitizedHeaders,\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n delayMs,\n }\n } else if (err.response.status === 401) {\n return {\n status: 'unauthorized',\n clientError: err,\n duration,\n sanitizedHeaders,\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n delayMs: 500,\n }\n }\n\n return {\n status: 'client-error',\n clientError: err,\n duration,\n sanitizedHeaders,\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n }\n }\n return {\n status: 'unknown-error',\n error: err,\n duration,\n sanitizedHeaders: sanitizedHeadersOutput(responseHeaders),\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n }\n }\n const t1 = performance.now()\n duration = Math.round(t1 - t0)\n return {\n status: 'ok',\n response,\n duration,\n sanitizedHeaders: sanitizedHeadersOutput(responseHeaders),\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n }\n}\n\n// Shopify GraphQL APIs signal rate limiting with `extensions.code` set to\n// `THROTTLED` (often on a 200 response) or `429` — the same codes that\n// crash-report suppression and analytics grouping already treat as rate\n// limiting via this shared helper.\nfunction isThrottled(error: ClientError): boolean {\n if (error.response.status === 429) {\n return true\n }\n return hasRateLimitCode(error.response.errors)\n}\n\nexport async function simpleRequestWithDebugLog<T extends {headers: Headers; status: number}>(\n requestOptions: RequestOptions<T>,\n errorHandler?: (error: unknown, requestId: string | undefined) => unknown,\n): Promise<T> {\n const result = await makeVerboseRequest(requestOptions)\n\n outputDebug(`Request to ${result.sanitizedUrl} completed in ${result.duration} ms\nWith response headers:\n${result.sanitizedHeaders}\n `)\n\n switch (result.status) {\n case 'ok': {\n return result.response\n }\n case 'client-error': {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n case 'unknown-error': {\n if (errorHandler) {\n throw errorHandler(result.error, result.requestId)\n } else {\n throw result.error\n }\n }\n case 'can-retry': {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n case 'unauthorized': {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n }\n}\n\n/**\n * Makes a HTTP request to some API, retrying if response headers indicate a retryable error.\n *\n * If a request fails with a 429, the retry-after header determines a delay before an automatic retry is performed.\n *\n * If unauthorizedHandler is provided, then it will be called in the case of a 401 and a retry performed. This allows\n * for a token refresh for instance.\n *\n * If there's a network error, e.g. DNS fails to resolve, then API calls are automatically retried.\n *\n * @param request - A function that returns a promise of the response\n * @param url - The URL to request\n * @param errorHandler - A function that handles errors\n * @param unauthorizedHandler - A function that handles unauthorized errors\n * @param retryOptions - Options for the retry\n * @returns The response from the request\n */\nexport async function retryAwareRequest<T extends {headers: Headers; status: number}>(\n requestOptions: RequestOptions<T>,\n errorHandler?: (error: unknown, requestId: string | undefined) => unknown,\n retryOptions: {\n limitRetriesTo?: number\n defaultDelayMs?: number\n scheduleDelay: (fn: () => void, delay: number) => void\n } = {\n scheduleDelay: setTimeout,\n },\n): Promise<T> {\n let retriesUsed = 0\n const limitRetriesTo = retryOptions.limitRetriesTo ?? DEFAULT_RETRY_LIMIT\n\n let result = await makeVerboseRequest(requestOptions)\n\n outputDebug(`Request to ${result.sanitizedUrl} completed in ${result.duration} ms\nWith response headers:\n${result.sanitizedHeaders}\n `)\n\n while (true) {\n if (result.status === 'ok') {\n if (retriesUsed > 0) {\n outputDebug(`Request to ${result.sanitizedUrl} succeeded after ${retriesUsed} retries`)\n }\n return result.response\n } else if (result.status === 'client-error') {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n } else if (result.status === 'unknown-error') {\n if (errorHandler) {\n throw errorHandler(result.error, result.requestId)\n } else {\n throw result.error\n }\n } else if (result.status === 'unauthorized') {\n throw result.clientError\n }\n\n if (limitRetriesTo <= retriesUsed) {\n outputDebug(`${limitRetriesTo} retries exhausted for request to ${result.sanitizedUrl}`)\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n retriesUsed += 1\n\n // Record command retries\n if (requestOptions.recordCommandRetries) {\n recordRetry(requestOptions.url, `http-retry-${retriesUsed}:${result.status}:`)\n }\n\n // prefer to wait based on a header if given; the caller's preference if not; and a default if neither.\n const retryDelayMs = result.delayMs ?? retryOptions.defaultDelayMs ?? DEFAULT_RETRY_DELAY_MS\n outputDebug(`Scheduling retry request #${retriesUsed} to ${result.sanitizedUrl} in ${retryDelayMs} ms`)\n\n // eslint-disable-next-line no-await-in-loop\n result = await new Promise<VerboseResponse<T>>((resolve) => {\n retryOptions.scheduleDelay(() => {\n resolve(makeVerboseRequest(requestOptions))\n }, retryDelayMs)\n })\n }\n}\n"]}
@@ -0,0 +1,29 @@
1
+ import { type CommandEvent, type CommandEventChannelOptions, type CommandEventEmissionOptions, type CommandEventInput } from '../../public/common/command-events.js';
2
+ export type CommandEventOutputMode = 'text' | 'json';
3
+ interface RunWithCommandEventsOptions extends CommandEventChannelOptions<CommandEvent> {
4
+ outputMode?: CommandEventOutputMode;
5
+ }
6
+ /**
7
+ * Runs a command execution with an event channel available to all nested asynchronous work.
8
+ *
9
+ * @param options - The event sink, clock, and output mode used by the channel.
10
+ * @param execute - The command execution to run with the channel.
11
+ * @returns The result of the command execution.
12
+ */
13
+ export declare function runWithCommandEvents<TResult>(options: RunWithCommandEventsOptions, execute: () => TResult): TResult;
14
+ /**
15
+ * Emits an event for the current command execution.
16
+ *
17
+ * Events emitted outside a command execution are ignored.
18
+ *
19
+ * @param event - The event to emit before its timestamp is added.
20
+ * @param options - Presentation details that are not included in the event.
21
+ */
22
+ export declare function emitCommandEvent(event: CommandEventInput, options?: CommandEventEmissionOptions): void;
23
+ /**
24
+ * Returns how command events are presented for the current execution.
25
+ *
26
+ * @returns The current event output mode, or undefined outside a command event context.
27
+ */
28
+ export declare function commandEventOutputMode(): CommandEventOutputMode | undefined;
29
+ export {};
@@ -0,0 +1,43 @@
1
+ import { createCommandEventChannel, } from '../../public/common/command-events.js';
2
+ import { AsyncLocalStorage } from 'node:async_hooks';
3
+ /**
4
+ * Runs a command execution with an event channel available to all nested asynchronous work.
5
+ *
6
+ * @param options - The event sink, clock, and output mode used by the channel.
7
+ * @param execute - The command execution to run with the channel.
8
+ * @returns The result of the command execution.
9
+ */
10
+ export function runWithCommandEvents(options, execute) {
11
+ return getCommandEventStorage().run({
12
+ channel: createCommandEventChannel(options),
13
+ outputMode: options.outputMode ?? 'text',
14
+ }, execute);
15
+ }
16
+ /**
17
+ * Emits an event for the current command execution.
18
+ *
19
+ * Events emitted outside a command execution are ignored.
20
+ *
21
+ * @param event - The event to emit before its timestamp is added.
22
+ * @param options - Presentation details that are not included in the event.
23
+ */
24
+ export function emitCommandEvent(event, options) {
25
+ getCommandEventStorage().getStore()?.channel.emit(event, options);
26
+ }
27
+ /**
28
+ * Returns how command events are presented for the current execution.
29
+ *
30
+ * @returns The current event output mode, or undefined outside a command event context.
31
+ */
32
+ export function commandEventOutputMode() {
33
+ return getCommandEventStorage().getStore()?.outputMode;
34
+ }
35
+ function getCommandEventStorage() {
36
+ const key = Symbol.for('command-event-storage');
37
+ const sharedGlobal = globalThis;
38
+ // cli-kit can be loaded both externally and inside the bundled CLI. Both copies must observe
39
+ // the same command execution context so output helpers consistently emit JSON events.
40
+ sharedGlobal[key] ??= new AsyncLocalStorage();
41
+ return sharedGlobal[key];
42
+ }
43
+ //# sourceMappingURL=command-event-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-event-context.js","sourceRoot":"","sources":["../../../src/private/node/command-event-context.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,GAM1B,MAAM,uCAAuC,CAAA;AAC9C,OAAO,EAAC,iBAAiB,EAAC,MAAM,kBAAkB,CAAA;AAalD;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAU,OAAoC,EAAE,OAAsB;IACxG,OAAO,sBAAsB,EAAE,CAAC,GAAG,CACjC;QACE,OAAO,EAAE,yBAAyB,CAAC,OAAO,CAAC;QAC3C,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,MAAM;KACzC,EACD,OAAO,CACR,CAAA;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAwB,EAAE,OAAqC;IAC9F,sBAAsB,EAAE,CAAC,QAAQ,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;AACnE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB;IACpC,OAAO,sBAAsB,EAAE,CAAC,QAAQ,EAAE,EAAE,UAAU,CAAA;AACxD,CAAC;AAED,SAAS,sBAAsB;IAC7B,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAA;IAC/C,MAAM,YAAY,GAAG,UAEpB,CAAA;IAED,6FAA6F;IAC7F,sFAAsF;IACtF,YAAY,CAAC,GAAG,CAAC,KAAK,IAAI,iBAAiB,EAAuB,CAAA;IAClE,OAAO,YAAY,CAAC,GAAG,CAAC,CAAA;AAC1B,CAAC","sourcesContent":["import {\n createCommandEventChannel,\n type CommandEvent,\n type CommandEventChannel,\n type CommandEventChannelOptions,\n type CommandEventEmissionOptions,\n type CommandEventInput,\n} from '../../public/common/command-events.js'\nimport {AsyncLocalStorage} from 'node:async_hooks'\n\nexport type CommandEventOutputMode = 'text' | 'json'\n\ninterface CommandEventContext {\n channel: CommandEventChannel\n outputMode: CommandEventOutputMode\n}\n\ninterface RunWithCommandEventsOptions extends CommandEventChannelOptions<CommandEvent> {\n outputMode?: CommandEventOutputMode\n}\n\n/**\n * Runs a command execution with an event channel available to all nested asynchronous work.\n *\n * @param options - The event sink, clock, and output mode used by the channel.\n * @param execute - The command execution to run with the channel.\n * @returns The result of the command execution.\n */\nexport function runWithCommandEvents<TResult>(options: RunWithCommandEventsOptions, execute: () => TResult): TResult {\n return getCommandEventStorage().run(\n {\n channel: createCommandEventChannel(options),\n outputMode: options.outputMode ?? 'text',\n },\n execute,\n )\n}\n\n/**\n * Emits an event for the current command execution.\n *\n * Events emitted outside a command execution are ignored.\n *\n * @param event - The event to emit before its timestamp is added.\n * @param options - Presentation details that are not included in the event.\n */\nexport function emitCommandEvent(event: CommandEventInput, options?: CommandEventEmissionOptions): void {\n getCommandEventStorage().getStore()?.channel.emit(event, options)\n}\n\n/**\n * Returns how command events are presented for the current execution.\n *\n * @returns The current event output mode, or undefined outside a command event context.\n */\nexport function commandEventOutputMode(): CommandEventOutputMode | undefined {\n return getCommandEventStorage().getStore()?.outputMode\n}\n\nfunction getCommandEventStorage(): AsyncLocalStorage<CommandEventContext> {\n const key = Symbol.for('command-event-storage')\n const sharedGlobal = globalThis as typeof globalThis & {\n [key]?: AsyncLocalStorage<CommandEventContext>\n }\n\n // cli-kit can be loaded both externally and inside the bundled CLI. Both copies must observe\n // the same command execution context so output helpers consistently emit JSON events.\n sharedGlobal[key] ??= new AsyncLocalStorage<CommandEventContext>()\n return sharedGlobal[key]\n}\n"]}
@@ -0,0 +1,7 @@
1
+ import { type CommandEvent } from '../../public/common/command-events.js';
2
+ /**
3
+ * Writes a command event as JSON without routing it back through the command event context.
4
+ *
5
+ * @param event - The event to write.
6
+ */
7
+ export declare function outputCommandEventAsJson(event: CommandEvent): void;
@@ -0,0 +1,16 @@
1
+ import { consoleWarn } from './output.js';
2
+ import { isUnitTest } from '../../public/node/context/local.js';
3
+ import { collectLog, outputWhereAppropriate } from '../../public/node/output.js';
4
+ import { commandEventSchema } from '../../public/common/command-events.js';
5
+ /**
6
+ * Writes a command event as JSON without routing it back through the command event context.
7
+ *
8
+ * @param event - The event to write.
9
+ */
10
+ export function outputCommandEventAsJson(event) {
11
+ const message = JSON.stringify(commandEventSchema.parse(event));
12
+ if (isUnitTest())
13
+ collectLog('info', message);
14
+ outputWhereAppropriate('info', consoleWarn, message);
15
+ }
16
+ //# sourceMappingURL=command-event-output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-event-output.js","sourceRoot":"","sources":["../../../src/private/node/command-event-output.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,aAAa,CAAA;AACvC,OAAO,EAAC,UAAU,EAAC,MAAM,oCAAoC,CAAA;AAC7D,OAAO,EAAC,UAAU,EAAE,sBAAsB,EAAC,MAAM,6BAA6B,CAAA;AAC9E,OAAO,EAAC,kBAAkB,EAAoB,MAAM,uCAAuC,CAAA;AAE3F;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,KAAmB;IAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAA;IAC/D,IAAI,UAAU,EAAE;QAAE,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7C,sBAAsB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,CAAC,CAAA;AACtD,CAAC","sourcesContent":["import {consoleWarn} from './output.js'\nimport {isUnitTest} from '../../public/node/context/local.js'\nimport {collectLog, outputWhereAppropriate} from '../../public/node/output.js'\nimport {commandEventSchema, type CommandEvent} from '../../public/common/command-events.js'\n\n/**\n * Writes a command event as JSON without routing it back through the command event context.\n *\n * @param event - The event to write.\n */\nexport function outputCommandEventAsJson(event: CommandEvent): void {\n const message = JSON.stringify(commandEventSchema.parse(event))\n if (isUnitTest()) collectLog('info', message)\n outputWhereAppropriate('info', consoleWarn, message)\n}\n"]}
@@ -0,0 +1,10 @@
1
+ import type { LazyCommandLoader } from '../../public/node/custom-oclif-loader.js';
2
+ import type { Config } from '@oclif/core';
3
+ /**
4
+ * Loads a command's schema without running its lifecycle or Oclif hooks.
5
+ *
6
+ * @param config - The loaded CLI configuration.
7
+ * @param argv - The CLI arguments, including the command name.
8
+ * @param lazyCommandLoader - The optional loader for bundled commands.
9
+ */
10
+ export declare function printCommandJsonSchema(config: Config, argv: string[], lazyCommandLoader?: LazyCommandLoader): Promise<void>;
@@ -0,0 +1,38 @@
1
+ import { AbortError } from '../../public/node/error.js';
2
+ import { commandEventOutputSchema } from '../../public/node/command-events.js';
3
+ import { jsonErrorOutputSchema } from '../../public/node/error/schema.js';
4
+ import { defineJsonOutputSchema } from '../../public/node/json-output-schema.js';
5
+ import { flushStdout, outputResult } from '../../public/node/output.js';
6
+ import { zod } from '../../public/node/schema.js';
7
+ import { normalizeArgv } from '@oclif/core/help';
8
+ /**
9
+ * Loads a command's schema without running its lifecycle or Oclif hooks.
10
+ *
11
+ * @param config - The loaded CLI configuration.
12
+ * @param argv - The CLI arguments, including the command name.
13
+ * @param lazyCommandLoader - The optional loader for bundled commands.
14
+ */
15
+ export async function printCommandJsonSchema(config, argv, lazyCommandLoader) {
16
+ const [id] = normalizeArgv(config, argv);
17
+ if (!id || id.startsWith('-'))
18
+ throw new AbortError('Specify a command to inspect its JSON output schema.');
19
+ const command = config.findCommand(id);
20
+ if (!command)
21
+ throw new AbortError(`Command "${id}" not found.`);
22
+ const commandClass = (await lazyCommandLoader?.(command.id)) ?? (await command.load());
23
+ const outputSchema = commandClass.jsonOutputSchema;
24
+ if (!outputSchema)
25
+ throw new AbortError('This command does not define a JSON output schema.');
26
+ const commandSchema = defineJsonOutputSchema({
27
+ name: 'CommandOutput',
28
+ schema: zod.union([outputSchema.schema, jsonErrorOutputSchema.schema, commandEventOutputSchema.schema]),
29
+ definitions: {
30
+ Result: outputSchema.schema,
31
+ Error: jsonErrorOutputSchema.schema,
32
+ Event: commandEventOutputSchema.schema,
33
+ },
34
+ });
35
+ outputResult(JSON.stringify(commandSchema.jsonSchema, null, 2));
36
+ await flushStdout();
37
+ }
38
+ //# sourceMappingURL=command-json-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-json-schema.js","sourceRoot":"","sources":["../../../src/private/node/command-json-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAC,MAAM,4BAA4B,CAAA;AACrD,OAAO,EAAC,wBAAwB,EAAC,MAAM,qCAAqC,CAAA;AAC5E,OAAO,EAAC,qBAAqB,EAAC,MAAM,mCAAmC,CAAA;AACvE,OAAO,EAAC,sBAAsB,EAAwB,MAAM,yCAAyC,CAAA;AACrG,OAAO,EAAC,WAAW,EAAE,YAAY,EAAC,MAAM,6BAA6B,CAAA;AACrE,OAAO,EAAC,GAAG,EAAC,MAAM,6BAA6B,CAAA;AAC/C,OAAO,EAAC,aAAa,EAAC,MAAM,kBAAkB,CAAA;AAI9C;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,MAAc,EACd,IAAc,EACd,iBAAqC;IAErC,MAAM,CAAC,EAAE,CAAC,GAAG,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;IACxC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,sDAAsD,CAAC,CAAA;IAE3G,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAA;IACtC,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,UAAU,CAAC,YAAY,EAAE,cAAc,CAAC,CAAA;IAEhE,MAAM,YAAY,GAAG,CAAC,MAAM,iBAAiB,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;IACtF,MAAM,YAAY,GAAI,YAA4E,CAAC,gBAAgB,CAAA;IACnH,IAAI,CAAC,YAAY;QAAE,MAAM,IAAI,UAAU,CAAC,oDAAoD,CAAC,CAAA;IAE7F,MAAM,aAAa,GAAG,sBAAsB,CAAC;QAC3C,IAAI,EAAE,eAAe;QACrB,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,MAAM,EAAE,qBAAqB,CAAC,MAAM,EAAE,wBAAwB,CAAC,MAAM,CAAC,CAAC;QACvG,WAAW,EAAE;YACX,MAAM,EAAE,YAAY,CAAC,MAAM;YAC3B,KAAK,EAAE,qBAAqB,CAAC,MAAM;YACnC,KAAK,EAAE,wBAAwB,CAAC,MAAM;SACvC;KACF,CAAC,CAAA;IACF,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;IAC/D,MAAM,WAAW,EAAE,CAAA;AACrB,CAAC","sourcesContent":["import {AbortError} from '../../public/node/error.js'\nimport {commandEventOutputSchema} from '../../public/node/command-events.js'\nimport {jsonErrorOutputSchema} from '../../public/node/error/schema.js'\nimport {defineJsonOutputSchema, type JsonOutputSchema} from '../../public/node/json-output-schema.js'\nimport {flushStdout, outputResult} from '../../public/node/output.js'\nimport {zod} from '../../public/node/schema.js'\nimport {normalizeArgv} from '@oclif/core/help'\nimport type {LazyCommandLoader} from '../../public/node/custom-oclif-loader.js'\nimport type {Config} from '@oclif/core'\n\n/**\n * Loads a command's schema without running its lifecycle or Oclif hooks.\n *\n * @param config - The loaded CLI configuration.\n * @param argv - The CLI arguments, including the command name.\n * @param lazyCommandLoader - The optional loader for bundled commands.\n */\nexport async function printCommandJsonSchema(\n config: Config,\n argv: string[],\n lazyCommandLoader?: LazyCommandLoader,\n): Promise<void> {\n const [id] = normalizeArgv(config, argv)\n if (!id || id.startsWith('-')) throw new AbortError('Specify a command to inspect its JSON output schema.')\n\n const command = config.findCommand(id)\n if (!command) throw new AbortError(`Command \"${id}\" not found.`)\n\n const commandClass = (await lazyCommandLoader?.(command.id)) ?? (await command.load())\n const outputSchema = (commandClass as typeof commandClass & {jsonOutputSchema?: JsonOutputSchema}).jsonOutputSchema\n if (!outputSchema) throw new AbortError('This command does not define a JSON output schema.')\n\n const commandSchema = defineJsonOutputSchema({\n name: 'CommandOutput',\n schema: zod.union([outputSchema.schema, jsonErrorOutputSchema.schema, commandEventOutputSchema.schema]),\n definitions: {\n Result: outputSchema.schema,\n Error: jsonErrorOutputSchema.schema,\n Event: commandEventOutputSchema.schema,\n },\n })\n outputResult(JSON.stringify(commandSchema.jsonSchema, null, 2))\n await flushStdout()\n}\n"]}
@@ -0,0 +1 @@
1
+ export declare function detectedAgentEnvironmentVariables(env?: NodeJS.ProcessEnv): Promise<NodeJS.ProcessEnv>;
@@ -0,0 +1,44 @@
1
+ import { outputDebug } from '../../../public/node/output.js';
2
+ import { determineAgent, KNOWN_AGENTS } from '@vercel/detect-agent';
3
+ const toolkitAgentNamesByDetectedName = new Map([
4
+ [KNOWN_AGENTS.CLAUDE, 'claude-code'],
5
+ [KNOWN_AGENTS.GEMINI, 'gemini-cli'],
6
+ ]);
7
+ const explicitAgentVariableNames = ['SHOPIFY_CLI_AGENT_INFO', 'SHOPIFY_CLI_AGENT_IDS'];
8
+ function hasExplicitAgentAttribution(env) {
9
+ return explicitAgentVariableNames.some((variableName) => (env[variableName] ?? '').trim() !== '');
10
+ }
11
+ function agentDetectionResult(state, extra = {}) {
12
+ return { ...extra, SHOPIFY_CLI_AGENT_DETECTION: state };
13
+ }
14
+ export async function detectedAgentEnvironmentVariables(env = process.env) {
15
+ // Emitting while a declaration exists would clobber the producer's whole packed value, not just the name.
16
+ if (hasExplicitAgentAttribution(env))
17
+ return agentDetectionResult('skipped');
18
+ try {
19
+ const detection = await determineAgent();
20
+ if (!detection.isAgent)
21
+ return agentDetectionResult('none');
22
+ const rawDetectedName = detection.agent.name;
23
+ const nameHasContentBeyondSeparators = /[^|\s]/.test(rawDetectedName);
24
+ // The name detection produced was real but unusable (nothing but separators/whitespace), which
25
+ // is different from no agent being detected at all, so it gets its own state.
26
+ if (!nameHasContentBeyondSeparators)
27
+ return agentDetectionResult('unusable_name');
28
+ // `|` separates tags, so a name containing one could otherwise fabricate tags we never detected.
29
+ const detectedName = rawDetectedName.replaceAll('|', '_').trim();
30
+ return agentDetectionResult('detected', {
31
+ SHOPIFY_CLI_AGENT_INFO: `n:${toolkitAgentNamesByDetectedName.get(detectedName) ?? detectedName}`,
32
+ });
33
+ // eslint-disable-next-line no-catch-all/no-catch-all
34
+ }
35
+ catch (error) {
36
+ let message = 'Unable to detect which AI agent is running the CLI';
37
+ if (error instanceof Error) {
38
+ message = message.concat(`: ${error.message}`);
39
+ }
40
+ outputDebug(message);
41
+ return agentDetectionResult('failed');
42
+ }
43
+ }
44
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../../../src/private/node/context/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,gCAAgC,CAAA;AAC1D,OAAO,EAAC,cAAc,EAAE,YAAY,EAAC,MAAM,sBAAsB,CAAA;AAEjE,MAAM,+BAA+B,GAAG,IAAI,GAAG,CAAiB;IAC9D,CAAC,YAAY,CAAC,MAAM,EAAE,aAAa,CAAC;IACpC,CAAC,YAAY,CAAC,MAAM,EAAE,YAAY,CAAC;CACpC,CAAC,CAAA;AAEF,MAAM,0BAA0B,GAAG,CAAC,wBAAwB,EAAE,uBAAuB,CAAC,CAAA;AAEtF,SAAS,2BAA2B,CAAC,GAAsB;IACzD,OAAO,0BAA0B,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;AACnG,CAAC;AAID,SAAS,oBAAoB,CAAC,KAA0B,EAAE,QAA2B,EAAE;IACrF,OAAO,EAAC,GAAG,KAAK,EAAE,2BAA2B,EAAE,KAAK,EAAC,CAAA;AACvD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iCAAiC,CACrD,MAAyB,OAAO,CAAC,GAAG;IAEpC,0GAA0G;IAC1G,IAAI,2BAA2B,CAAC,GAAG,CAAC;QAAE,OAAO,oBAAoB,CAAC,SAAS,CAAC,CAAA;IAE5E,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,cAAc,EAAE,CAAA;QACxC,IAAI,CAAC,SAAS,CAAC,OAAO;YAAE,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAA;QAE3D,MAAM,eAAe,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,CAAA;QAC5C,MAAM,8BAA8B,GAAG,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;QACrE,+FAA+F;QAC/F,8EAA8E;QAC9E,IAAI,CAAC,8BAA8B;YAAE,OAAO,oBAAoB,CAAC,eAAe,CAAC,CAAA;QAEjF,iGAAiG;QACjG,MAAM,YAAY,GAAG,eAAe,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAA;QAEhE,OAAO,oBAAoB,CAAC,UAAU,EAAE;YACtC,sBAAsB,EAAE,KAAK,+BAA+B,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,YAAY,EAAE;SACjG,CAAC,CAAA;QAEF,qDAAqD;IACvD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,OAAO,GAAG,oDAAoD,CAAA;QAClE,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,oBAAoB,CAAC,QAAQ,CAAC,CAAA;IACvC,CAAC;AACH,CAAC","sourcesContent":["import {outputDebug} from '../../../public/node/output.js'\nimport {determineAgent, KNOWN_AGENTS} from '@vercel/detect-agent'\n\nconst toolkitAgentNamesByDetectedName = new Map<string, string>([\n [KNOWN_AGENTS.CLAUDE, 'claude-code'],\n [KNOWN_AGENTS.GEMINI, 'gemini-cli'],\n])\n\nconst explicitAgentVariableNames = ['SHOPIFY_CLI_AGENT_INFO', 'SHOPIFY_CLI_AGENT_IDS']\n\nfunction hasExplicitAgentAttribution(env: NodeJS.ProcessEnv): boolean {\n return explicitAgentVariableNames.some((variableName) => (env[variableName] ?? '').trim() !== '')\n}\n\ntype AgentDetectionState = 'skipped' | 'detected' | 'none' | 'unusable_name' | 'failed'\n\nfunction agentDetectionResult(state: AgentDetectionState, extra: NodeJS.ProcessEnv = {}): NodeJS.ProcessEnv {\n return {...extra, SHOPIFY_CLI_AGENT_DETECTION: state}\n}\n\nexport async function detectedAgentEnvironmentVariables(\n env: NodeJS.ProcessEnv = process.env,\n): Promise<NodeJS.ProcessEnv> {\n // Emitting while a declaration exists would clobber the producer's whole packed value, not just the name.\n if (hasExplicitAgentAttribution(env)) return agentDetectionResult('skipped')\n\n try {\n const detection = await determineAgent()\n if (!detection.isAgent) return agentDetectionResult('none')\n\n const rawDetectedName = detection.agent.name\n const nameHasContentBeyondSeparators = /[^|\\s]/.test(rawDetectedName)\n // The name detection produced was real but unusable (nothing but separators/whitespace), which\n // is different from no agent being detected at all, so it gets its own state.\n if (!nameHasContentBeyondSeparators) return agentDetectionResult('unusable_name')\n\n // `|` separates tags, so a name containing one could otherwise fabricate tags we never detected.\n const detectedName = rawDetectedName.replaceAll('|', '_').trim()\n\n return agentDetectionResult('detected', {\n SHOPIFY_CLI_AGENT_INFO: `n:${toolkitAgentNamesByDetectedName.get(detectedName) ?? detectedName}`,\n })\n\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n let message = 'Unable to detect which AI agent is running the CLI'\n if (error instanceof Error) {\n message = message.concat(`: ${error.message}`)\n }\n outputDebug(message)\n return agentDetectionResult('failed')\n }\n}\n"]}
@@ -0,0 +1,23 @@
1
+ interface FatalErrorLike {
2
+ type?: number;
3
+ message?: unknown;
4
+ formattedMessage?: unknown;
5
+ tryMessage?: unknown;
6
+ nextSteps?: unknown;
7
+ customSections?: unknown;
8
+ stack?: unknown;
9
+ command?: unknown;
10
+ args?: unknown;
11
+ details?: unknown;
12
+ code?: unknown;
13
+ }
14
+ /**
15
+ * Writes the public JSON representation of a fatal error to stdout.
16
+ *
17
+ * The allow-list mirrors the meaningful content of the regular fatal-error renderer.
18
+ * Arbitrary error properties remain private and are never copied to stdout.
19
+ *
20
+ * @param error - Fatal error to serialize.
21
+ */
22
+ export declare function renderFatalErrorAsJson(error: FatalErrorLike): void;
23
+ export {};