@shopify/cli-kit 4.1.0 → 4.2.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 (63) hide show
  1. package/assets/graphiql/favicon.ico +0 -0
  2. package/assets/graphiql/style.css +58 -0
  3. package/dist/private/common/array.js +2 -1
  4. package/dist/private/common/array.js.map +1 -1
  5. package/dist/private/node/api/headers.js +6 -3
  6. package/dist/private/node/api/headers.js.map +1 -1
  7. package/dist/private/node/session/device-authorization.js +4 -16
  8. package/dist/private/node/session/device-authorization.js.map +1 -1
  9. package/dist/private/node/ui.js +4 -1
  10. package/dist/private/node/ui.js.map +1 -1
  11. package/dist/public/common/gid.d.ts +24 -0
  12. package/dist/public/common/gid.js +32 -0
  13. package/dist/public/common/gid.js.map +1 -0
  14. package/dist/public/common/url.d.ts +16 -0
  15. package/dist/public/common/url.js +30 -0
  16. package/dist/public/common/url.js.map +1 -1
  17. package/dist/public/common/version.d.ts +1 -1
  18. package/dist/public/common/version.js +1 -1
  19. package/dist/public/common/version.js.map +1 -1
  20. package/dist/public/node/analytics.js +3 -5
  21. package/dist/public/node/analytics.js.map +1 -1
  22. package/dist/public/node/cli.d.ts +13 -0
  23. package/dist/public/node/cli.js +12 -0
  24. package/dist/public/node/cli.js.map +1 -1
  25. package/dist/public/node/error-handler.js +1 -1
  26. package/dist/public/node/error-handler.js.map +1 -1
  27. package/dist/public/node/graphiql/server.d.ts +80 -0
  28. package/dist/public/node/graphiql/server.js +234 -0
  29. package/dist/public/node/graphiql/server.js.map +1 -0
  30. package/dist/public/node/graphiql/templates/graphiql.d.ts +12 -0
  31. package/dist/public/node/graphiql/templates/graphiql.js +314 -0
  32. package/dist/public/node/graphiql/templates/graphiql.js.map +1 -0
  33. package/dist/public/node/graphiql/templates/unauthorized.d.ts +5 -0
  34. package/dist/public/node/graphiql/templates/unauthorized.js +111 -0
  35. package/dist/public/node/graphiql/templates/unauthorized.js.map +1 -0
  36. package/dist/public/node/graphiql/utilities.d.ts +12 -0
  37. package/dist/public/node/graphiql/utilities.js +44 -0
  38. package/dist/public/node/graphiql/utilities.js.map +1 -0
  39. package/dist/public/node/graphql.d.ts +19 -0
  40. package/dist/public/node/graphql.js +41 -0
  41. package/dist/public/node/graphql.js.map +1 -0
  42. package/dist/public/node/hooks/postrun.js +12 -2
  43. package/dist/public/node/hooks/postrun.js.map +1 -1
  44. package/dist/public/node/http.js +27 -31
  45. package/dist/public/node/http.js.map +1 -1
  46. package/dist/public/node/metadata.d.ts +3 -0
  47. package/dist/public/node/metadata.js.map +1 -1
  48. package/dist/public/node/monorail.d.ts +2 -1
  49. package/dist/public/node/monorail.js +1 -1
  50. package/dist/public/node/monorail.js.map +1 -1
  51. package/dist/public/node/output.js +20 -11
  52. package/dist/public/node/output.js.map +1 -1
  53. package/dist/public/node/system.js +3 -0
  54. package/dist/public/node/system.js.map +1 -1
  55. package/dist/public/node/tcp.js +11 -3
  56. package/dist/public/node/tcp.js.map +1 -1
  57. package/dist/public/node/themes/api.js +76 -4
  58. package/dist/public/node/themes/api.js.map +1 -1
  59. package/dist/public/node/toml/toml-file.d.ts +3 -2
  60. package/dist/public/node/toml/toml-file.js +3 -2
  61. package/dist/public/node/toml/toml-file.js.map +1 -1
  62. package/dist/tsconfig.tsbuildinfo +1 -1
  63. package/package.json +34 -29
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graphql.js","sourceRoot":"","sources":["../../../src/public/node/graphql.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,EAAC,MAAM,SAAS,CAAA;AAEtD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,aAAsB;IACpE,IAAI,QAAQ,CAAA;IACZ,IAAI,CAAC;QACH,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,CAAA;QACvB,sGAAsG;IACxG,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;IAED,MAAM,UAAU,GAAG,QAAQ,CAAC,WAAW,CAAC,MAAM,CAC5C,CAAC,UAAU,EAAyC,EAAE,CAAC,UAAU,CAAC,IAAI,KAAK,qBAAqB,CACjG,CAAA;IAED,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IAEzC,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,KAAK,aAAa,CAAC,CAAA;QACtF,OAAO,MAAM,EAAE,SAAS,KAAK,UAAU,CAAA;IACzC,CAAC;IAED,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,UAAU,CAAC,CAAC,CAAE,CAAC,SAAS,KAAK,UAAU,CAAA;IAChD,CAAC;IAED,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,SAAS,KAAK,UAAU,CAAC,CAAA;AAC3E,CAAC","sourcesContent":["import {OperationDefinitionNode, parse} from 'graphql'\n\n/**\n * Returns true if the GraphQL document contains a mutation operation that\n * would actually be executed for the given (optional) operation name.\n *\n * - When `operationName` is provided, only the matching operation is checked.\n * - When `operationName` is omitted and the document has a single operation,\n * that operation is checked.\n * - When the document has multiple operations and no operation name is given,\n * any mutation in the document is treated as a mutation request (the GraphQL\n * server would reject the ambiguous request anyway).\n *\n * Returns false for queries, subscriptions, fragment-only documents, and any\n * input that fails to parse as GraphQL.\n *\n * @param query - The GraphQL document to inspect.\n * @param operationName - Optional name of the operation to check; when set, only that operation is considered.\n * @returns True if the relevant operation is a mutation; false otherwise.\n */\nexport function containsMutation(query: string, operationName?: string): boolean {\n let document\n try {\n document = parse(query)\n // eslint-disable-next-line no-catch-all/no-catch-all -- swallowing parse errors is the entire purpose\n } catch {\n return false\n }\n\n const operations = document.definitions.filter(\n (definition): definition is OperationDefinitionNode => definition.kind === 'OperationDefinition',\n )\n\n if (operations.length === 0) return false\n\n if (operationName) {\n const target = operations.find((operation) => operation.name?.value === operationName)\n return target?.operation === 'mutation'\n }\n\n if (operations.length === 1) {\n return operations[0]!.operation === 'mutation'\n }\n\n return operations.some((operation) => operation.operation === 'mutation')\n}\n"]}
@@ -50,8 +50,16 @@ export function waitForPostRunHookAndExit() {
50
50
  // This hook is called after each successful command run. More info: https://oclif.io/docs/hooks
51
51
  export const hook = async ({ config, Command }) => {
52
52
  await detectStopCommand(Command);
53
- const { reportAnalyticsEvent } = await import('../analytics.js');
54
- await reportAnalyticsEvent({ config, exitMode: 'ok' });
53
+ const metadata = await import('../metadata.js');
54
+ const { commandStartOptions } = metadata.getAllSensitiveMetadata();
55
+ if (commandStartOptions) {
56
+ await metadata.addSensitiveMetadata(() => ({
57
+ commandStartOptions: {
58
+ ...commandStartOptions,
59
+ endTime: new Date().getTime(),
60
+ },
61
+ }));
62
+ }
55
63
  const { postrun: deprecationsHook } = await import('./deprecations.js');
56
64
  deprecationsHook(Command);
57
65
  const { outputDebug } = await import('../output.js');
@@ -59,6 +67,8 @@ export const hook = async ({ config, Command }) => {
59
67
  outputDebug(`Completed command ${command}`);
60
68
  if (!command.includes('notifications') && !command.includes('upgrade'))
61
69
  await autoUpgradeIfNeeded();
70
+ const { reportAnalyticsEvent } = await import('../analytics.js');
71
+ await reportAnalyticsEvent({ config, exitMode: 'ok' });
62
72
  postRunHookCompleted = true;
63
73
  };
64
74
  /**
@@ -1 +1 @@
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"]}
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 metadata = await import('../metadata.js')\n const {commandStartOptions} = metadata.getAllSensitiveMetadata()\n if (commandStartOptions) {\n await metadata.addSensitiveMetadata(() => ({\n commandStartOptions: {\n ...commandStartOptions,\n endTime: new Date().getTime(),\n },\n }))\n }\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\n const {reportAnalyticsEvent} = await import('../analytics.js')\n await reportAnalyticsEvent({config, exitMode: 'ok'})\n\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"]}
@@ -9,6 +9,7 @@ import { simpleRequestWithDebugLog } from '../../private/node/api.js';
9
9
  import { DEFAULT_MAX_TIME_MS } from '../../private/node/sleep-with-backoff.js';
10
10
  import FormData from 'form-data';
11
11
  import nodeFetch from 'node-fetch';
12
+ import { pipeline } from 'stream/promises';
12
13
  export { FetchError, Request, Response } from 'node-fetch';
13
14
  /**
14
15
  * Create a new FormData object.
@@ -170,39 +171,34 @@ export async function shopifyFetch(url, init, preferredBehaviour) {
170
171
  export function downloadFile(url, to) {
171
172
  const sanitizedUrl = sanitizeURL(url);
172
173
  outputDebug(`Downloading ${sanitizedUrl} to ${to}`);
173
- return runWithTimer('cmd_all_timing_network_ms')(() => {
174
- return new Promise((resolve, reject) => {
175
- if (!fileExistsSync(dirname(to))) {
176
- mkdirSync(dirname(to));
177
- }
178
- const file = createFileWriteStream(to);
179
- // if we can't remove the file for some reason (seen on windows), that's ok -- it's in a temporary directory
180
- const tryToRemoveFile = () => {
181
- try {
174
+ return runWithTimer('cmd_all_timing_network_ms')(async () => {
175
+ if (!fileExistsSync(dirname(to))) {
176
+ mkdirSync(dirname(to));
177
+ }
178
+ // if we can't remove the file for some reason (seen on windows), that's ok -- it's in a temporary directory
179
+ const tryToRemoveFile = () => {
180
+ try {
181
+ if (fileExistsSync(to)) {
182
182
  unlinkFileSync(to);
183
- // eslint-disable-next-line no-catch-all/no-catch-all
184
183
  }
185
- catch (err) {
186
- outputDebug(outputContent `Failed to remove file ${outputToken.path(to)}: ${outputToken.raw(String(err))}`);
187
- }
188
- };
189
- file.on('finish', () => {
190
- file.close();
191
- resolve(to);
192
- });
193
- file.on('error', (err) => {
194
- tryToRemoveFile();
195
- reject(err);
196
- });
197
- nodeFetch(url, { redirect: 'follow' })
198
- .then((res) => {
199
- res.body?.pipe(file);
200
- })
201
- .catch((err) => {
202
- tryToRemoveFile();
203
- reject(err instanceof Error ? err : new Error(String(err)));
204
- });
205
- });
184
+ // eslint-disable-next-line no-catch-all/no-catch-all
185
+ }
186
+ catch (err) {
187
+ outputDebug(outputContent `Failed to remove file ${outputToken.path(to)}: ${outputToken.raw(String(err))}`);
188
+ }
189
+ };
190
+ try {
191
+ const res = await nodeFetch(url, { redirect: 'follow' });
192
+ if (!res.body) {
193
+ throw new Error(`No response body received when downloading ${sanitizedUrl}`);
194
+ }
195
+ await pipeline(res.body, createFileWriteStream(to));
196
+ return to;
197
+ }
198
+ catch (err) {
199
+ tryToRemoveFile();
200
+ throw err instanceof Error ? err : new Error(String(err));
201
+ }
206
202
  });
207
203
  }
208
204
  //# sourceMappingURL=http.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/public/node/http.ts"],"names":[],"mappings":"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","sourcesContent":["import {dirname} from './path.js'\nimport {createFileWriteStream, fileExistsSync, mkdirSync, unlinkFileSync} from './fs.js'\nimport {runWithTimer} from './metadata.js'\nimport {maxRequestTimeForNetworkCallsMs, skipNetworkLevelRetry} from './environment.js'\nimport {outputContent, outputDebug, outputToken} from './output.js'\nimport {sanitizeURL} from '../../private/node/api/urls.js'\nimport {httpsAgent, sanitizedHeadersOutput} from '../../private/node/api/headers.js'\nimport {NetworkRetryBehaviour, simpleRequestWithDebugLog} from '../../private/node/api.js'\nimport {DEFAULT_MAX_TIME_MS} from '../../private/node/sleep-with-backoff.js'\n\nimport FormData from 'form-data'\nimport nodeFetch, {RequestInfo, RequestInit, Response} from 'node-fetch'\n\nexport {FetchError, Request, Response} from 'node-fetch'\n\n/**\n * Create a new FormData object.\n *\n * @returns A FormData object.\n */\nexport function formData(): FormData {\n return new FormData()\n}\n\ntype AbortSignal = RequestInit['signal']\n\ntype PresetFetchBehaviour = 'default' | 'non-blocking' | 'slow-request'\n\ntype AutomaticCancellationBehaviour =\n | {\n useAbortSignal: true\n timeoutMs: number\n }\n | {\n useAbortSignal: false\n }\n | {\n useAbortSignal: AbortSignal | (() => AbortSignal)\n }\n\nexport type RequestBehaviour = NetworkRetryBehaviour & AutomaticCancellationBehaviour\n\nexport type RequestModeInput = PresetFetchBehaviour | RequestBehaviour\n\n/**\n * Specify the behaviour of a network request.\n *\n * - default: Requests are automatically retried, and are subject to automatic cancellation if they're taking too long.\n * This is generally desirable.\n * - non-blocking: Requests are not retried if they fail with a network error, and are automatically cancelled if\n * they're taking too long. This is good for throwaway requests, like polling or tracking.\n * - slow-request: Requests are not retried if they fail with a network error, and are not automatically cancelled.\n * This is good for slow requests that should be give the chance to complete, and are unlikely to be safe to retry.\n *\n * Some request behaviours may be de-activated by the environment, and this function takes care of that concern. You\n * can also provide a customised request behaviour.\n *\n * @param preset - The preset to use.\n * @param env - Process environment variables.\n * @returns A request behaviour object.\n */\nexport function requestMode(\n preset: RequestModeInput = 'default',\n env: NodeJS.ProcessEnv = process.env,\n): RequestBehaviour {\n const networkLevelRetryIsSupported = !skipNetworkLevelRetry(env)\n switch (preset) {\n case 'default':\n return {\n useNetworkLevelRetry: networkLevelRetryIsSupported,\n maxRetryTimeMs: DEFAULT_MAX_TIME_MS,\n useAbortSignal: true,\n timeoutMs: maxRequestTimeForNetworkCallsMs(env),\n }\n case 'non-blocking':\n return {\n useNetworkLevelRetry: false,\n useAbortSignal: true,\n timeoutMs: maxRequestTimeForNetworkCallsMs(env),\n }\n case 'slow-request':\n return {\n useNetworkLevelRetry: false,\n useAbortSignal: false,\n }\n }\n return {\n ...preset,\n useNetworkLevelRetry: networkLevelRetryIsSupported && preset.useNetworkLevelRetry,\n } as RequestBehaviour\n}\n\ninterface FetchOptions {\n url: RequestInfo\n behaviour: RequestBehaviour\n init?: RequestInit\n logRequest: boolean\n useHttpsAgent: boolean\n}\n\n/**\n * Create an AbortSignal for automatic request cancellation, from a request behaviour.\n *\n * @param behaviour - The request behaviour.\n * @returns An AbortSignal.\n */\nexport function abortSignalFromRequestBehaviour(behaviour: RequestBehaviour): AbortSignal {\n let signal: AbortSignal\n if (behaviour.useAbortSignal === true) {\n signal = AbortSignal.timeout(behaviour.timeoutMs)\n } else if (behaviour.useAbortSignal && typeof behaviour.useAbortSignal === 'function') {\n signal = behaviour.useAbortSignal()\n } else if (behaviour.useAbortSignal) {\n signal = behaviour.useAbortSignal\n }\n return signal\n}\n\nasync function innerFetch({url, behaviour, init, logRequest, useHttpsAgent}: FetchOptions): Promise<Response> {\n if (logRequest) {\n outputDebug(outputContent`Sending ${init?.method ?? 'GET'} request to URL ${sanitizeURL(url.toString())}\nWith request headers:\n${sanitizedHeadersOutput((init?.headers ?? {}) as Record<string, string>)}\n`)\n }\n\n let agent: RequestInit['agent']\n if (useHttpsAgent) {\n agent = await httpsAgent()\n }\n\n const request = async () => {\n // each time we make the request, we need to potentially reset the abort signal, as the request logic may make\n // the same request multiple times.\n let signal = abortSignalFromRequestBehaviour(behaviour)\n\n // it's possible to provide a signal through the request's init structure.\n if (init?.signal) {\n signal = init.signal\n }\n\n return nodeFetch(url, {...init, agent, signal})\n }\n\n return runWithTimer('cmd_all_timing_network_ms')(async () => {\n return simpleRequestWithDebugLog({\n url: url.toString(),\n request,\n ...behaviour,\n })\n })\n}\n\n/**\n * An interface that abstracts way node-fetch. When Node has built-in\n * support for \"fetch\" in the standard library, we can drop the node-fetch\n * dependency from here.\n * Note that we are exposing types from \"node-fetch\". The reason being is that\n * they are consistent with the Web API so if we drop node-fetch in the future\n * it won't require changes from the callers.\n *\n * The CLI's fetch function supports special behaviours, like automatic retries. These are disabled by default through\n * this function.\n *\n * @param url - This defines the resource that you wish to fetch.\n * @param init - An object containing any custom settings that you want to apply to the request.\n * @param preferredBehaviour - A request behaviour object that overrides the default behaviour.\n * @returns A promise that resolves with the response.\n */\nexport async function fetch(\n url: RequestInfo,\n init?: RequestInit,\n preferredBehaviour?: RequestModeInput,\n): Promise<Response> {\n const options = {\n url,\n init,\n logRequest: false,\n useHttpsAgent: false,\n // all special behaviours are disabled by default\n behaviour: preferredBehaviour ? requestMode(preferredBehaviour) : requestMode('non-blocking'),\n } as const\n\n return innerFetch(options)\n}\n\n/**\n * A fetch function to use with Shopify services. The function ensures the right\n * TLS configuragion is used based on the environment in which the service is running\n * (e.g. Local). NB: headers/auth are the responsibility of the caller.\n *\n * By default, the CLI's fetch function's special behaviours, like automatic retries, are enabled.\n *\n * @param url - This defines the resource that you wish to fetch.\n * @param init - An object containing any custom settings that you want to apply to the request.\n * @param preferredBehaviour - A request behaviour object that overrides the default behaviour.\n * @returns A promise that resolves with the response.\n */\nexport async function shopifyFetch(\n url: RequestInfo,\n init?: RequestInit,\n preferredBehaviour?: RequestModeInput,\n): Promise<Response> {\n const options = {\n url,\n init,\n logRequest: true,\n useHttpsAgent: true,\n // special behaviours enabled by default\n behaviour: preferredBehaviour ? requestMode(preferredBehaviour) : requestMode(),\n }\n\n return innerFetch(options)\n}\n\n/**\n * Download a file from a URL to a local path.\n *\n * @param url - The URL to download from.\n * @param to - The local path to download to.\n * @returns - A promise that resolves with the local path.\n */\nexport function downloadFile(url: string, to: string): Promise<string> {\n const sanitizedUrl = sanitizeURL(url)\n outputDebug(`Downloading ${sanitizedUrl} to ${to}`)\n\n return runWithTimer('cmd_all_timing_network_ms')(() => {\n return new Promise<string>((resolve, reject) => {\n if (!fileExistsSync(dirname(to))) {\n mkdirSync(dirname(to))\n }\n\n const file = createFileWriteStream(to)\n\n // if we can't remove the file for some reason (seen on windows), that's ok -- it's in a temporary directory\n const tryToRemoveFile = () => {\n try {\n unlinkFileSync(to)\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (err: unknown) {\n outputDebug(outputContent`Failed to remove file ${outputToken.path(to)}: ${outputToken.raw(String(err))}`)\n }\n }\n\n file.on('finish', () => {\n file.close()\n resolve(to)\n })\n\n file.on('error', (err) => {\n tryToRemoveFile()\n reject(err)\n })\n\n nodeFetch(url, {redirect: 'follow'})\n .then((res) => {\n res.body?.pipe(file)\n })\n .catch((err) => {\n tryToRemoveFile()\n reject(err instanceof Error ? err : new Error(String(err)))\n })\n })\n })\n}\n"]}
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/public/node/http.ts"],"names":[],"mappings":"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","sourcesContent":["import {dirname} from './path.js'\nimport {createFileWriteStream, fileExistsSync, mkdirSync, unlinkFileSync} from './fs.js'\nimport {runWithTimer} from './metadata.js'\nimport {maxRequestTimeForNetworkCallsMs, skipNetworkLevelRetry} from './environment.js'\nimport {outputContent, outputDebug, outputToken} from './output.js'\nimport {sanitizeURL} from '../../private/node/api/urls.js'\nimport {httpsAgent, sanitizedHeadersOutput} from '../../private/node/api/headers.js'\nimport {NetworkRetryBehaviour, simpleRequestWithDebugLog} from '../../private/node/api.js'\nimport {DEFAULT_MAX_TIME_MS} from '../../private/node/sleep-with-backoff.js'\n\nimport FormData from 'form-data'\nimport nodeFetch, {RequestInfo, RequestInit, Response} from 'node-fetch'\nimport {pipeline} from 'stream/promises'\n\nexport {FetchError, Request, Response} from 'node-fetch'\n\n/**\n * Create a new FormData object.\n *\n * @returns A FormData object.\n */\nexport function formData(): FormData {\n return new FormData()\n}\n\ntype AbortSignal = RequestInit['signal']\n\ntype PresetFetchBehaviour = 'default' | 'non-blocking' | 'slow-request'\n\ntype AutomaticCancellationBehaviour =\n | {\n useAbortSignal: true\n timeoutMs: number\n }\n | {\n useAbortSignal: false\n }\n | {\n useAbortSignal: AbortSignal | (() => AbortSignal)\n }\n\nexport type RequestBehaviour = NetworkRetryBehaviour & AutomaticCancellationBehaviour\n\nexport type RequestModeInput = PresetFetchBehaviour | RequestBehaviour\n\n/**\n * Specify the behaviour of a network request.\n *\n * - default: Requests are automatically retried, and are subject to automatic cancellation if they're taking too long.\n * This is generally desirable.\n * - non-blocking: Requests are not retried if they fail with a network error, and are automatically cancelled if\n * they're taking too long. This is good for throwaway requests, like polling or tracking.\n * - slow-request: Requests are not retried if they fail with a network error, and are not automatically cancelled.\n * This is good for slow requests that should be give the chance to complete, and are unlikely to be safe to retry.\n *\n * Some request behaviours may be de-activated by the environment, and this function takes care of that concern. You\n * can also provide a customised request behaviour.\n *\n * @param preset - The preset to use.\n * @param env - Process environment variables.\n * @returns A request behaviour object.\n */\nexport function requestMode(\n preset: RequestModeInput = 'default',\n env: NodeJS.ProcessEnv = process.env,\n): RequestBehaviour {\n const networkLevelRetryIsSupported = !skipNetworkLevelRetry(env)\n switch (preset) {\n case 'default':\n return {\n useNetworkLevelRetry: networkLevelRetryIsSupported,\n maxRetryTimeMs: DEFAULT_MAX_TIME_MS,\n useAbortSignal: true,\n timeoutMs: maxRequestTimeForNetworkCallsMs(env),\n }\n case 'non-blocking':\n return {\n useNetworkLevelRetry: false,\n useAbortSignal: true,\n timeoutMs: maxRequestTimeForNetworkCallsMs(env),\n }\n case 'slow-request':\n return {\n useNetworkLevelRetry: false,\n useAbortSignal: false,\n }\n }\n return {\n ...preset,\n useNetworkLevelRetry: networkLevelRetryIsSupported && preset.useNetworkLevelRetry,\n } as RequestBehaviour\n}\n\ninterface FetchOptions {\n url: RequestInfo\n behaviour: RequestBehaviour\n init?: RequestInit\n logRequest: boolean\n useHttpsAgent: boolean\n}\n\n/**\n * Create an AbortSignal for automatic request cancellation, from a request behaviour.\n *\n * @param behaviour - The request behaviour.\n * @returns An AbortSignal.\n */\nexport function abortSignalFromRequestBehaviour(behaviour: RequestBehaviour): AbortSignal {\n let signal: AbortSignal\n if (behaviour.useAbortSignal === true) {\n signal = AbortSignal.timeout(behaviour.timeoutMs)\n } else if (behaviour.useAbortSignal && typeof behaviour.useAbortSignal === 'function') {\n signal = behaviour.useAbortSignal()\n } else if (behaviour.useAbortSignal) {\n signal = behaviour.useAbortSignal\n }\n return signal\n}\n\nasync function innerFetch({url, behaviour, init, logRequest, useHttpsAgent}: FetchOptions): Promise<Response> {\n if (logRequest) {\n outputDebug(outputContent`Sending ${init?.method ?? 'GET'} request to URL ${sanitizeURL(url.toString())}\nWith request headers:\n${sanitizedHeadersOutput((init?.headers ?? {}) as Record<string, string>)}\n`)\n }\n\n let agent: RequestInit['agent']\n if (useHttpsAgent) {\n agent = await httpsAgent()\n }\n\n const request = async () => {\n // each time we make the request, we need to potentially reset the abort signal, as the request logic may make\n // the same request multiple times.\n let signal = abortSignalFromRequestBehaviour(behaviour)\n\n // it's possible to provide a signal through the request's init structure.\n if (init?.signal) {\n signal = init.signal\n }\n\n return nodeFetch(url, {...init, agent, signal})\n }\n\n return runWithTimer('cmd_all_timing_network_ms')(async () => {\n return simpleRequestWithDebugLog({\n url: url.toString(),\n request,\n ...behaviour,\n })\n })\n}\n\n/**\n * An interface that abstracts way node-fetch. When Node has built-in\n * support for \"fetch\" in the standard library, we can drop the node-fetch\n * dependency from here.\n * Note that we are exposing types from \"node-fetch\". The reason being is that\n * they are consistent with the Web API so if we drop node-fetch in the future\n * it won't require changes from the callers.\n *\n * The CLI's fetch function supports special behaviours, like automatic retries. These are disabled by default through\n * this function.\n *\n * @param url - This defines the resource that you wish to fetch.\n * @param init - An object containing any custom settings that you want to apply to the request.\n * @param preferredBehaviour - A request behaviour object that overrides the default behaviour.\n * @returns A promise that resolves with the response.\n */\nexport async function fetch(\n url: RequestInfo,\n init?: RequestInit,\n preferredBehaviour?: RequestModeInput,\n): Promise<Response> {\n const options = {\n url,\n init,\n logRequest: false,\n useHttpsAgent: false,\n // all special behaviours are disabled by default\n behaviour: preferredBehaviour ? requestMode(preferredBehaviour) : requestMode('non-blocking'),\n } as const\n\n return innerFetch(options)\n}\n\n/**\n * A fetch function to use with Shopify services. The function ensures the right\n * TLS configuragion is used based on the environment in which the service is running\n * (e.g. Local). NB: headers/auth are the responsibility of the caller.\n *\n * By default, the CLI's fetch function's special behaviours, like automatic retries, are enabled.\n *\n * @param url - This defines the resource that you wish to fetch.\n * @param init - An object containing any custom settings that you want to apply to the request.\n * @param preferredBehaviour - A request behaviour object that overrides the default behaviour.\n * @returns A promise that resolves with the response.\n */\nexport async function shopifyFetch(\n url: RequestInfo,\n init?: RequestInit,\n preferredBehaviour?: RequestModeInput,\n): Promise<Response> {\n const options = {\n url,\n init,\n logRequest: true,\n useHttpsAgent: true,\n // special behaviours enabled by default\n behaviour: preferredBehaviour ? requestMode(preferredBehaviour) : requestMode(),\n }\n\n return innerFetch(options)\n}\n\n/**\n * Download a file from a URL to a local path.\n *\n * @param url - The URL to download from.\n * @param to - The local path to download to.\n * @returns - A promise that resolves with the local path.\n */\nexport function downloadFile(url: string, to: string): Promise<string> {\n const sanitizedUrl = sanitizeURL(url)\n outputDebug(`Downloading ${sanitizedUrl} to ${to}`)\n\n return runWithTimer('cmd_all_timing_network_ms')(async () => {\n if (!fileExistsSync(dirname(to))) {\n mkdirSync(dirname(to))\n }\n\n // if we can't remove the file for some reason (seen on windows), that's ok -- it's in a temporary directory\n const tryToRemoveFile = () => {\n try {\n if (fileExistsSync(to)) {\n unlinkFileSync(to)\n }\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (err: unknown) {\n outputDebug(outputContent`Failed to remove file ${outputToken.path(to)}: ${outputToken.raw(String(err))}`)\n }\n }\n\n try {\n const res = await nodeFetch(url, {redirect: 'follow'})\n if (!res.body) {\n throw new Error(`No response body received when downloading ${sanitizedUrl}`)\n }\n await pipeline(res.body, createFileWriteStream(to))\n return to\n } catch (err) {\n tryToRemoveFile()\n throw err instanceof Error ? err : new Error(String(err))\n }\n })\n}\n"]}
@@ -38,6 +38,7 @@ type CmdFieldsFromMonorail = PickByPrefix<MonorailEventPublic, 'cmd_all_'> & Pic
38
38
  declare const coreData: RuntimeMetadataManager<CmdFieldsFromMonorail, {
39
39
  commandStartOptions: {
40
40
  startTime: number;
41
+ endTime?: number;
41
42
  startCommand: string;
42
43
  startTopic?: string;
43
44
  startArgs: string[];
@@ -58,6 +59,7 @@ declare const coreData: RuntimeMetadataManager<CmdFieldsFromMonorail, {
58
59
  export declare const getAllPublicMetadata: () => Partial<CmdFieldsFromMonorail>, getAllSensitiveMetadata: () => Partial<{
59
60
  commandStartOptions: {
60
61
  startTime: number;
62
+ endTime?: number;
61
63
  startCommand: string;
62
64
  startTopic?: string;
63
65
  startArgs: string[];
@@ -77,6 +79,7 @@ export declare const getAllPublicMetadata: () => Partial<CmdFieldsFromMonorail>,
77
79
  }, "store_", never>>, addPublicMetadata: (getData: ProvideMetadata<CmdFieldsFromMonorail>, onError?: MetadataErrorHandling) => Promise<void>, addSensitiveMetadata: (getData: ProvideMetadata<{
78
80
  commandStartOptions: {
79
81
  startTime: number;
82
+ endTime?: number;
80
83
  startCommand: string;
81
84
  startTopic?: string;
82
85
  startArgs: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../../src/public/node/metadata.ts"],"names":[],"mappings":"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","sourcesContent":["import {isUnitTest} from './context/local.js'\nimport {performance} from 'node:perf_hooks'\nimport type {PickByPrefix} from '../common/ts/pick-by-prefix.js'\nimport type {AnyJson} from '../../private/common/json.js'\nimport type {MonorailEventPublic, MonorailEventSensitive} from './monorail.js'\n\ntype ProvideMetadata<T> = () => Partial<T> | Promise<Partial<T>>\n\ntype MetadataErrorHandling =\n // Mute & report errors in production, throw them whilst testing\n | 'auto'\n // Errors are not reported to the user and do not stop execution, but they are reported to Bugsnag\n | 'mute-and-report'\n // Errors are not caught and will bubble out as normal\n | 'bubble'\n\n/**\n * Get the error handling strategy for metadata.\n *\n * @returns 'mute-and-report' in production, 'bubble' in tests.\n */\nfunction getMetadataErrorHandlingStrategy(): 'mute-and-report' | 'bubble' {\n if (isUnitTest()) {\n return 'bubble'\n }\n return 'mute-and-report'\n}\n\n/**\n * Any key in T that has a numeric value.\n */\ntype NumericKeyOf<T> = {\n [K in keyof T]: T[K] extends number ? (K extends string ? K : never) : never\n}[keyof T]\n\nexport interface RuntimeMetadataManager<TPublic extends AnyJson, TSensitive extends AnyJson> {\n /** Add some public metadata -- this should not contain any PII. */\n addPublicMetadata: (getData: ProvideMetadata<TPublic>, onError?: MetadataErrorHandling) => Promise<void>\n /**\n * Add some potentially sensitive metadata -- this may include PII, but unnecessary data should never be tracked\n * (this is a good fit for command args for instance).\n */\n addSensitiveMetadata: (getData: ProvideMetadata<TSensitive>, onError?: MetadataErrorHandling) => Promise<void>\n /** Get a snapshot of the tracked public data. */\n getAllPublicMetadata: () => Partial<TPublic>\n /** Get a snapshot of the tracked sensitive data. */\n getAllSensitiveMetadata: () => Partial<TSensitive>\n /** Run a function, monitoring how long it takes, and adding the elapsed time to a running total. */\n runWithTimer: (field: NumericKeyOf<TPublic>) => <T>(fn: () => Promise<T>) => Promise<T>\n}\n\nexport type PublicSchema<T> = T extends RuntimeMetadataManager<infer TPublic, infer _TSensitive> ? TPublic : never\nexport type SensitiveSchema<T> = T extends RuntimeMetadataManager<infer _TPublic, infer TSensitive> ? TSensitive : never\n\n/**\n * Creates a container for metadata collected at runtime.\n * The container provides async-safe functions for extracting the gathered metadata, and for setting it.\n *\n * @param defaultPublicMetadata - Optional, default data for the container.\n * @returns A container for the metadata.\n */\nexport function createRuntimeMetadataContainer<\n TPublic extends AnyJson,\n TSensitive extends AnyJson = Record<string, never>,\n>(defaultPublicMetadata: Partial<TPublic> = {}): RuntimeMetadataManager<TPublic, TSensitive> {\n const raw: {sensitive: Partial<TSensitive>; public: Partial<TPublic>} = {\n sensitive: {},\n public: {\n ...defaultPublicMetadata,\n },\n }\n const addPublic = (data: Partial<TPublic>) => {\n Object.assign(raw.public, data)\n }\n const addSensitive = (data: Partial<TSensitive>) => {\n Object.assign(raw.sensitive, data)\n }\n\n const addMetadata = async <T>(\n addFn: (data: Partial<T>) => void,\n getFn: ProvideMetadata<T>,\n onError: MetadataErrorHandling,\n ) => {\n const errorHandling = onError === 'auto' ? getMetadataErrorHandlingStrategy() : onError\n const getAndSet = async () => {\n const data = await getFn()\n addFn(data)\n }\n\n if (errorHandling === 'bubble') {\n await getAndSet()\n } else {\n try {\n await getAndSet()\n // eslint-disable-next-line no-catch-all/no-catch-all, @typescript-eslint/no-explicit-any\n } catch (error: any) {\n // This is very prone to becoming a circular dependency, so we import it dynamically\n const {sendErrorToBugsnag} = await import('./error-handler.js')\n await sendErrorToBugsnag(error, 'unexpected_error')\n }\n }\n }\n\n // See `runWithTimer` below.\n const durationStack: number[] = []\n\n return {\n getAllPublicMetadata: () => {\n return {...raw.public}\n },\n getAllSensitiveMetadata: () => {\n return {...raw.sensitive}\n },\n addPublicMetadata: async (getData: ProvideMetadata<TPublic>, onError: MetadataErrorHandling = 'auto') => {\n return addMetadata(addPublic, getData, onError)\n },\n addSensitiveMetadata: async (getData: ProvideMetadata<TSensitive>, onError: MetadataErrorHandling = 'auto') => {\n return addMetadata(addSensitive, getData, onError)\n },\n runWithTimer: (field: NumericKeyOf<TPublic>): (<T>(fn: () => Promise<T>) => Promise<T>) => {\n return async (fn) => {\n /**\n * For nested timers, we subtract the inner timer's duration from the outer timer's. We use a stack to track the\n * cumulative durations of nested timers. On starting a timer, we push a zero onto the stack to initialize the total\n * duration for subsequent nested timers. Before logging, we pop the stack to get the total nested timers' duration.\n * We subtract this from the current timer's actual duration to get its measurable duration. We then add the current\n * timer's actual duration to the stack's top, allowing any parent timer to deduct it from its own duration.\n */\n\n // Initialise the running total duration for all nested timers\n durationStack.push(0)\n\n // Do the work, and time it\n const start = performance.now()\n try {\n const result = await fn()\n return result\n } finally {\n let end = performance.now()\n // For very short durations, the end time can be before the start time(!) - we flatten this out to zero.\n end = Math.max(start, end)\n\n // The top of the stack is the total time for all nested timers\n const wallClockDuration = Math.max(end - start, 0)\n\n const childDurations = durationStack.pop()!\n const duration = Math.max(wallClockDuration - childDurations, 0)\n\n // If this is the topmost timer, the stack will be empty.\n if (durationStack.length > 0) {\n durationStack[durationStack.length - 1] = (durationStack[durationStack.length - 1] ?? 0) + wallClockDuration\n }\n\n // Log it -- we include it in the metadata, but also log via the standard performance API. The TS types for this library are not quite right, so we have to cast to `any` here.\n performance.measure(`${field}#measurable`, {\n start,\n duration,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any)\n performance.measure(`${field}#wall`, {\n start,\n end,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any)\n\n // There might not be a value set, yet\n let currentValue = (raw.public[field] || 0) as number\n currentValue += duration\n\n // TS is not quite smart enough to realise that raw.public[field] must be a numeric type\n raw.public[field] = currentValue as TPublic[NumericKeyOf<TPublic>]\n }\n }\n },\n }\n}\n\n// We want to track anything that ends up getting sent to monorail as `cmd_all_*`,\n// `cmd_app_*`, `cmd_theme_*`, `store_*`, and `env_auto_upgrade_*`\ntype CmdFieldsFromMonorail = PickByPrefix<MonorailEventPublic, 'cmd_all_'> &\n PickByPrefix<MonorailEventPublic, 'cmd_app_'> &\n PickByPrefix<MonorailEventPublic, 'cmd_create_app_'> &\n PickByPrefix<MonorailEventPublic, 'cmd_theme_'> &\n PickByPrefix<MonorailEventPublic, 'store_'> &\n PickByPrefix<MonorailEventPublic, 'env_auto_upgrade_'>\n\nconst coreData = createRuntimeMetadataContainer<\n CmdFieldsFromMonorail,\n {\n commandStartOptions: {\n startTime: number\n startCommand: string\n startTopic?: string\n startArgs: string[]\n }\n } & {environmentFlags: string} & PickByPrefix<MonorailEventSensitive, 'store_'>\n>({cmd_all_timing_network_ms: 0, cmd_all_timing_prompts_ms: 0})\n\nexport const {getAllPublicMetadata, getAllSensitiveMetadata, addPublicMetadata, addSensitiveMetadata, runWithTimer} =\n coreData\n\nexport type Public = PublicSchema<typeof coreData>\nexport type Sensitive = SensitiveSchema<typeof coreData>\n"]}
1
+ {"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../../src/public/node/metadata.ts"],"names":[],"mappings":"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","sourcesContent":["import {isUnitTest} from './context/local.js'\nimport {performance} from 'node:perf_hooks'\nimport type {PickByPrefix} from '../common/ts/pick-by-prefix.js'\nimport type {AnyJson} from '../../private/common/json.js'\nimport type {MonorailEventPublic, MonorailEventSensitive} from './monorail.js'\n\ntype ProvideMetadata<T> = () => Partial<T> | Promise<Partial<T>>\n\ntype MetadataErrorHandling =\n // Mute & report errors in production, throw them whilst testing\n | 'auto'\n // Errors are not reported to the user and do not stop execution, but they are reported to Bugsnag\n | 'mute-and-report'\n // Errors are not caught and will bubble out as normal\n | 'bubble'\n\n/**\n * Get the error handling strategy for metadata.\n *\n * @returns 'mute-and-report' in production, 'bubble' in tests.\n */\nfunction getMetadataErrorHandlingStrategy(): 'mute-and-report' | 'bubble' {\n if (isUnitTest()) {\n return 'bubble'\n }\n return 'mute-and-report'\n}\n\n/**\n * Any key in T that has a numeric value.\n */\ntype NumericKeyOf<T> = {\n [K in keyof T]: T[K] extends number ? (K extends string ? K : never) : never\n}[keyof T]\n\nexport interface RuntimeMetadataManager<TPublic extends AnyJson, TSensitive extends AnyJson> {\n /** Add some public metadata -- this should not contain any PII. */\n addPublicMetadata: (getData: ProvideMetadata<TPublic>, onError?: MetadataErrorHandling) => Promise<void>\n /**\n * Add some potentially sensitive metadata -- this may include PII, but unnecessary data should never be tracked\n * (this is a good fit for command args for instance).\n */\n addSensitiveMetadata: (getData: ProvideMetadata<TSensitive>, onError?: MetadataErrorHandling) => Promise<void>\n /** Get a snapshot of the tracked public data. */\n getAllPublicMetadata: () => Partial<TPublic>\n /** Get a snapshot of the tracked sensitive data. */\n getAllSensitiveMetadata: () => Partial<TSensitive>\n /** Run a function, monitoring how long it takes, and adding the elapsed time to a running total. */\n runWithTimer: (field: NumericKeyOf<TPublic>) => <T>(fn: () => Promise<T>) => Promise<T>\n}\n\nexport type PublicSchema<T> = T extends RuntimeMetadataManager<infer TPublic, infer _TSensitive> ? TPublic : never\nexport type SensitiveSchema<T> = T extends RuntimeMetadataManager<infer _TPublic, infer TSensitive> ? TSensitive : never\n\n/**\n * Creates a container for metadata collected at runtime.\n * The container provides async-safe functions for extracting the gathered metadata, and for setting it.\n *\n * @param defaultPublicMetadata - Optional, default data for the container.\n * @returns A container for the metadata.\n */\nexport function createRuntimeMetadataContainer<\n TPublic extends AnyJson,\n TSensitive extends AnyJson = Record<string, never>,\n>(defaultPublicMetadata: Partial<TPublic> = {}): RuntimeMetadataManager<TPublic, TSensitive> {\n const raw: {sensitive: Partial<TSensitive>; public: Partial<TPublic>} = {\n sensitive: {},\n public: {\n ...defaultPublicMetadata,\n },\n }\n const addPublic = (data: Partial<TPublic>) => {\n Object.assign(raw.public, data)\n }\n const addSensitive = (data: Partial<TSensitive>) => {\n Object.assign(raw.sensitive, data)\n }\n\n const addMetadata = async <T>(\n addFn: (data: Partial<T>) => void,\n getFn: ProvideMetadata<T>,\n onError: MetadataErrorHandling,\n ) => {\n const errorHandling = onError === 'auto' ? getMetadataErrorHandlingStrategy() : onError\n const getAndSet = async () => {\n const data = await getFn()\n addFn(data)\n }\n\n if (errorHandling === 'bubble') {\n await getAndSet()\n } else {\n try {\n await getAndSet()\n // eslint-disable-next-line no-catch-all/no-catch-all, @typescript-eslint/no-explicit-any\n } catch (error: any) {\n // This is very prone to becoming a circular dependency, so we import it dynamically\n const {sendErrorToBugsnag} = await import('./error-handler.js')\n await sendErrorToBugsnag(error, 'unexpected_error')\n }\n }\n }\n\n // See `runWithTimer` below.\n const durationStack: number[] = []\n\n return {\n getAllPublicMetadata: () => {\n return {...raw.public}\n },\n getAllSensitiveMetadata: () => {\n return {...raw.sensitive}\n },\n addPublicMetadata: async (getData: ProvideMetadata<TPublic>, onError: MetadataErrorHandling = 'auto') => {\n return addMetadata(addPublic, getData, onError)\n },\n addSensitiveMetadata: async (getData: ProvideMetadata<TSensitive>, onError: MetadataErrorHandling = 'auto') => {\n return addMetadata(addSensitive, getData, onError)\n },\n runWithTimer: (field: NumericKeyOf<TPublic>): (<T>(fn: () => Promise<T>) => Promise<T>) => {\n return async (fn) => {\n /**\n * For nested timers, we subtract the inner timer's duration from the outer timer's. We use a stack to track the\n * cumulative durations of nested timers. On starting a timer, we push a zero onto the stack to initialize the total\n * duration for subsequent nested timers. Before logging, we pop the stack to get the total nested timers' duration.\n * We subtract this from the current timer's actual duration to get its measurable duration. We then add the current\n * timer's actual duration to the stack's top, allowing any parent timer to deduct it from its own duration.\n */\n\n // Initialise the running total duration for all nested timers\n durationStack.push(0)\n\n // Do the work, and time it\n const start = performance.now()\n try {\n const result = await fn()\n return result\n } finally {\n let end = performance.now()\n // For very short durations, the end time can be before the start time(!) - we flatten this out to zero.\n end = Math.max(start, end)\n\n // The top of the stack is the total time for all nested timers\n const wallClockDuration = Math.max(end - start, 0)\n\n const childDurations = durationStack.pop()!\n const duration = Math.max(wallClockDuration - childDurations, 0)\n\n // If this is the topmost timer, the stack will be empty.\n if (durationStack.length > 0) {\n durationStack[durationStack.length - 1] = (durationStack[durationStack.length - 1] ?? 0) + wallClockDuration\n }\n\n // Log it -- we include it in the metadata, but also log via the standard performance API. The TS types for this library are not quite right, so we have to cast to `any` here.\n performance.measure(`${field}#measurable`, {\n start,\n duration,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any)\n performance.measure(`${field}#wall`, {\n start,\n end,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any)\n\n // There might not be a value set, yet\n let currentValue = (raw.public[field] || 0) as number\n currentValue += duration\n\n // TS is not quite smart enough to realise that raw.public[field] must be a numeric type\n raw.public[field] = currentValue as TPublic[NumericKeyOf<TPublic>]\n }\n }\n },\n }\n}\n\n// We want to track anything that ends up getting sent to monorail as `cmd_all_*`,\n// `cmd_app_*`, `cmd_theme_*`, `store_*`, and `env_auto_upgrade_*`\ntype CmdFieldsFromMonorail = PickByPrefix<MonorailEventPublic, 'cmd_all_'> &\n PickByPrefix<MonorailEventPublic, 'cmd_app_'> &\n PickByPrefix<MonorailEventPublic, 'cmd_create_app_'> &\n PickByPrefix<MonorailEventPublic, 'cmd_theme_'> &\n PickByPrefix<MonorailEventPublic, 'store_'> &\n PickByPrefix<MonorailEventPublic, 'env_auto_upgrade_'>\n\nconst coreData = createRuntimeMetadataContainer<\n CmdFieldsFromMonorail,\n {\n commandStartOptions: {\n startTime: number\n endTime?: number\n startCommand: string\n startTopic?: string\n startArgs: string[]\n }\n } & {environmentFlags: string} & PickByPrefix<MonorailEventSensitive, 'store_'>\n>({cmd_all_timing_network_ms: 0, cmd_all_timing_prompts_ms: 0})\n\nexport const {getAllPublicMetadata, getAllSensitiveMetadata, addPublicMetadata, addSensitiveMetadata, runWithTimer} =\n coreData\n\nexport type Public = PublicSchema<typeof coreData>\nexport type Sensitive = SensitiveSchema<typeof coreData>\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.24";
5
+ export declare const MONORAIL_COMMAND_TOPIC = "app_cli3_command/1.26";
6
6
  export interface Schemas {
7
7
  [MONORAIL_COMMAND_TOPIC]: {
8
8
  sensitive: {
@@ -33,6 +33,7 @@ export interface Schemas {
33
33
  is_employee: boolean;
34
34
  store_fqdn_hash?: Optional<string>;
35
35
  store_fqdn_validated?: Optional<boolean>;
36
+ store_domain?: Optional<string>;
36
37
  user_id: string;
37
38
  cmd_all_alias_used?: Optional<string>;
38
39
  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.24';
5
+ export const MONORAIL_COMMAND_TOPIC = 'app_cli3_command/1.26';
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;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"]}
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;AAoL7D,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.26'\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 store_domain?: 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"]}
@@ -187,6 +187,10 @@ function shouldOutput(logLevel) {
187
187
  }
188
188
  // eslint-disable-next-line import-x/no-mutable-exports
189
189
  export let collectedLogs = {};
190
+ /**
191
+ * Memoized value for the color check.
192
+ */
193
+ let memoizedShouldDisplayColors;
190
194
  /**
191
195
  * This is only used during UnitTesting.
192
196
  * If we are in a testing context, instead of printing the logs to the console,
@@ -196,12 +200,11 @@ export let collectedLogs = {};
196
200
  * @param content - The content of the log.
197
201
  */
198
202
  export function collectLog(key, content) {
199
- const output = collectedLogs.output ?? [];
200
- const data = collectedLogs[key] ?? [];
201
- data.push(stripAnsi(stringifyMessage(content) ?? ''));
202
- output.push(stripAnsi(stringifyMessage(content) ?? ''));
203
- collectedLogs[key] = data;
204
- collectedLogs.output = output;
203
+ const message = stripAnsi(stringifyMessage(content));
204
+ collectedLogs.output ?? (collectedLogs.output = []);
205
+ collectedLogs[key] ?? (collectedLogs[key] = []);
206
+ collectedLogs.output.push(message);
207
+ collectedLogs[key].push(message);
205
208
  }
206
209
  export const clearCollectedLogs = () => {
207
210
  collectedLogs = {};
@@ -341,6 +344,10 @@ export function outputWhereAppropriate(logLevel, logger, message) {
341
344
  * @returns The message without styles.
342
345
  */
343
346
  export function unstyled(message) {
347
+ // Optimization: skip regex execution for strings that don't have ANSI escape codes.
348
+ // In high-frequency paths like terminal layout calculations, this can save significant CPU time.
349
+ if (!message.includes('\u001b'))
350
+ return message;
344
351
  return stripAnsi(message);
345
352
  }
346
353
  /**
@@ -350,13 +357,15 @@ export function unstyled(message) {
350
357
  * @returns True if the console outputs should display colors, false otherwise.
351
358
  */
352
359
  export function shouldDisplayColors(_process = process) {
353
- const { env, stdout } = _process;
354
- if (Object.hasOwnProperty.call(env, 'FORCE_COLOR')) {
355
- return isTruthy(env.FORCE_COLOR);
360
+ if (_process === process && memoizedShouldDisplayColors !== undefined) {
361
+ return memoizedShouldDisplayColors;
356
362
  }
357
- else {
358
- return Boolean(stdout.isTTY);
363
+ const { env, stdout } = _process;
364
+ const result = Object.hasOwnProperty.call(env, 'FORCE_COLOR') ? isTruthy(env.FORCE_COLOR) : Boolean(stdout.isTTY);
365
+ if (_process === process) {
366
+ memoizedShouldDisplayColors = result;
359
367
  }
368
+ return result;
360
369
  }
361
370
  /**
362
371
  * Parse title and body to be a single formatted string.
@@ -1 +1 @@
1
- {"version":3,"file":"output.js","sourceRoot":"","sources":["../../../src/public/node/output.ts"],"names":[],"mappings":"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","sourcesContent":["import {isUnitTest, isVerbose} from './context/local.js'\nimport {PackageManager} from './node-package-manager.js'\nimport {currentProcessIsGlobal} from './is-global.js'\nimport {AbortSignal} from './abort.js'\nimport colors from './colors.js'\nimport {isTruthy} from './context/utilities.js'\nimport {TokenItem} from './ui.js'\nimport {\n ColorContentToken,\n CommandContentToken,\n ContentToken,\n ErrorContentToken,\n HeadingContentToken,\n ItalicContentToken,\n JsonContentToken,\n LinesDiffContentToken,\n LinkContentToken,\n PathContentToken,\n RawContentToken,\n SubHeadingContentToken,\n} from '../../private/node/content-tokens.js'\nimport {tokenItemToString} from '../../private/node/ui/components/TokenizedText.js'\nimport {consoleLog, consoleWarn, output} from '../../private/node/output.js'\nimport stripAnsi from 'strip-ansi'\nimport {Writable} from 'stream'\n\nimport type {Change} from 'diff'\n\nexport type Logger = Writable | ((message: string, logLevel?: LogLevel) => void)\n\nexport class TokenizedString {\n value: string\n constructor(value: string) {\n this.value = value\n }\n}\n\nexport type OutputMessage = string | TokenizedString\n\nexport const outputToken = {\n raw(value: string): RawContentToken {\n return new RawContentToken(value)\n },\n genericShellCommand(value: OutputMessage): CommandContentToken {\n return new CommandContentToken(value)\n },\n json(value: unknown): JsonContentToken {\n return new JsonContentToken(value)\n },\n path(value: OutputMessage): PathContentToken {\n return new PathContentToken(value)\n },\n link(value: OutputMessage, link?: string, fallback?: string | undefined): LinkContentToken {\n return new LinkContentToken(value, link, fallback)\n },\n heading(value: OutputMessage): HeadingContentToken {\n return new HeadingContentToken(value)\n },\n subheading(value: OutputMessage): SubHeadingContentToken {\n return new SubHeadingContentToken(value)\n },\n italic(value: OutputMessage): ItalicContentToken {\n return new ItalicContentToken(value)\n },\n errorText(value: OutputMessage): ErrorContentToken {\n return new ErrorContentToken(value)\n },\n cyan(value: OutputMessage): ColorContentToken {\n return new ColorContentToken(value, colors.cyan)\n },\n yellow(value: OutputMessage): ColorContentToken {\n return new ColorContentToken(value, colors.yellow)\n },\n magenta(value: OutputMessage): ColorContentToken {\n return new ColorContentToken(value, colors.magenta)\n },\n green(value: OutputMessage): ColorContentToken {\n return new ColorContentToken(value, colors.green)\n },\n gray(value: OutputMessage): ColorContentToken {\n return new ColorContentToken(value, colors.gray)\n },\n packagejsonScript(packageManager: PackageManager, scriptName: string, ...scriptArgs: string[]): CommandContentToken {\n return new CommandContentToken(formatPackageManagerCommand(packageManager, scriptName, ...scriptArgs))\n },\n successIcon(): ColorContentToken {\n return new ColorContentToken('✔', colors.green)\n },\n failIcon(): ErrorContentToken {\n return new ErrorContentToken('✖')\n },\n linesDiff(value: Change[]): LinesDiffContentToken {\n return new LinesDiffContentToken(value)\n },\n}\n\n/**\n * Given a command and its arguments, it formats it depending on the package manager.\n *\n * @param packageManager - The package manager to use (pnpm, npm, yarn).\n * @param scriptName - The name of the script to run.\n * @param scriptArgs - The arguments to pass to the script.\n * @returns The formatted command.\n */\nexport function formatPackageManagerCommand(\n packageManager: PackageManager,\n scriptName: string,\n ...scriptArgs: string[]\n): string {\n if (currentProcessIsGlobal()) {\n return [scriptName, ...scriptArgs].join(' ')\n }\n switch (packageManager) {\n case 'pnpm':\n case 'bun':\n case 'yarn': {\n const pieces = [packageManager, scriptName, ...scriptArgs]\n return pieces.join(' ')\n }\n case 'npm': {\n const pieces = ['npm', 'run', scriptName]\n if (scriptArgs.length > 0) {\n pieces.push('--')\n pieces.push(...scriptArgs)\n }\n return pieces.join(' ')\n }\n case 'homebrew':\n case 'unknown': {\n const pieces = [scriptName, ...scriptArgs]\n return pieces.join(' ')\n }\n }\n}\n\n/**\n * Creates a tokenized string from an array of strings and tokens.\n *\n * @param strings - The strings to join.\n * @param keys - Array of tokens or strings to join.\n * @returns The tokenized string.\n */\nexport function outputContent(\n strings: TemplateStringsArray,\n ...keys: (ContentToken<unknown> | string)[]\n): TokenizedString {\n let output = ``\n strings.forEach((string, i) => {\n output += string\n if (i >= keys.length) {\n return\n }\n\n const token = keys[i]!\n\n if (typeof token === 'string') {\n output += token\n } else if (token) {\n const enumTokenOutput = token.output()\n\n if (Array.isArray(enumTokenOutput)) {\n enumTokenOutput.forEach((line: string) => {\n output += line\n })\n } else {\n output += enumTokenOutput\n }\n }\n })\n return new TokenizedString(output)\n}\n\n/** Log levels. */\nexport type LogLevel = 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace' | 'silent'\n\n/**\n * It maps a level to a numeric value.\n *\n * @param level - The level for which we'll return its numeric value.\n * @returns The numeric value of the level.\n */\nfunction logLevelValue(level: LogLevel): number {\n switch (level) {\n case 'trace':\n return 10\n case 'debug':\n return 20\n case 'info':\n return 30\n case 'warn':\n return 40\n case 'error':\n return 50\n case 'fatal':\n return 60\n case 'silent':\n return 70\n }\n}\n\n/**\n * It returns the current log level (debug or info).\n *\n * @returns The log level set by the user.\n */\nfunction currentLogLevel(): LogLevel {\n if (isVerbose()) {\n return 'debug'\n } else {\n return 'info'\n }\n}\n\n/**\n * It checks if the message should be outputted or not.\n *\n * @param logLevel - The desired log level for the message.\n * @returns True if the message should be outputted, false otherwise.\n */\nfunction shouldOutput(logLevel: LogLevel): boolean {\n if (isUnitTest()) {\n return false\n }\n const currentLogLevelValue = logLevelValue(currentLogLevel())\n const messageLogLevelValue = logLevelValue(logLevel)\n return messageLogLevelValue >= currentLogLevelValue\n}\n\n// eslint-disable-next-line import-x/no-mutable-exports\nexport let collectedLogs: Record<string, string[]> = {}\n\n/**\n * This is only used during UnitTesting.\n * If we are in a testing context, instead of printing the logs to the console,\n * we will store them in a variable that can be accessed from the tests.\n *\n * @param key - The key of the log.\n * @param content - The content of the log.\n */\nexport function collectLog(key: string, content: OutputMessage): void {\n const output = collectedLogs.output ?? []\n const data = collectedLogs[key] ?? []\n data.push(stripAnsi(stringifyMessage(content) ?? ''))\n output.push(stripAnsi(stringifyMessage(content) ?? ''))\n collectedLogs[key] = data\n collectedLogs.output = output\n}\n\nexport const clearCollectedLogs = (): void => {\n collectedLogs = {}\n}\n\n/**\n * Outputs command result information to the user.\n * Result messages don't get additional formatting.\n * The messages are logged at info level to stdout.\n *\n * @param content - The content to be output to the user.\n */\nexport function outputResult(content: OutputMessage): void {\n output(content, 'info', consoleLog)\n}\n\n/**\n * Logs information at the info level.\n * Info messages don't get additional formatting.\n * Note: By default, info messages are sent through the standard error.\n *\n * @param content - The content to be output to the user.\n * @param logger - The logging function to use to output to the user.\n */\nexport function outputInfo(content: OutputMessage, logger: Logger = consoleWarn): void {\n const message = stringifyMessage(content)\n if (isUnitTest()) collectLog('info', content)\n outputWhereAppropriate('info', logger, message)\n}\n\n/**\n * Outputs a success message to the user.\n * Success messages receive a special formatting to make them stand out in the console.\n * Note: Success messages are sent through the standard error.\n *\n * @param content - The content to be output to the user.\n * @param logger - The logging function to use to output to the user.\n */\nexport function outputSuccess(content: OutputMessage, logger: Logger = consoleWarn): void {\n const message = colors.bold(`✅ Success! ${stringifyMessage(content)}.`)\n if (isUnitTest()) collectLog('success', content)\n outputWhereAppropriate('info', logger, message)\n}\n\n/**\n * Outputs a completed message to the user.\n * Completed message receive a special formatting to make them stand out in the console.\n * Note: Completed messages are sent through the standard error.\n *\n * @param content - The content to be output to the user.\n * @param logger - The logging function to use to output to the user.\n */\nexport function outputCompleted(content: OutputMessage, logger: Logger = consoleWarn): void {\n const message = `${colors.green('✔')} ${stringifyMessage(content)}`\n if (isUnitTest()) collectLog('completed', content)\n outputWhereAppropriate('info', logger, message)\n}\n\n/**\n * Logs a message at the debug level. By default these output is hidden unless the user calls the CLI with --verbose.\n * Debug messages don't get additional formatting.\n * Note: By default, debug messages are sent through the standard error.\n *\n * @param content - The content to be output to the user.\n * @param logger - The logging function to use to output to the user.\n */\nexport function outputDebug(content: OutputMessage, logger: Logger = consoleWarn): void {\n if (isUnitTest()) collectLog('debug', content)\n if (!shouldOutput('debug')) return\n\n const message = colors.gray(stringifyMessage(content))\n outputWhereAppropriate('debug', logger, `${new Date().toISOString()}: ${message}`)\n}\n\n/**\n * Logs a message at the warning level.\n * Warning messages receive a special formatting to make them stand out in the console.\n * Note: By default, warning messages are sent through the standard error.\n *\n * @param content - The content to be output to the user.\n * @param logger - The logging function to use to output to the user.\n */\nexport function outputWarn(content: OutputMessage, logger: Logger = consoleWarn): void {\n if (isUnitTest()) collectLog('warn', content)\n const message = colors.yellow(stringifyMessage(content))\n outputWhereAppropriate('warn', logger, message)\n}\n\n/**\n * Prints a new line in the terminal.\n */\nexport function outputNewline(): void {\n consoleWarn('')\n}\n\n/**\n * Converts a Message to string.\n *\n * @param message - The message to convert to string.\n * @returns The string representation of the message.\n */\nexport function stringifyMessage(message: OutputMessage): string {\n if (message instanceof TokenizedString) {\n return message.value\n } else {\n return message\n }\n}\n\n/**\n * Convert a TokenItem to string.\n *\n * @param item - The item to convert to string.\n * @returns The string representation of the item.\n */\nexport function itemToString(item: TokenItem): string {\n return tokenItemToString(item)\n}\n\nexport interface OutputProcess {\n /**\n * The prefix to include in the logs\n * [vite] Output coming from Vite.\n */\n prefix: string\n /**\n * A callback to invoke the process. Stdout and stderr should be used\n * to send standard output and error data that gets formatted with the\n * right prefix.\n */\n action: (stdout: Writable, stderr: Writable, signal: AbortSignal) => Promise<void>\n}\n\n/**\n * Writes a message to the appropiated logger.\n *\n * @param logLevel - The log level to use to determine if the message should be output.\n * @param logger - The logger to use to output the message.\n * @param message - The message to output.\n */\nexport function outputWhereAppropriate(logLevel: LogLevel, logger: Logger, message: string): void {\n if (shouldOutput(logLevel)) {\n if (logger instanceof Writable) {\n logger.write(message)\n } else {\n logger(message, logLevel)\n }\n }\n}\n\n/**\n * Returns a message without styles (colors or any ANSI escape codes).\n *\n * @param message - The message to remove styles from.\n * @returns The message without styles.\n */\nexport function unstyled(message: string): string {\n return stripAnsi(message)\n}\n\n/**\n * Checks if the console outputs should display colors or not.\n *\n * @param _process - Optional, the process-like object to use to check if the console should display colors. Defaults to the global process.\n * @returns True if the console outputs should display colors, false otherwise.\n */\nexport function shouldDisplayColors(_process = process): boolean {\n const {env, stdout} = _process\n if (Object.hasOwnProperty.call(env, 'FORCE_COLOR')) {\n return isTruthy(env.FORCE_COLOR)\n } else {\n return Boolean(stdout.isTTY)\n }\n}\n\n/**\n * Parse title and body to be a single formatted string.\n *\n * @param title - The title of the message. Will be formatted as a heading.\n * @param body - The body of the message. Will respect the original formatting.\n * @returns The formatted message.\n */\nexport function formatSection(title: string, body: string): string {\n const formattedTitle = `${title.toUpperCase()}${' '.repeat(35 - title.length)}`\n return outputContent`${outputToken.heading(formattedTitle)}\\n${body}`.value\n}\n"]}
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../../../src/public/node/output.ts"],"names":[],"mappings":"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","sourcesContent":["import {isUnitTest, isVerbose} from './context/local.js'\nimport {PackageManager} from './node-package-manager.js'\nimport {currentProcessIsGlobal} from './is-global.js'\nimport {AbortSignal} from './abort.js'\nimport colors from './colors.js'\nimport {isTruthy} from './context/utilities.js'\nimport {TokenItem} from './ui.js'\nimport {\n ColorContentToken,\n CommandContentToken,\n ContentToken,\n ErrorContentToken,\n HeadingContentToken,\n ItalicContentToken,\n JsonContentToken,\n LinesDiffContentToken,\n LinkContentToken,\n PathContentToken,\n RawContentToken,\n SubHeadingContentToken,\n} from '../../private/node/content-tokens.js'\nimport {tokenItemToString} from '../../private/node/ui/components/TokenizedText.js'\nimport {consoleLog, consoleWarn, output} from '../../private/node/output.js'\nimport stripAnsi from 'strip-ansi'\nimport {Writable} from 'stream'\n\nimport type {Change} from 'diff'\n\nexport type Logger = Writable | ((message: string, logLevel?: LogLevel) => void)\n\nexport class TokenizedString {\n value: string\n constructor(value: string) {\n this.value = value\n }\n}\n\nexport type OutputMessage = string | TokenizedString\n\nexport const outputToken = {\n raw(value: string): RawContentToken {\n return new RawContentToken(value)\n },\n genericShellCommand(value: OutputMessage): CommandContentToken {\n return new CommandContentToken(value)\n },\n json(value: unknown): JsonContentToken {\n return new JsonContentToken(value)\n },\n path(value: OutputMessage): PathContentToken {\n return new PathContentToken(value)\n },\n link(value: OutputMessage, link?: string, fallback?: string | undefined): LinkContentToken {\n return new LinkContentToken(value, link, fallback)\n },\n heading(value: OutputMessage): HeadingContentToken {\n return new HeadingContentToken(value)\n },\n subheading(value: OutputMessage): SubHeadingContentToken {\n return new SubHeadingContentToken(value)\n },\n italic(value: OutputMessage): ItalicContentToken {\n return new ItalicContentToken(value)\n },\n errorText(value: OutputMessage): ErrorContentToken {\n return new ErrorContentToken(value)\n },\n cyan(value: OutputMessage): ColorContentToken {\n return new ColorContentToken(value, colors.cyan)\n },\n yellow(value: OutputMessage): ColorContentToken {\n return new ColorContentToken(value, colors.yellow)\n },\n magenta(value: OutputMessage): ColorContentToken {\n return new ColorContentToken(value, colors.magenta)\n },\n green(value: OutputMessage): ColorContentToken {\n return new ColorContentToken(value, colors.green)\n },\n gray(value: OutputMessage): ColorContentToken {\n return new ColorContentToken(value, colors.gray)\n },\n packagejsonScript(packageManager: PackageManager, scriptName: string, ...scriptArgs: string[]): CommandContentToken {\n return new CommandContentToken(formatPackageManagerCommand(packageManager, scriptName, ...scriptArgs))\n },\n successIcon(): ColorContentToken {\n return new ColorContentToken('✔', colors.green)\n },\n failIcon(): ErrorContentToken {\n return new ErrorContentToken('✖')\n },\n linesDiff(value: Change[]): LinesDiffContentToken {\n return new LinesDiffContentToken(value)\n },\n}\n\n/**\n * Given a command and its arguments, it formats it depending on the package manager.\n *\n * @param packageManager - The package manager to use (pnpm, npm, yarn).\n * @param scriptName - The name of the script to run.\n * @param scriptArgs - The arguments to pass to the script.\n * @returns The formatted command.\n */\nexport function formatPackageManagerCommand(\n packageManager: PackageManager,\n scriptName: string,\n ...scriptArgs: string[]\n): string {\n if (currentProcessIsGlobal()) {\n return [scriptName, ...scriptArgs].join(' ')\n }\n switch (packageManager) {\n case 'pnpm':\n case 'bun':\n case 'yarn': {\n const pieces = [packageManager, scriptName, ...scriptArgs]\n return pieces.join(' ')\n }\n case 'npm': {\n const pieces = ['npm', 'run', scriptName]\n if (scriptArgs.length > 0) {\n pieces.push('--')\n pieces.push(...scriptArgs)\n }\n return pieces.join(' ')\n }\n case 'homebrew':\n case 'unknown': {\n const pieces = [scriptName, ...scriptArgs]\n return pieces.join(' ')\n }\n }\n}\n\n/**\n * Creates a tokenized string from an array of strings and tokens.\n *\n * @param strings - The strings to join.\n * @param keys - Array of tokens or strings to join.\n * @returns The tokenized string.\n */\nexport function outputContent(\n strings: TemplateStringsArray,\n ...keys: (ContentToken<unknown> | string)[]\n): TokenizedString {\n let output = ``\n strings.forEach((string, i) => {\n output += string\n if (i >= keys.length) {\n return\n }\n\n const token = keys[i]!\n\n if (typeof token === 'string') {\n output += token\n } else if (token) {\n const enumTokenOutput = token.output()\n\n if (Array.isArray(enumTokenOutput)) {\n enumTokenOutput.forEach((line: string) => {\n output += line\n })\n } else {\n output += enumTokenOutput\n }\n }\n })\n return new TokenizedString(output)\n}\n\n/** Log levels. */\nexport type LogLevel = 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace' | 'silent'\n\n/**\n * It maps a level to a numeric value.\n *\n * @param level - The level for which we'll return its numeric value.\n * @returns The numeric value of the level.\n */\nfunction logLevelValue(level: LogLevel): number {\n switch (level) {\n case 'trace':\n return 10\n case 'debug':\n return 20\n case 'info':\n return 30\n case 'warn':\n return 40\n case 'error':\n return 50\n case 'fatal':\n return 60\n case 'silent':\n return 70\n }\n}\n\n/**\n * It returns the current log level (debug or info).\n *\n * @returns The log level set by the user.\n */\nfunction currentLogLevel(): LogLevel {\n if (isVerbose()) {\n return 'debug'\n } else {\n return 'info'\n }\n}\n\n/**\n * It checks if the message should be outputted or not.\n *\n * @param logLevel - The desired log level for the message.\n * @returns True if the message should be outputted, false otherwise.\n */\nfunction shouldOutput(logLevel: LogLevel): boolean {\n if (isUnitTest()) {\n return false\n }\n const currentLogLevelValue = logLevelValue(currentLogLevel())\n const messageLogLevelValue = logLevelValue(logLevel)\n return messageLogLevelValue >= currentLogLevelValue\n}\n\n// eslint-disable-next-line import-x/no-mutable-exports\nexport let collectedLogs: Record<string, string[]> = {}\n\n/**\n * Memoized value for the color check.\n */\nlet memoizedShouldDisplayColors: boolean | undefined\n\n/**\n * This is only used during UnitTesting.\n * If we are in a testing context, instead of printing the logs to the console,\n * we will store them in a variable that can be accessed from the tests.\n *\n * @param key - The key of the log.\n * @param content - The content of the log.\n */\nexport function collectLog(key: string, content: OutputMessage): void {\n const message = stripAnsi(stringifyMessage(content))\n collectedLogs.output ??= []\n collectedLogs[key] ??= []\n collectedLogs.output.push(message)\n collectedLogs[key].push(message)\n}\n\nexport const clearCollectedLogs = (): void => {\n collectedLogs = {}\n}\n\n/**\n * Outputs command result information to the user.\n * Result messages don't get additional formatting.\n * The messages are logged at info level to stdout.\n *\n * @param content - The content to be output to the user.\n */\nexport function outputResult(content: OutputMessage): void {\n output(content, 'info', consoleLog)\n}\n\n/**\n * Logs information at the info level.\n * Info messages don't get additional formatting.\n * Note: By default, info messages are sent through the standard error.\n *\n * @param content - The content to be output to the user.\n * @param logger - The logging function to use to output to the user.\n */\nexport function outputInfo(content: OutputMessage, logger: Logger = consoleWarn): void {\n const message = stringifyMessage(content)\n if (isUnitTest()) collectLog('info', content)\n outputWhereAppropriate('info', logger, message)\n}\n\n/**\n * Outputs a success message to the user.\n * Success messages receive a special formatting to make them stand out in the console.\n * Note: Success messages are sent through the standard error.\n *\n * @param content - The content to be output to the user.\n * @param logger - The logging function to use to output to the user.\n */\nexport function outputSuccess(content: OutputMessage, logger: Logger = consoleWarn): void {\n const message = colors.bold(`✅ Success! ${stringifyMessage(content)}.`)\n if (isUnitTest()) collectLog('success', content)\n outputWhereAppropriate('info', logger, message)\n}\n\n/**\n * Outputs a completed message to the user.\n * Completed message receive a special formatting to make them stand out in the console.\n * Note: Completed messages are sent through the standard error.\n *\n * @param content - The content to be output to the user.\n * @param logger - The logging function to use to output to the user.\n */\nexport function outputCompleted(content: OutputMessage, logger: Logger = consoleWarn): void {\n const message = `${colors.green('✔')} ${stringifyMessage(content)}`\n if (isUnitTest()) collectLog('completed', content)\n outputWhereAppropriate('info', logger, message)\n}\n\n/**\n * Logs a message at the debug level. By default these output is hidden unless the user calls the CLI with --verbose.\n * Debug messages don't get additional formatting.\n * Note: By default, debug messages are sent through the standard error.\n *\n * @param content - The content to be output to the user.\n * @param logger - The logging function to use to output to the user.\n */\nexport function outputDebug(content: OutputMessage, logger: Logger = consoleWarn): void {\n if (isUnitTest()) collectLog('debug', content)\n if (!shouldOutput('debug')) return\n\n const message = colors.gray(stringifyMessage(content))\n outputWhereAppropriate('debug', logger, `${new Date().toISOString()}: ${message}`)\n}\n\n/**\n * Logs a message at the warning level.\n * Warning messages receive a special formatting to make them stand out in the console.\n * Note: By default, warning messages are sent through the standard error.\n *\n * @param content - The content to be output to the user.\n * @param logger - The logging function to use to output to the user.\n */\nexport function outputWarn(content: OutputMessage, logger: Logger = consoleWarn): void {\n if (isUnitTest()) collectLog('warn', content)\n const message = colors.yellow(stringifyMessage(content))\n outputWhereAppropriate('warn', logger, message)\n}\n\n/**\n * Prints a new line in the terminal.\n */\nexport function outputNewline(): void {\n consoleWarn('')\n}\n\n/**\n * Converts a Message to string.\n *\n * @param message - The message to convert to string.\n * @returns The string representation of the message.\n */\nexport function stringifyMessage(message: OutputMessage): string {\n if (message instanceof TokenizedString) {\n return message.value\n } else {\n return message\n }\n}\n\n/**\n * Convert a TokenItem to string.\n *\n * @param item - The item to convert to string.\n * @returns The string representation of the item.\n */\nexport function itemToString(item: TokenItem): string {\n return tokenItemToString(item)\n}\n\nexport interface OutputProcess {\n /**\n * The prefix to include in the logs\n * [vite] Output coming from Vite.\n */\n prefix: string\n /**\n * A callback to invoke the process. Stdout and stderr should be used\n * to send standard output and error data that gets formatted with the\n * right prefix.\n */\n action: (stdout: Writable, stderr: Writable, signal: AbortSignal) => Promise<void>\n}\n\n/**\n * Writes a message to the appropiated logger.\n *\n * @param logLevel - The log level to use to determine if the message should be output.\n * @param logger - The logger to use to output the message.\n * @param message - The message to output.\n */\nexport function outputWhereAppropriate(logLevel: LogLevel, logger: Logger, message: string): void {\n if (shouldOutput(logLevel)) {\n if (logger instanceof Writable) {\n logger.write(message)\n } else {\n logger(message, logLevel)\n }\n }\n}\n\n/**\n * Returns a message without styles (colors or any ANSI escape codes).\n *\n * @param message - The message to remove styles from.\n * @returns The message without styles.\n */\nexport function unstyled(message: string): string {\n // Optimization: skip regex execution for strings that don't have ANSI escape codes.\n // In high-frequency paths like terminal layout calculations, this can save significant CPU time.\n if (!message.includes('\\u001b')) return message\n\n return stripAnsi(message)\n}\n\n/**\n * Checks if the console outputs should display colors or not.\n *\n * @param _process - Optional, the process-like object to use to check if the console should display colors. Defaults to the global process.\n * @returns True if the console outputs should display colors, false otherwise.\n */\nexport function shouldDisplayColors(_process = process): boolean {\n if (_process === process && memoizedShouldDisplayColors !== undefined) {\n return memoizedShouldDisplayColors\n }\n\n const {env, stdout} = _process\n const result = Object.hasOwnProperty.call(env, 'FORCE_COLOR') ? isTruthy(env.FORCE_COLOR) : Boolean(stdout.isTTY)\n\n if (_process === process) {\n memoizedShouldDisplayColors = result\n }\n\n return result\n}\n\n/**\n * Parse title and body to be a single formatted string.\n *\n * @param title - The title of the message. Will be formatted as a heading.\n * @param body - The body of the message. Will respect the original formatting.\n * @returns The formatted message.\n */\nexport function formatSection(title: string, body: string): string {\n const formattedTitle = `${title.toUpperCase()}${' '.repeat(35 - title.length)}`\n return outputContent`${outputToken.heading(formattedTitle)}\\n${body}`.value\n}\n"]}