@shopify/cli-kit 3.70.0 → 3.71.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/dist/cli/api/graphql/admin/generated/theme_files_upsert.d.ts +21 -0
  2. package/dist/cli/api/graphql/admin/generated/theme_files_upsert.js +82 -0
  3. package/dist/cli/api/graphql/admin/generated/theme_files_upsert.js.map +1 -0
  4. package/dist/private/node/api.d.ts +1 -1
  5. package/dist/private/node/api.js +30 -2
  6. package/dist/private/node/api.js.map +1 -1
  7. package/dist/private/node/constants.d.ts +2 -0
  8. package/dist/private/node/constants.js +2 -0
  9. package/dist/private/node/constants.js.map +1 -1
  10. package/dist/private/node/session/exchange.js +2 -2
  11. package/dist/private/node/session/exchange.js.map +1 -1
  12. package/dist/private/node/session/scopes.js +3 -5
  13. package/dist/private/node/session/scopes.js.map +1 -1
  14. package/dist/private/node/session.js +2 -3
  15. package/dist/private/node/session.js.map +1 -1
  16. package/dist/private/node/ui/alert.js +1 -3
  17. package/dist/private/node/ui/alert.js.map +1 -1
  18. package/dist/private/node/ui/components/ConcurrentOutput.js +0 -2
  19. package/dist/private/node/ui/components/ConcurrentOutput.js.map +1 -1
  20. package/dist/private/node/ui/components/Link.js +3 -0
  21. package/dist/private/node/ui/components/Link.js.map +1 -1
  22. package/dist/private/node/ui/components/Link.test.js +23 -0
  23. package/dist/private/node/ui/components/Link.test.js.map +1 -1
  24. package/dist/private/node/ui.js +1 -1
  25. package/dist/private/node/ui.js.map +1 -1
  26. package/dist/public/common/version.d.ts +1 -1
  27. package/dist/public/common/version.js +1 -1
  28. package/dist/public/common/version.js.map +1 -1
  29. package/dist/public/node/api/admin.js +11 -1
  30. package/dist/public/node/api/admin.js.map +1 -1
  31. package/dist/public/node/api/graphql.d.ts +2 -0
  32. package/dist/public/node/api/graphql.js +2 -2
  33. package/dist/public/node/api/graphql.js.map +1 -1
  34. package/dist/public/node/api/webhooks.d.ts +13 -0
  35. package/dist/public/node/api/webhooks.js +34 -0
  36. package/dist/public/node/api/webhooks.js.map +1 -0
  37. package/dist/public/node/cli-launcher.d.ts +12 -0
  38. package/dist/public/node/cli-launcher.js +29 -0
  39. package/dist/public/node/cli-launcher.js.map +1 -0
  40. package/dist/public/node/cli.d.ts +12 -10
  41. package/dist/public/node/cli.js +38 -100
  42. package/dist/public/node/cli.js.map +1 -1
  43. package/dist/public/node/context/fqdn.js +11 -7
  44. package/dist/public/node/context/fqdn.js.map +1 -1
  45. package/dist/public/node/context/local.d.ts +7 -0
  46. package/dist/public/node/context/local.js +9 -0
  47. package/dist/public/node/context/local.js.map +1 -1
  48. package/dist/public/node/environment.d.ts +7 -0
  49. package/dist/public/node/environment.js +11 -0
  50. package/dist/public/node/environment.js.map +1 -1
  51. package/dist/public/node/error-handler.js +1 -3
  52. package/dist/public/node/error-handler.js.map +1 -1
  53. package/dist/public/node/hooks/prerun.js +0 -2
  54. package/dist/public/node/hooks/prerun.js.map +1 -1
  55. package/dist/public/node/json-schema.d.ts +2 -1
  56. package/dist/public/node/json-schema.js +8 -3
  57. package/dist/public/node/json-schema.js.map +1 -1
  58. package/dist/public/node/notifications-system.d.ts +3 -1
  59. package/dist/public/node/notifications-system.js +9 -1
  60. package/dist/public/node/notifications-system.js.map +1 -1
  61. package/dist/public/node/output.d.ts +1 -6
  62. package/dist/public/node/output.js +1 -5
  63. package/dist/public/node/output.js.map +1 -1
  64. package/dist/public/node/path.d.ts +3 -3
  65. package/dist/public/node/path.js +4 -5
  66. package/dist/public/node/path.js.map +1 -1
  67. package/dist/public/node/system.js +14 -2
  68. package/dist/public/node/system.js.map +1 -1
  69. package/dist/public/node/themes/api.js +67 -8
  70. package/dist/public/node/themes/api.js.map +1 -1
  71. package/dist/public/node/themes/factories.d.ts +1 -3
  72. package/dist/public/node/themes/factories.js +0 -16
  73. package/dist/public/node/themes/factories.js.map +1 -1
  74. package/dist/public/node/tree-kill.js +0 -2
  75. package/dist/public/node/tree-kill.js.map +1 -1
  76. package/dist/public/node/ui.js +30 -80
  77. package/dist/public/node/ui.js.map +1 -1
  78. package/dist/public/node/vendor/dev_server/DevServer.d.ts +19 -0
  79. package/dist/public/node/vendor/dev_server/DevServer.js +170 -0
  80. package/dist/public/node/vendor/dev_server/DevServer.js.map +1 -0
  81. package/dist/tsconfig.tsbuildinfo +1 -1
  82. package/package.json +7 -4
  83. package/dist/private/node/demo-recorder.d.ts +0 -17
  84. package/dist/private/node/demo-recorder.js +0 -121
  85. package/dist/private/node/demo-recorder.js.map +0 -1
@@ -6,7 +6,6 @@ import { AbortSilentError, CancelExecution, errorMapper, shouldReportErrorAsUnex
6
6
  import { getEnvironmentData } from '../../private/node/analytics.js';
7
7
  import { outputDebug, outputInfo } from '../../public/node/output.js';
8
8
  import { bugsnagApiKey, reportingRateLimit } from '../../private/node/constants.js';
9
- import { printEventsJson } from '../../private/node/demo-recorder.js';
10
9
  import { CLI_KIT_VERSION } from '../common/version.js';
11
10
  import { runWithRateLimit } from '../../private/node/conf-store.js';
12
11
  import { settings } from '@oclif/core';
@@ -20,7 +19,7 @@ export async function errorHandler(error, config) {
20
19
  }
21
20
  }
22
21
  else if (error instanceof AbortSilentError) {
23
- printEventsJson();
22
+ /* empty */
24
23
  }
25
24
  else {
26
25
  return errorMapper(error)
@@ -28,7 +27,6 @@ export async function errorHandler(error, config) {
28
27
  return handler(error);
29
28
  })
30
29
  .then((mappedError) => {
31
- printEventsJson();
32
30
  return reportError(mappedError, config);
33
31
  });
34
32
  }
@@ -1 +1 @@
1
- {"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../../src/public/node/error-handler.ts"],"names":[],"mappings":"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","sourcesContent":["import {CommandExitMode, reportAnalyticsEvent} from './analytics.js'\nimport * as path from './path.js'\nimport {fanoutHooks} from './plugins.js'\nimport * as metadata from './metadata.js'\nimport {\n AbortSilentError,\n CancelExecution,\n errorMapper,\n shouldReportErrorAsUnexpected,\n handler,\n cleanSingleStackTracePath,\n} from './error.js'\nimport {getEnvironmentData} from '../../private/node/analytics.js'\nimport {outputDebug, outputInfo} from '../../public/node/output.js'\nimport {bugsnagApiKey, reportingRateLimit} from '../../private/node/constants.js'\nimport {printEventsJson} from '../../private/node/demo-recorder.js'\nimport {CLI_KIT_VERSION} from '../common/version.js'\nimport {runWithRateLimit} from '../../private/node/conf-store.js'\nimport {settings, Interfaces} from '@oclif/core'\nimport StackTracey from 'stacktracey'\nimport Bugsnag, {Event} from '@bugsnag/js'\nimport {realpath} from 'fs/promises'\n\nexport async function errorHandler(\n error: Error & {exitCode?: number | undefined},\n config?: Interfaces.Config,\n): Promise<void> {\n if (error instanceof CancelExecution) {\n if (error.message && error.message !== '') {\n outputInfo(`✨ ${error.message}`)\n }\n } else if (error instanceof AbortSilentError) {\n printEventsJson()\n } else {\n return errorMapper(error)\n .then((error) => {\n return handler(error)\n })\n .then((mappedError) => {\n printEventsJson()\n return reportError(mappedError, config)\n })\n }\n}\n\nconst reportError = async (error: unknown, config?: Interfaces.Config): Promise<void> => {\n // categorise the error first\n let exitMode: CommandExitMode = 'expected_error'\n if (shouldReportErrorAsUnexpected(error)) exitMode = 'unexpected_error'\n\n if (config !== undefined) {\n // Log an analytics event when there's an error\n await reportAnalyticsEvent({config, errorMessage: error instanceof Error ? error.message : undefined, exitMode})\n }\n await sendErrorToBugsnag(error, exitMode)\n}\n\n/**\n * Sends an error to Bugsnag. This is configured automatically for uncaught errors from CLI commands, but can also be used to manually record an error.\n *\n * @returns the reported error (this may have been tweaked for better reporting), and a bool to indicate if the error was actually submitted or not\n */\nexport async function sendErrorToBugsnag(\n error: unknown,\n exitMode: Omit<CommandExitMode, 'ok'>,\n): Promise<{reported: false; error: unknown; unhandled: unknown} | {error: Error; reported: true; unhandled: boolean}> {\n if (settings.debug) {\n outputDebug(`Skipping Bugsnag report`)\n return {reported: false, error, unhandled: undefined}\n }\n\n // If the error was unexpected, we flag it as \"unhandled\" in Bugsnag. This is a helpful distinction.\n const unhandled = exitMode === 'unexpected_error'\n\n let reportableError: Error\n let stacktrace: string | undefined\n let report = false\n\n if (error instanceof Error) {\n report = true\n reportableError = new Error(error.message)\n stacktrace = error.stack\n\n /**\n * Some errors that reach this point have an empty string. For example:\n * https://app.bugsnag.com/shopify/cli/errors/62cd5d31fd5040000814086c?filters[event.since]=30d&filters[error.status]=new&filters[release.seen_in]=3.1.0\n *\n * Because at this point we have neither the error message nor a stack trace reporting them\n * to Bugsnag is pointless and adds noise.\n */\n } else if (typeof error === 'string' && error.trim().length !== 0) {\n report = true\n reportableError = new Error(error)\n stacktrace = reportableError.stack\n } else {\n report = false\n reportableError = new Error('Unknown error')\n }\n\n const formattedStacktrace = new StackTracey(stacktrace ?? '')\n .clean()\n .items.map((item) => {\n const filePath = cleanSingleStackTracePath(item.file)\n return ` at ${item.callee} (${filePath}:${item.line}:${item.column})`\n })\n .join('\\n')\n reportableError.stack = `Error: ${reportableError.message}\\n${formattedStacktrace}`\n\n let withinRateLimit = false\n await runWithRateLimit({\n key: 'send-error-to-bugsnag',\n ...reportingRateLimit,\n task: async () => {\n withinRateLimit = true\n },\n })\n if (!withinRateLimit) {\n outputDebug(`Skipping Bugsnag report due to rate limiting`)\n report = false\n }\n\n if (report) {\n initializeBugsnag()\n await new Promise((resolve, reject) => {\n outputDebug(`Reporting ${unhandled ? 'unhandled' : 'handled'} error to Bugsnag: ${reportableError.message}`)\n const eventHandler = (event: Event) => {\n event.severity = 'error'\n event.unhandled = unhandled\n }\n const errorHandler = (error: unknown) => {\n if (error) {\n reject(error)\n } else {\n resolve(reportableError)\n }\n }\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n Bugsnag.notify(reportableError, eventHandler, errorHandler)\n })\n }\n return {error: reportableError, reported: report, unhandled}\n}\n\n/**\n * If the given file path is within a node_modules folder, remove prefix up\n * to and including the node_modules folder.\n *\n * This gives us very consistent paths for errors generated by the CLI.\n */\nexport function cleanStackFrameFilePath({\n currentFilePath,\n projectRoot,\n pluginLocations,\n}: {\n currentFilePath: string\n projectRoot: string\n pluginLocations: {name: string; pluginPath: string}[]\n}): string {\n const fullLocation = path.isAbsolutePath(currentFilePath)\n ? currentFilePath\n : path.joinPath(projectRoot, currentFilePath)\n\n const matchingPluginPath = pluginLocations.filter(({pluginPath}) => fullLocation.startsWith(pluginPath))[0]\n\n if (matchingPluginPath !== undefined) {\n // the plugin name (e.g. @shopify/cli-kit), plus the relative path of the error line from within the plugin's code (e.g. dist/something.js )\n return path.joinPath(matchingPluginPath.name, path.relativePath(matchingPluginPath.pluginPath, fullLocation))\n }\n\n // strip prefix up to node_modules folder, so we can normalize error reporting\n return currentFilePath.replace(/.*node_modules\\//, '')\n}\n\n/**\n * Register a Bugsnag error listener to clean up stack traces for errors within plugin code.\n *\n */\nexport async function registerCleanBugsnagErrorsFromWithinPlugins(config: Interfaces.Config): Promise<void> {\n // Bugsnag have their own plug-ins that use this private field\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const bugsnagConfigProjectRoot: string = (Bugsnag as any)?._client?._config?.projectRoot ?? path.cwd()\n const projectRoot = path.normalizePath(bugsnagConfigProjectRoot)\n const pluginLocations = await Promise.all(\n [...config.plugins].map(async ([_, plugin]) => {\n const followSymlinks = await realpath(plugin.root)\n return {name: plugin.name, pluginPath: path.normalizePath(followSymlinks)}\n }),\n )\n initializeBugsnag()\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n Bugsnag.addOnError(async (event) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n event.errors.forEach((error: any) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n error.stacktrace.forEach((stackFrame: any) => {\n stackFrame.file = cleanStackFrameFilePath({currentFilePath: stackFrame.file, projectRoot, pluginLocations})\n })\n })\n try {\n await addBugsnagMetadata(event, config)\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (metadataError) {\n outputDebug(`There was an error adding metadata to the Bugsnag report; Ignoring and carrying on ${metadataError}`)\n }\n })\n}\n\n// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any\nexport async function addBugsnagMetadata(event: any, config: Interfaces.Config): Promise<void> {\n const publicData = metadata.getAllPublicMetadata()\n const {commandStartOptions} = metadata.getAllSensitiveMetadata()\n const {startCommand} = commandStartOptions ?? {}\n\n const {'@shopify/app': appPublic, ...otherPluginsPublic} = await fanoutHooks(config, 'public_command_metadata', {})\n\n const environment = await getEnvironmentData(config)\n\n const allMetadata = {\n command: startCommand,\n ...appPublic,\n ...publicData,\n ...environment,\n pluginData: otherPluginsPublic,\n }\n\n const appData = {} as {[key: string]: unknown}\n const commandData = {} as {[key: string]: unknown}\n const environmentData = {} as {[key: string]: unknown}\n const miscData = {} as {[key: string]: unknown}\n const appKeys = ['api_key', 'partner_id', 'project_type']\n const commandKeys = ['command']\n const environmentKeys = ['cli_version', 'node_version', 'uname']\n\n Object.entries(allMetadata).forEach(([key, value]) => {\n if (key.startsWith('app_') || appKeys.includes(key)) {\n appData[key] = value\n } else if (key.startsWith('cmd_') || commandKeys.includes(key)) {\n commandData[key] = value\n } else if (key.startsWith('env_') || environmentKeys) {\n environmentData[key] = value\n } else {\n miscData[key] = value\n }\n })\n\n // app, command, environment, misc\n const bugsnagMetadata = {\n 'Shopify App': appData,\n Command: commandData,\n Environment: environmentData,\n Misc: miscData,\n }\n Object.entries(bugsnagMetadata).forEach(([section, values]) => {\n event.addMetadata(section, values)\n })\n}\n\nfunction initializeBugsnag() {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n if (Bugsnag.isStarted()) {\n return\n }\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n Bugsnag.start({\n appType: 'node',\n apiKey: bugsnagApiKey,\n logger: null,\n appVersion: CLI_KIT_VERSION,\n autoTrackSessions: false,\n autoDetectErrors: false,\n enabledReleaseStages: ['production'],\n })\n}\n"]}
1
+ {"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../../src/public/node/error-handler.ts"],"names":[],"mappings":"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","sourcesContent":["import {CommandExitMode, reportAnalyticsEvent} from './analytics.js'\nimport * as path from './path.js'\nimport {fanoutHooks} from './plugins.js'\nimport * as metadata from './metadata.js'\nimport {\n AbortSilentError,\n CancelExecution,\n errorMapper,\n shouldReportErrorAsUnexpected,\n handler,\n cleanSingleStackTracePath,\n} from './error.js'\nimport {getEnvironmentData} from '../../private/node/analytics.js'\nimport {outputDebug, outputInfo} from '../../public/node/output.js'\nimport {bugsnagApiKey, reportingRateLimit} from '../../private/node/constants.js'\nimport {CLI_KIT_VERSION} from '../common/version.js'\nimport {runWithRateLimit} from '../../private/node/conf-store.js'\nimport {settings, Interfaces} from '@oclif/core'\nimport StackTracey from 'stacktracey'\nimport Bugsnag, {Event} from '@bugsnag/js'\nimport {realpath} from 'fs/promises'\n\nexport async function errorHandler(\n error: Error & {exitCode?: number | undefined},\n config?: Interfaces.Config,\n): Promise<void> {\n if (error instanceof CancelExecution) {\n if (error.message && error.message !== '') {\n outputInfo(`✨ ${error.message}`)\n }\n } else if (error instanceof AbortSilentError) {\n /* empty */\n } else {\n return errorMapper(error)\n .then((error) => {\n return handler(error)\n })\n .then((mappedError) => {\n return reportError(mappedError, config)\n })\n }\n}\n\nconst reportError = async (error: unknown, config?: Interfaces.Config): Promise<void> => {\n // categorise the error first\n let exitMode: CommandExitMode = 'expected_error'\n if (shouldReportErrorAsUnexpected(error)) exitMode = 'unexpected_error'\n\n if (config !== undefined) {\n // Log an analytics event when there's an error\n await reportAnalyticsEvent({config, errorMessage: error instanceof Error ? error.message : undefined, exitMode})\n }\n await sendErrorToBugsnag(error, exitMode)\n}\n\n/**\n * Sends an error to Bugsnag. This is configured automatically for uncaught errors from CLI commands, but can also be used to manually record an error.\n *\n * @returns the reported error (this may have been tweaked for better reporting), and a bool to indicate if the error was actually submitted or not\n */\nexport async function sendErrorToBugsnag(\n error: unknown,\n exitMode: Omit<CommandExitMode, 'ok'>,\n): Promise<{reported: false; error: unknown; unhandled: unknown} | {error: Error; reported: true; unhandled: boolean}> {\n if (settings.debug) {\n outputDebug(`Skipping Bugsnag report`)\n return {reported: false, error, unhandled: undefined}\n }\n\n // If the error was unexpected, we flag it as \"unhandled\" in Bugsnag. This is a helpful distinction.\n const unhandled = exitMode === 'unexpected_error'\n\n let reportableError: Error\n let stacktrace: string | undefined\n let report = false\n\n if (error instanceof Error) {\n report = true\n reportableError = new Error(error.message)\n stacktrace = error.stack\n\n /**\n * Some errors that reach this point have an empty string. For example:\n * https://app.bugsnag.com/shopify/cli/errors/62cd5d31fd5040000814086c?filters[event.since]=30d&filters[error.status]=new&filters[release.seen_in]=3.1.0\n *\n * Because at this point we have neither the error message nor a stack trace reporting them\n * to Bugsnag is pointless and adds noise.\n */\n } else if (typeof error === 'string' && error.trim().length !== 0) {\n report = true\n reportableError = new Error(error)\n stacktrace = reportableError.stack\n } else {\n report = false\n reportableError = new Error('Unknown error')\n }\n\n const formattedStacktrace = new StackTracey(stacktrace ?? '')\n .clean()\n .items.map((item) => {\n const filePath = cleanSingleStackTracePath(item.file)\n return ` at ${item.callee} (${filePath}:${item.line}:${item.column})`\n })\n .join('\\n')\n reportableError.stack = `Error: ${reportableError.message}\\n${formattedStacktrace}`\n\n let withinRateLimit = false\n await runWithRateLimit({\n key: 'send-error-to-bugsnag',\n ...reportingRateLimit,\n task: async () => {\n withinRateLimit = true\n },\n })\n if (!withinRateLimit) {\n outputDebug(`Skipping Bugsnag report due to rate limiting`)\n report = false\n }\n\n if (report) {\n initializeBugsnag()\n await new Promise((resolve, reject) => {\n outputDebug(`Reporting ${unhandled ? 'unhandled' : 'handled'} error to Bugsnag: ${reportableError.message}`)\n const eventHandler = (event: Event) => {\n event.severity = 'error'\n event.unhandled = unhandled\n }\n const errorHandler = (error: unknown) => {\n if (error) {\n reject(error)\n } else {\n resolve(reportableError)\n }\n }\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n Bugsnag.notify(reportableError, eventHandler, errorHandler)\n })\n }\n return {error: reportableError, reported: report, unhandled}\n}\n\n/**\n * If the given file path is within a node_modules folder, remove prefix up\n * to and including the node_modules folder.\n *\n * This gives us very consistent paths for errors generated by the CLI.\n */\nexport function cleanStackFrameFilePath({\n currentFilePath,\n projectRoot,\n pluginLocations,\n}: {\n currentFilePath: string\n projectRoot: string\n pluginLocations: {name: string; pluginPath: string}[]\n}): string {\n const fullLocation = path.isAbsolutePath(currentFilePath)\n ? currentFilePath\n : path.joinPath(projectRoot, currentFilePath)\n\n const matchingPluginPath = pluginLocations.filter(({pluginPath}) => fullLocation.startsWith(pluginPath))[0]\n\n if (matchingPluginPath !== undefined) {\n // the plugin name (e.g. @shopify/cli-kit), plus the relative path of the error line from within the plugin's code (e.g. dist/something.js )\n return path.joinPath(matchingPluginPath.name, path.relativePath(matchingPluginPath.pluginPath, fullLocation))\n }\n\n // strip prefix up to node_modules folder, so we can normalize error reporting\n return currentFilePath.replace(/.*node_modules\\//, '')\n}\n\n/**\n * Register a Bugsnag error listener to clean up stack traces for errors within plugin code.\n *\n */\nexport async function registerCleanBugsnagErrorsFromWithinPlugins(config: Interfaces.Config): Promise<void> {\n // Bugsnag have their own plug-ins that use this private field\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const bugsnagConfigProjectRoot: string = (Bugsnag as any)?._client?._config?.projectRoot ?? path.cwd()\n const projectRoot = path.normalizePath(bugsnagConfigProjectRoot)\n const pluginLocations = await Promise.all(\n [...config.plugins].map(async ([_, plugin]) => {\n const followSymlinks = await realpath(plugin.root)\n return {name: plugin.name, pluginPath: path.normalizePath(followSymlinks)}\n }),\n )\n initializeBugsnag()\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n Bugsnag.addOnError(async (event) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n event.errors.forEach((error: any) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n error.stacktrace.forEach((stackFrame: any) => {\n stackFrame.file = cleanStackFrameFilePath({currentFilePath: stackFrame.file, projectRoot, pluginLocations})\n })\n })\n try {\n await addBugsnagMetadata(event, config)\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (metadataError) {\n outputDebug(`There was an error adding metadata to the Bugsnag report; Ignoring and carrying on ${metadataError}`)\n }\n })\n}\n\n// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any\nexport async function addBugsnagMetadata(event: any, config: Interfaces.Config): Promise<void> {\n const publicData = metadata.getAllPublicMetadata()\n const {commandStartOptions} = metadata.getAllSensitiveMetadata()\n const {startCommand} = commandStartOptions ?? {}\n\n const {'@shopify/app': appPublic, ...otherPluginsPublic} = await fanoutHooks(config, 'public_command_metadata', {})\n\n const environment = await getEnvironmentData(config)\n\n const allMetadata = {\n command: startCommand,\n ...appPublic,\n ...publicData,\n ...environment,\n pluginData: otherPluginsPublic,\n }\n\n const appData = {} as {[key: string]: unknown}\n const commandData = {} as {[key: string]: unknown}\n const environmentData = {} as {[key: string]: unknown}\n const miscData = {} as {[key: string]: unknown}\n const appKeys = ['api_key', 'partner_id', 'project_type']\n const commandKeys = ['command']\n const environmentKeys = ['cli_version', 'node_version', 'uname']\n\n Object.entries(allMetadata).forEach(([key, value]) => {\n if (key.startsWith('app_') || appKeys.includes(key)) {\n appData[key] = value\n } else if (key.startsWith('cmd_') || commandKeys.includes(key)) {\n commandData[key] = value\n } else if (key.startsWith('env_') || environmentKeys) {\n environmentData[key] = value\n } else {\n miscData[key] = value\n }\n })\n\n // app, command, environment, misc\n const bugsnagMetadata = {\n 'Shopify App': appData,\n Command: commandData,\n Environment: environmentData,\n Misc: miscData,\n }\n Object.entries(bugsnagMetadata).forEach(([section, values]) => {\n event.addMetadata(section, values)\n })\n}\n\nfunction initializeBugsnag() {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n if (Bugsnag.isStarted()) {\n return\n }\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n Bugsnag.start({\n appType: 'node',\n apiKey: bugsnagApiKey,\n logger: null,\n appVersion: CLI_KIT_VERSION,\n autoTrackSessions: false,\n autoDetectErrors: false,\n enabledReleaseStages: ['production'],\n })\n}\n"]}
@@ -3,11 +3,9 @@ import { checkForNewVersion, checkForCachedNewVersion } from '../node-package-ma
3
3
  import { startAnalytics } from '../../../private/node/analytics.js';
4
4
  import { outputDebug, outputWarn } from '../../../public/node/output.js';
5
5
  import { getOutputUpdateCLIReminder } from '../../../public/node/upgrade.js';
6
- import { initDemoRecorder } from '../../../private/node/demo-recorder.js';
7
6
  import { runAtMinimumInterval } from '../../../private/node/conf-store.js';
8
7
  // This hook is called before each command run. More info: https://oclif.io/docs/hooks
9
8
  export const hook = async (options) => {
10
- initDemoRecorder();
11
9
  const commandContent = parseCommandContent({
12
10
  id: options.Command.id,
13
11
  aliases: options.Command.aliases,
@@ -1 +1 @@
1
- {"version":3,"file":"prerun.js","sourceRoot":"","sources":["../../../../src/public/node/hooks/prerun.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,yBAAyB,CAAA;AACvD,OAAO,EAAC,kBAAkB,EAAE,wBAAwB,EAAC,MAAM,4BAA4B,CAAA;AACvF,OAAO,EAAC,cAAc,EAAC,MAAM,oCAAoC,CAAA;AACjE,OAAO,EAAC,WAAW,EAAE,UAAU,EAAC,MAAM,gCAAgC,CAAA;AACtE,OAAO,EAAC,0BAA0B,EAAC,MAAM,iCAAiC,CAAA;AAE1E,OAAO,EAAC,gBAAgB,EAAC,MAAM,wCAAwC,CAAA;AACvE,OAAO,EAAC,oBAAoB,EAAC,MAAM,qCAAqC,CAAA;AAQxE,sFAAsF;AACtF,MAAM,CAAC,MAAM,IAAI,GAAgB,KAAK,EAAE,OAAO,EAAE,EAAE;IACjD,gBAAgB,EAAE,CAAA;IAClB,MAAM,cAAc,GAAG,mBAAmB,CAAC;QACzC,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE;QACtB,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,OAAO;QAChC,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK;KAC3C,CAAC,CAAA;IACF,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAA;IACzB,MAAM,sBAAsB,EAAE,CAAA;IAC9B,WAAW,CAAC,mBAAmB,cAAc,CAAC,OAAO,EAAE,CAAC,CAAA;IACxD,MAAM,cAAc,CAAC,EAAC,cAAc,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,CAAC,OAAoC,EAAC,CAAC,CAAA;AAC1G,CAAC,CAAA;AAED,MAAM,UAAU,mBAAmB,CAAC,OAA8D;IAChG,IAAI,cAAc,GAAG,kBAAkB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IAC5D,IAAI,CAAC,cAAc,EAAE;QACnB,cAAc,GAAG,kBAAkB,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;KACjE;IACD,OAAO,cAAc,CAAA;AACvB,CAAC;AAED,SAAS,kBAAkB,CAAC,EAAU,EAAE,OAAiB;IACvD,OAAO;QACL,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC;QAC9B,KAAK,EAAE,UAAU,CAAC,EAAE,CAAC;QACrB,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC;KAC1B,CAAA;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAS,kBAAkB,CAAC,WAAoB;IAC9C,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,kBAAkB,CAAC,EAAE;QAChD,OAAO,SAAS,CAAA;KACjB;IAED,OAAO,EAAC,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAC,CAAA;AACvE,CAAC;AAED;;;;;;GAMG;AACH,SAAS,UAAU,CAAC,GAAW;IAC7B,IAAI,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE;QAC/B,OAAM;KACP;IACD,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;AAC9D,CAAC;AAED;;;;;GAKG;AACH,SAAS,SAAS,CAAC,OAAiB;IAClC,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAC3C,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAC1E,CAAA;IACD,IAAI,aAAa,EAAE;QACjB,OAAO,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;KACxC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB;IAC1C,MAAM,aAAa,GAAG,cAAc,CAAA;IACpC,MAAM,cAAc,GAAG,eAAe,CAAA;IACtC,IAAI,cAAc,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE;QACtC,yFAAyF;QACzF,OAAM;KACP;IAED,sCAAsC;IACtC,mCAAmC;IACnC,KAAK,kBAAkB,CAAC,aAAa,EAAE,cAAc,EAAE,EAAC,kBAAkB,EAAE,EAAE,EAAC,CAAC,CAAA;IAEhF,4CAA4C;IAC5C,MAAM,oBAAoB,CAAC,2BAA2B,EAAE,EAAC,IAAI,EAAE,CAAC,EAAC,EAAE,KAAK,IAAI,EAAE;QAC5E,MAAM,YAAY,GAAG,wBAAwB,CAAC,aAAa,EAAE,cAAc,CAAC,CAAA;QAC5E,IAAI,YAAY,EAAE;YAChB,UAAU,CAAC,0BAA0B,CAAC,YAAY,CAAC,CAAC,CAAA;SACrD;IACH,CAAC,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import {CLI_KIT_VERSION} from '../../common/version.js'\nimport {checkForNewVersion, checkForCachedNewVersion} from '../node-package-manager.js'\nimport {startAnalytics} from '../../../private/node/analytics.js'\nimport {outputDebug, outputWarn} from '../../../public/node/output.js'\nimport {getOutputUpdateCLIReminder} from '../../../public/node/upgrade.js'\nimport Command from '../../../public/node/base-command.js'\nimport {initDemoRecorder} from '../../../private/node/demo-recorder.js'\nimport {runAtMinimumInterval} from '../../../private/node/conf-store.js'\nimport {Hook} from '@oclif/core'\n\nexport declare interface CommandContent {\n command: string\n topic?: string\n alias?: string\n}\n// This hook is called before each command run. More info: https://oclif.io/docs/hooks\nexport const hook: Hook.Prerun = async (options) => {\n initDemoRecorder()\n const commandContent = parseCommandContent({\n id: options.Command.id,\n aliases: options.Command.aliases,\n pluginAlias: options.Command.plugin?.alias,\n })\n const args = options.argv\n await warnOnAvailableUpgrade()\n outputDebug(`Running command ${commandContent.command}`)\n await startAnalytics({commandContent, args, commandClass: options.Command as unknown as typeof Command})\n}\n\nexport function parseCommandContent(cmdInfo: {id: string; aliases: string[]; pluginAlias?: string}): CommandContent {\n let commandContent = parseCreateCommand(cmdInfo.pluginAlias)\n if (!commandContent) {\n commandContent = parseNormalCommand(cmdInfo.id, cmdInfo.aliases)\n }\n return commandContent\n}\n\nfunction parseNormalCommand(id: string, aliases: string[]): CommandContent {\n return {\n command: id.replace(/:/g, ' '),\n topic: parseTopic(id),\n alias: findAlias(aliases),\n }\n}\n\n/**\n * Create commands implement Init by default, so the name of the command must be extracted from\n * the plugin/module name. Neither alias or topic are supported\n *\n * @param commandClass - Oclif command configuration\n * @returns Command content with the name of the command or undefined otherwise\n */\nfunction parseCreateCommand(pluginAlias?: string): CommandContent | undefined {\n if (!pluginAlias?.startsWith('@shopify/create-')) {\n return undefined\n }\n\n return {command: pluginAlias.substring(pluginAlias.indexOf('/') + 1)}\n}\n\n/**\n * Commands use this pattern topic:subtopic1:...:subtopicN:command. This method extract the topic and subtopic\n * information replacing the ':' separator with one space\n *\n * @param cmd - Complete command string to extract the topic information\n * @returns The topic name or undefined otherwise\n */\nfunction parseTopic(cmd: string) {\n if (cmd.lastIndexOf(':') === -1) {\n return\n }\n return cmd.slice(0, cmd.lastIndexOf(':')).replace(/:/g, ' ')\n}\n\n/**\n * Identifies if the command was launched using an alias instead of the oficial command name\n *\n * @param aliases - List of possible alias a command has\n * @returns The alias used or undefined otherwise\n */\nfunction findAlias(aliases: string[]) {\n const existingAlias = aliases.find((alias) =>\n alias.split(':').every((aliasToken) => process.argv.includes(aliasToken)),\n )\n if (existingAlias) {\n return existingAlias.replace(/:/g, ' ')\n }\n}\n\n/**\n * Warns the user if there is a new version of the CLI available\n */\nexport async function warnOnAvailableUpgrade(): Promise<void> {\n const cliDependency = '@shopify/cli'\n const currentVersion = CLI_KIT_VERSION\n if (currentVersion.startsWith('0.0.0')) {\n // This is a nightly/snapshot/experimental version, so we don't want to check for updates\n return\n }\n\n // Check in the background, once daily\n // eslint-disable-next-line no-void\n void checkForNewVersion(cliDependency, currentVersion, {cacheExpiryInHours: 24})\n\n // Warn if we previously found a new version\n await runAtMinimumInterval('warn-on-available-upgrade', {days: 1}, async () => {\n const newerVersion = checkForCachedNewVersion(cliDependency, currentVersion)\n if (newerVersion) {\n outputWarn(getOutputUpdateCLIReminder(newerVersion))\n }\n })\n}\n"]}
1
+ {"version":3,"file":"prerun.js","sourceRoot":"","sources":["../../../../src/public/node/hooks/prerun.ts"],"names":[],"mappings":"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","sourcesContent":["import {CLI_KIT_VERSION} from '../../common/version.js'\nimport {checkForNewVersion, checkForCachedNewVersion} from '../node-package-manager.js'\nimport {startAnalytics} from '../../../private/node/analytics.js'\nimport {outputDebug, outputWarn} from '../../../public/node/output.js'\nimport {getOutputUpdateCLIReminder} from '../../../public/node/upgrade.js'\nimport Command from '../../../public/node/base-command.js'\nimport {runAtMinimumInterval} from '../../../private/node/conf-store.js'\nimport {Hook} from '@oclif/core'\n\nexport declare interface CommandContent {\n command: string\n topic?: string\n alias?: string\n}\n// This hook is called before each command run. More info: https://oclif.io/docs/hooks\nexport const hook: Hook.Prerun = async (options) => {\n const commandContent = parseCommandContent({\n id: options.Command.id,\n aliases: options.Command.aliases,\n pluginAlias: options.Command.plugin?.alias,\n })\n const args = options.argv\n await warnOnAvailableUpgrade()\n outputDebug(`Running command ${commandContent.command}`)\n await startAnalytics({commandContent, args, commandClass: options.Command as unknown as typeof Command})\n}\n\nexport function parseCommandContent(cmdInfo: {id: string; aliases: string[]; pluginAlias?: string}): CommandContent {\n let commandContent = parseCreateCommand(cmdInfo.pluginAlias)\n if (!commandContent) {\n commandContent = parseNormalCommand(cmdInfo.id, cmdInfo.aliases)\n }\n return commandContent\n}\n\nfunction parseNormalCommand(id: string, aliases: string[]): CommandContent {\n return {\n command: id.replace(/:/g, ' '),\n topic: parseTopic(id),\n alias: findAlias(aliases),\n }\n}\n\n/**\n * Create commands implement Init by default, so the name of the command must be extracted from\n * the plugin/module name. Neither alias or topic are supported\n *\n * @param commandClass - Oclif command configuration\n * @returns Command content with the name of the command or undefined otherwise\n */\nfunction parseCreateCommand(pluginAlias?: string): CommandContent | undefined {\n if (!pluginAlias?.startsWith('@shopify/create-')) {\n return undefined\n }\n\n return {command: pluginAlias.substring(pluginAlias.indexOf('/') + 1)}\n}\n\n/**\n * Commands use this pattern topic:subtopic1:...:subtopicN:command. This method extract the topic and subtopic\n * information replacing the ':' separator with one space\n *\n * @param cmd - Complete command string to extract the topic information\n * @returns The topic name or undefined otherwise\n */\nfunction parseTopic(cmd: string) {\n if (cmd.lastIndexOf(':') === -1) {\n return\n }\n return cmd.slice(0, cmd.lastIndexOf(':')).replace(/:/g, ' ')\n}\n\n/**\n * Identifies if the command was launched using an alias instead of the oficial command name\n *\n * @param aliases - List of possible alias a command has\n * @returns The alias used or undefined otherwise\n */\nfunction findAlias(aliases: string[]) {\n const existingAlias = aliases.find((alias) =>\n alias.split(':').every((aliasToken) => process.argv.includes(aliasToken)),\n )\n if (existingAlias) {\n return existingAlias.replace(/:/g, ' ')\n }\n}\n\n/**\n * Warns the user if there is a new version of the CLI available\n */\nexport async function warnOnAvailableUpgrade(): Promise<void> {\n const cliDependency = '@shopify/cli'\n const currentVersion = CLI_KIT_VERSION\n if (currentVersion.startsWith('0.0.0')) {\n // This is a nightly/snapshot/experimental version, so we don't want to check for updates\n return\n }\n\n // Check in the background, once daily\n // eslint-disable-next-line no-void\n void checkForNewVersion(cliDependency, currentVersion, {cacheExpiryInHours: 24})\n\n // Warn if we previously found a new version\n await runAtMinimumInterval('warn-on-available-upgrade', {days: 1}, async () => {\n const newerVersion = checkForCachedNewVersion(cliDependency, currentVersion)\n if (newerVersion) {\n outputWarn(getOutputUpdateCLIReminder(newerVersion))\n }\n })\n}\n"]}
@@ -19,9 +19,10 @@ export declare function normaliseJsonSchema(schema: string): Promise<SchemaObjec
19
19
  *
20
20
  * @param subject - The object to validate.
21
21
  * @param schema - The JSON schema to validate against.
22
+ * @param identifier - The identifier of the schema being validated, used to cache the validator.
22
23
  * @returns The result of the validation. If the state is 'error', the errors will be in a zod-like format.
23
24
  */
24
- export declare function jsonSchemaValidate(subject: object, schema: SchemaObject): ParseConfigurationResult<unknown> & {
25
+ export declare function jsonSchemaValidate(subject: object, schema: SchemaObject, identifier: string): ParseConfigurationResult<unknown> & {
25
26
  rawErrors?: AjvError[];
26
27
  };
27
28
  export {};
@@ -16,6 +16,7 @@ export async function normaliseJsonSchema(schema) {
16
16
  await $RefParser.dereference(parsedSchema, { resolve: { external: false } });
17
17
  return parsedSchema;
18
18
  }
19
+ const validatorsCache = new Map();
19
20
  /**
20
21
  * Given a subject object and a JSON schema contract, validate the subject against the contract.
21
22
  *
@@ -23,11 +24,14 @@ export async function normaliseJsonSchema(schema) {
23
24
  *
24
25
  * @param subject - The object to validate.
25
26
  * @param schema - The JSON schema to validate against.
27
+ * @param identifier - The identifier of the schema being validated, used to cache the validator.
26
28
  * @returns The result of the validation. If the state is 'error', the errors will be in a zod-like format.
27
29
  */
28
- export function jsonSchemaValidate(subject, schema) {
30
+ export function jsonSchemaValidate(subject, schema, identifier) {
29
31
  const ajv = new Ajv({ allowUnionTypes: true });
30
- const validator = ajv.compile(schema);
32
+ ajv.addKeyword('x-taplo');
33
+ const validator = validatorsCache.get(identifier) ?? ajv.compile(schema);
34
+ validatorsCache.set(identifier, validator);
31
35
  validator(subject);
32
36
  // Errors from the contract are post-processed to be more zod-like and to deal with unions better
33
37
  let jsonSchemaErrors;
@@ -133,7 +137,8 @@ function convertJsonSchemaErrors(rawErrors, subject, schema) {
133
137
  * @returns A simplified list of errors.
134
138
  */
135
139
  function simplifyUnionErrors(rawErrors, subject, schema) {
136
- const ajv = new Ajv();
140
+ const ajv = new Ajv({ allowUnionTypes: true });
141
+ ajv.addKeyword('x-taplo');
137
142
  let errors = rawErrors;
138
143
  const resolvedUnionErrors = new Set();
139
144
  while (true) {
@@ -1 +1 @@
1
- {"version":3,"file":"json-schema.js","sourceRoot":"","sources":["../../../src/public/node/json-schema.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-non-null-assertion */\nimport {ParseConfigurationResult} from './schema.js'\nimport {getPathValue} from '../common/object.js'\nimport {capitalize} from '../common/string.js'\nimport {Ajv, ErrorObject, SchemaObject} from 'ajv'\nimport $RefParser from '@apidevtools/json-schema-ref-parser'\n\ntype AjvError = ErrorObject<string, {[key: string]: unknown}>\n\n/**\n * Normalises a JSON Schema by standardising it's internal implementation.\n *\n * We prefer to not use $ref elements in our schemas, so we inline them; it's easier then to process errors.\n *\n * @param schema - The JSON schema (as a string) to normalise.\n * @returns The normalised JSON schema.\n */\nexport async function normaliseJsonSchema(schema: string): Promise<SchemaObject> {\n // we want to modify the schema, removing any $ref elements and inlining with their source\n const parsedSchema = JSON.parse(schema)\n await $RefParser.dereference(parsedSchema, {resolve: {external: false}})\n return parsedSchema\n}\n\n/**\n * Given a subject object and a JSON schema contract, validate the subject against the contract.\n *\n * Errors are returned in a zod-like format, and processed to better handle unions.\n *\n * @param subject - The object to validate.\n * @param schema - The JSON schema to validate against.\n * @returns The result of the validation. If the state is 'error', the errors will be in a zod-like format.\n */\nexport function jsonSchemaValidate(\n subject: object,\n schema: SchemaObject,\n): ParseConfigurationResult<unknown> & {rawErrors?: AjvError[]} {\n const ajv = new Ajv({allowUnionTypes: true})\n const validator = ajv.compile(schema)\n validator(subject)\n\n // Errors from the contract are post-processed to be more zod-like and to deal with unions better\n let jsonSchemaErrors\n if (validator.errors && validator.errors.length > 0) {\n jsonSchemaErrors = convertJsonSchemaErrors(validator.errors, subject, schema)\n return {\n state: 'error',\n data: undefined,\n errors: jsonSchemaErrors,\n rawErrors: validator.errors,\n }\n }\n return {\n state: 'ok',\n data: subject,\n errors: undefined,\n rawErrors: undefined,\n }\n}\n\n/**\n * Converts errors from Ajv into a zod-like format.\n *\n * @param rawErrors - JSON Schema errors taken directly from Ajv.\n * @param subject - The object being validated.\n * @param schema - The JSON schema to validated against.\n * @returns The errors in a zod-like format.\n */\nfunction convertJsonSchemaErrors(rawErrors: AjvError[], subject: object, schema: SchemaObject) {\n // This reduces the number of errors by simplifying errors coming from different branches of a union\n const errors = simplifyUnionErrors(rawErrors, subject, schema)\n\n // Now we can remap errors to be more zod-like\n return errors.map((error) => {\n const path: string[] = error.instancePath.split('/').slice(1)\n if (error.params.missingProperty) {\n const missingProperty = error.params.missingProperty as string\n return {path: [...path, missingProperty], message: 'Required'}\n }\n\n if (error.params.type) {\n const expectedType = error.params.type as string\n const actualType = getPathValue(subject, path.join('.'))\n return {path, message: `Expected ${expectedType}, received ${typeof actualType}`}\n }\n\n if (error.keyword === 'anyOf' || error.keyword === 'oneOf') {\n return {path, message: 'Invalid input'}\n }\n\n if (error.params.allowedValues) {\n const allowedValues = error.params.allowedValues as string[]\n const actualValue = getPathValue(subject, path.join('.'))\n return {\n path,\n message: `Invalid enum value. Expected ${allowedValues\n .map((value) => JSON.stringify(value))\n .join(' | ')}, received ${JSON.stringify(actualValue)}`.replace(/\"/g, \"'\"),\n }\n }\n\n if (error.params.comparison) {\n const comparison = error.params.comparison as string\n const limit = error.params.limit\n const actualValue = getPathValue(subject, path.join('.'))\n\n let comparisonText = comparison\n switch (comparison) {\n case '<=':\n comparisonText = 'less than or equal to'\n break\n case '<':\n comparisonText = 'less than'\n break\n case '>=':\n comparisonText = 'greater than or equal to'\n break\n case '>':\n comparisonText = 'greater than'\n break\n }\n\n return {\n path,\n message: capitalize(`${typeof actualValue} must be ${comparisonText} ${limit}`),\n }\n }\n\n return {\n path,\n message: error.message,\n }\n })\n}\n\n/**\n * If a JSON schema specifies a union (anyOf, oneOf), and the subject doesn't meet any of the 'candidates' for the\n * union, then the error list received ends up being quite long: you get an error for the union property itself, and\n * then additional errors for each of the candidate branches.\n *\n * This function simplifies the error collection. By default it strips anything other than the union error itself.\n *\n * In some cases, it can be possible to identify what the intended branch of the union was -- for instance, maybe there\n * is a discriminating field like `type` that is unique between the branches. We inspect each candidate branch and if\n * one branch is less wrong than the others -- e.g. It had a valid `type`, but problems elsewhere -- then we keep the\n * errors for that branch.\n *\n * This is complex but in practise gives much more actionable errors.\n *\n * @param rawErrors - JSON Schema errors taken directly from Ajv.\n * @param subject - The object being validated.\n * @param schema - The JSON schema to validated against.\n * @returns A simplified list of errors.\n */\nfunction simplifyUnionErrors(rawErrors: AjvError[], subject: object, schema: SchemaObject): AjvError[] {\n const ajv = new Ajv()\n let errors = rawErrors\n\n const resolvedUnionErrors = new Set()\n while (true) {\n const unionError = errors.filter(\n (error) =>\n (error.keyword === 'oneOf' || error.keyword === 'anyOf') && !resolvedUnionErrors.has(error.instancePath),\n )[0]\n if (unionError === undefined) {\n break\n }\n // split errors into those sharing an instance path and those not\n const unrelatedErrors = errors.filter((error) => !error.instancePath.startsWith(unionError.instancePath))\n\n // we start by assuming only the union error itself is useful, and not the errors from the candidate schemas\n let simplifiedUnionRelatedErrors: AjvError[] = [unionError]\n\n // get the schema list from where the union issue occured\n const dottedSchemaPath = unionError.schemaPath.replace('#/', '').replace(/\\//g, '.')\n const unionSchemas = getPathValue<SchemaObject[]>(schema, dottedSchemaPath)\n // and the slice of the subject that caused the issue\n const subjectValue = getPathValue(subject, unionError.instancePath.split('/').slice(1).join('.'))\n\n if (unionSchemas !== undefined && subjectValue !== undefined) {\n // we know that none of the union schemas are correct, but for each of them we can measure how wrong they are\n const correctValuesAndErrors = unionSchemas\n .map((candidateSchemaFromUnion: SchemaObject) => {\n const candidateSchemaValidator = ajv.compile(candidateSchemaFromUnion)\n candidateSchemaValidator(subjectValue)\n\n let score = 0\n if (candidateSchemaFromUnion.type === 'object') {\n // provided the schema is an object, we can measure how many properties are good\n const candidatesObjectProperties = Object.keys(candidateSchemaFromUnion.properties)\n score = candidatesObjectProperties.reduce((acc, propertyName) => {\n const subSchema = candidateSchemaFromUnion.properties[propertyName] as SchemaObject\n const subjectValueSlice = getPathValue(subjectValue, propertyName)\n\n const subValidator = ajv.compile(subSchema)\n if (subValidator(subjectValueSlice)) {\n return acc + 1\n }\n return acc\n }, score)\n }\n\n return [score, candidateSchemaValidator.errors!] as const\n })\n .sort(([scoreA], [scoreB]) => scoreA - scoreB)\n\n if (correctValuesAndErrors.length >= 2) {\n const [bestScore, bestErrors] = correctValuesAndErrors[correctValuesAndErrors.length - 1]!\n const [penultimateScore] = correctValuesAndErrors[correctValuesAndErrors.length - 2]!\n\n if (bestScore !== penultimateScore) {\n // If there's a winner, show the errors for the best schema as they'll likely be actionable.\n // We got these through a nested schema, so we need to adjust the instance path\n simplifiedUnionRelatedErrors = [\n unionError,\n ...bestErrors.map((bestError) => ({\n ...bestError,\n instancePath: unionError.instancePath + bestError.instancePath,\n })),\n ]\n }\n }\n }\n errors = [...unrelatedErrors, ...simplifiedUnionRelatedErrors]\n\n resolvedUnionErrors.add(unionError.instancePath)\n }\n return errors\n}\n"]}
1
+ {"version":3,"file":"json-schema.js","sourceRoot":"","sources":["../../../src/public/node/json-schema.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-non-null-assertion */\nimport {ParseConfigurationResult} from './schema.js'\nimport {getPathValue} from '../common/object.js'\nimport {capitalize} from '../common/string.js'\nimport {Ajv, ErrorObject, SchemaObject, ValidateFunction} from 'ajv'\nimport $RefParser from '@apidevtools/json-schema-ref-parser'\n\ntype AjvError = ErrorObject<string, {[key: string]: unknown}>\n\n/**\n * Normalises a JSON Schema by standardising it's internal implementation.\n *\n * We prefer to not use $ref elements in our schemas, so we inline them; it's easier then to process errors.\n *\n * @param schema - The JSON schema (as a string) to normalise.\n * @returns The normalised JSON schema.\n */\nexport async function normaliseJsonSchema(schema: string): Promise<SchemaObject> {\n // we want to modify the schema, removing any $ref elements and inlining with their source\n const parsedSchema = JSON.parse(schema)\n await $RefParser.dereference(parsedSchema, {resolve: {external: false}})\n return parsedSchema\n}\n\nconst validatorsCache = new Map<string, ValidateFunction>()\n\n/**\n * Given a subject object and a JSON schema contract, validate the subject against the contract.\n *\n * Errors are returned in a zod-like format, and processed to better handle unions.\n *\n * @param subject - The object to validate.\n * @param schema - The JSON schema to validate against.\n * @param identifier - The identifier of the schema being validated, used to cache the validator.\n * @returns The result of the validation. If the state is 'error', the errors will be in a zod-like format.\n */\nexport function jsonSchemaValidate(\n subject: object,\n schema: SchemaObject,\n identifier: string,\n): ParseConfigurationResult<unknown> & {rawErrors?: AjvError[]} {\n const ajv = new Ajv({allowUnionTypes: true})\n\n ajv.addKeyword('x-taplo')\n\n const validator = validatorsCache.get(identifier) ?? ajv.compile(schema)\n validatorsCache.set(identifier, validator)\n\n validator(subject)\n\n // Errors from the contract are post-processed to be more zod-like and to deal with unions better\n let jsonSchemaErrors\n if (validator.errors && validator.errors.length > 0) {\n jsonSchemaErrors = convertJsonSchemaErrors(validator.errors, subject, schema)\n return {\n state: 'error',\n data: undefined,\n errors: jsonSchemaErrors,\n rawErrors: validator.errors,\n }\n }\n return {\n state: 'ok',\n data: subject,\n errors: undefined,\n rawErrors: undefined,\n }\n}\n\n/**\n * Converts errors from Ajv into a zod-like format.\n *\n * @param rawErrors - JSON Schema errors taken directly from Ajv.\n * @param subject - The object being validated.\n * @param schema - The JSON schema to validated against.\n * @returns The errors in a zod-like format.\n */\nfunction convertJsonSchemaErrors(rawErrors: AjvError[], subject: object, schema: SchemaObject) {\n // This reduces the number of errors by simplifying errors coming from different branches of a union\n const errors = simplifyUnionErrors(rawErrors, subject, schema)\n\n // Now we can remap errors to be more zod-like\n return errors.map((error) => {\n const path: string[] = error.instancePath.split('/').slice(1)\n if (error.params.missingProperty) {\n const missingProperty = error.params.missingProperty as string\n return {path: [...path, missingProperty], message: 'Required'}\n }\n\n if (error.params.type) {\n const expectedType = error.params.type as string\n const actualType = getPathValue(subject, path.join('.'))\n return {path, message: `Expected ${expectedType}, received ${typeof actualType}`}\n }\n\n if (error.keyword === 'anyOf' || error.keyword === 'oneOf') {\n return {path, message: 'Invalid input'}\n }\n\n if (error.params.allowedValues) {\n const allowedValues = error.params.allowedValues as string[]\n const actualValue = getPathValue(subject, path.join('.'))\n return {\n path,\n message: `Invalid enum value. Expected ${allowedValues\n .map((value) => JSON.stringify(value))\n .join(' | ')}, received ${JSON.stringify(actualValue)}`.replace(/\"/g, \"'\"),\n }\n }\n\n if (error.params.comparison) {\n const comparison = error.params.comparison as string\n const limit = error.params.limit\n const actualValue = getPathValue(subject, path.join('.'))\n\n let comparisonText = comparison\n switch (comparison) {\n case '<=':\n comparisonText = 'less than or equal to'\n break\n case '<':\n comparisonText = 'less than'\n break\n case '>=':\n comparisonText = 'greater than or equal to'\n break\n case '>':\n comparisonText = 'greater than'\n break\n }\n\n return {\n path,\n message: capitalize(`${typeof actualValue} must be ${comparisonText} ${limit}`),\n }\n }\n\n return {\n path,\n message: error.message,\n }\n })\n}\n\n/**\n * If a JSON schema specifies a union (anyOf, oneOf), and the subject doesn't meet any of the 'candidates' for the\n * union, then the error list received ends up being quite long: you get an error for the union property itself, and\n * then additional errors for each of the candidate branches.\n *\n * This function simplifies the error collection. By default it strips anything other than the union error itself.\n *\n * In some cases, it can be possible to identify what the intended branch of the union was -- for instance, maybe there\n * is a discriminating field like `type` that is unique between the branches. We inspect each candidate branch and if\n * one branch is less wrong than the others -- e.g. It had a valid `type`, but problems elsewhere -- then we keep the\n * errors for that branch.\n *\n * This is complex but in practise gives much more actionable errors.\n *\n * @param rawErrors - JSON Schema errors taken directly from Ajv.\n * @param subject - The object being validated.\n * @param schema - The JSON schema to validated against.\n * @returns A simplified list of errors.\n */\nfunction simplifyUnionErrors(rawErrors: AjvError[], subject: object, schema: SchemaObject): AjvError[] {\n const ajv = new Ajv({allowUnionTypes: true})\n ajv.addKeyword('x-taplo')\n let errors = rawErrors\n\n const resolvedUnionErrors = new Set()\n while (true) {\n const unionError = errors.filter(\n (error) =>\n (error.keyword === 'oneOf' || error.keyword === 'anyOf') && !resolvedUnionErrors.has(error.instancePath),\n )[0]\n if (unionError === undefined) {\n break\n }\n // split errors into those sharing an instance path and those not\n const unrelatedErrors = errors.filter((error) => !error.instancePath.startsWith(unionError.instancePath))\n\n // we start by assuming only the union error itself is useful, and not the errors from the candidate schemas\n let simplifiedUnionRelatedErrors: AjvError[] = [unionError]\n\n // get the schema list from where the union issue occured\n const dottedSchemaPath = unionError.schemaPath.replace('#/', '').replace(/\\//g, '.')\n const unionSchemas = getPathValue<SchemaObject[]>(schema, dottedSchemaPath)\n // and the slice of the subject that caused the issue\n const subjectValue = getPathValue(subject, unionError.instancePath.split('/').slice(1).join('.'))\n\n if (unionSchemas !== undefined && subjectValue !== undefined) {\n // we know that none of the union schemas are correct, but for each of them we can measure how wrong they are\n const correctValuesAndErrors = unionSchemas\n .map((candidateSchemaFromUnion: SchemaObject) => {\n const candidateSchemaValidator = ajv.compile(candidateSchemaFromUnion)\n candidateSchemaValidator(subjectValue)\n\n let score = 0\n if (candidateSchemaFromUnion.type === 'object') {\n // provided the schema is an object, we can measure how many properties are good\n const candidatesObjectProperties = Object.keys(candidateSchemaFromUnion.properties)\n score = candidatesObjectProperties.reduce((acc, propertyName) => {\n const subSchema = candidateSchemaFromUnion.properties[propertyName] as SchemaObject\n const subjectValueSlice = getPathValue(subjectValue, propertyName)\n\n const subValidator = ajv.compile(subSchema)\n if (subValidator(subjectValueSlice)) {\n return acc + 1\n }\n return acc\n }, score)\n }\n\n return [score, candidateSchemaValidator.errors!] as const\n })\n .sort(([scoreA], [scoreB]) => scoreA - scoreB)\n\n if (correctValuesAndErrors.length >= 2) {\n const [bestScore, bestErrors] = correctValuesAndErrors[correctValuesAndErrors.length - 1]!\n const [penultimateScore] = correctValuesAndErrors[correctValuesAndErrors.length - 2]!\n\n if (bestScore !== penultimateScore) {\n // If there's a winner, show the errors for the best schema as they'll likely be actionable.\n // We got these through a nested schema, so we need to adjust the instance path\n simplifiedUnionRelatedErrors = [\n unionError,\n ...bestErrors.map((bestError) => ({\n ...bestError,\n instancePath: unionError.instancePath + bestError.instancePath,\n })),\n ]\n }\n }\n }\n errors = [...unrelatedErrors, ...simplifiedUnionRelatedErrors]\n\n resolvedUnionErrors.add(unionError.instancePath)\n }\n return errors\n}\n"]}
@@ -1,3 +1,4 @@
1
+ /// <reference types="node" resolution-mode="require"/>
1
2
  import { zod } from './schema.js';
2
3
  declare const NotificationSchema: zod.ZodObject<{
3
4
  id: zod.ZodString;
@@ -161,9 +162,10 @@ export type Notifications = zod.infer<typeof NotificationsSchema>;
161
162
  * Shows notifications to the user if they meet the criteria specified in the notifications.json file.
162
163
  *
163
164
  * @param currentSurfaces - The surfaces present in the current project (usually for app extensions).
165
+ * @param environment - Process environment variables.
164
166
  * @returns - A promise that resolves when the notifications have been shown.
165
167
  */
166
- export declare function showNotificationsIfNeeded(currentSurfaces?: string[]): Promise<void>;
168
+ export declare function showNotificationsIfNeeded(currentSurfaces?: string[], environment?: NodeJS.ProcessEnv): Promise<void>;
167
169
  /**
168
170
  * Get notifications list from cache (refreshed every hour) or fetch it if not present.
169
171
  *
@@ -4,6 +4,8 @@ import { getCurrentCommandId } from './global-context.js';
4
4
  import { outputDebug } from './output.js';
5
5
  import { zod } from './schema.js';
6
6
  import { AbortSilentError } from './error.js';
7
+ import { isTruthy } from './context/utilities.js';
8
+ import { jsonOutputEnabled } from './environment.js';
7
9
  import { CLI_KIT_VERSION } from '../common/version.js';
8
10
  import { cacheRetrieve, cacheRetrieveOrRepopulate, cacheStore, } from '../../private/node/conf-store.js';
9
11
  import { fetch } from '@shopify/cli-kit/node/http';
@@ -37,10 +39,13 @@ const NotificationsSchema = zod.object({ notifications: zod.array(NotificationSc
37
39
  * Shows notifications to the user if they meet the criteria specified in the notifications.json file.
38
40
  *
39
41
  * @param currentSurfaces - The surfaces present in the current project (usually for app extensions).
42
+ * @param environment - Process environment variables.
40
43
  * @returns - A promise that resolves when the notifications have been shown.
41
44
  */
42
- export async function showNotificationsIfNeeded(currentSurfaces) {
45
+ export async function showNotificationsIfNeeded(currentSurfaces, environment = process.env) {
43
46
  try {
47
+ if (skipNotifications(environment))
48
+ return;
44
49
  const notifications = await getNotifications();
45
50
  const commandId = getCurrentCommandId();
46
51
  const notificationsToShow = filterNotifications(notifications.notifications, commandId, currentSurfaces);
@@ -58,6 +63,9 @@ export async function showNotificationsIfNeeded(currentSurfaces) {
58
63
  await sendErrorToBugsnag(errorMessage, 'unexpected_error');
59
64
  }
60
65
  }
66
+ function skipNotifications(environment) {
67
+ return isTruthy(environment.CI) || isTruthy(environment.SHOPIFY_UNIT_TEST) || jsonOutputEnabled(environment);
68
+ }
61
69
  /**
62
70
  * Renders the first 2 notifications to the user.
63
71
  *
@@ -1 +1 @@
1
- {"version":3,"file":"notifications-system.js","sourceRoot":"","sources":["../../../src/public/node/notifications-system.ts"],"names":[],"mappings":"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","sourcesContent":["import {versionSatisfies} from './node-package-manager.js'\nimport {renderError, renderInfo, renderWarning} from './ui.js'\nimport {getCurrentCommandId} from './global-context.js'\nimport {outputDebug} from './output.js'\nimport {zod} from './schema.js'\nimport {AbortSilentError} from './error.js'\nimport {CLI_KIT_VERSION} from '../common/version.js'\nimport {\n NotificationKey,\n NotificationsKey,\n cacheRetrieve,\n cacheRetrieveOrRepopulate,\n cacheStore,\n} from '../../private/node/conf-store.js'\nimport {fetch} from '@shopify/cli-kit/node/http'\n\nconst URL = 'https://cdn.shopify.com/static/cli/notifications.json'\nconst CACHE_DURATION_IN_MS = 3600 * 1000\n\nfunction url(): string {\n return process.env.SHOPIFY_CLI_NOTIFICATIONS_URL ?? URL\n}\n\nconst NotificationSchema = zod.object({\n id: zod.string(),\n message: zod.string(),\n type: zod.enum(['info', 'warning', 'error']),\n frequency: zod.enum(['always', 'once', 'once_a_day', 'once_a_week']),\n ownerChannel: zod.string(),\n cta: zod\n .object({\n label: zod.string(),\n url: zod.string().url(),\n })\n .optional(),\n title: zod.string().optional(),\n minVersion: zod.string().optional(),\n maxVersion: zod.string().optional(),\n minDate: zod.string().optional(),\n maxDate: zod.string().optional(),\n commands: zod.array(zod.string()).optional(),\n surface: zod.string().optional(),\n})\nexport type Notification = zod.infer<typeof NotificationSchema>\n\nconst NotificationsSchema = zod.object({notifications: zod.array(NotificationSchema)})\nexport type Notifications = zod.infer<typeof NotificationsSchema>\n\n/**\n * Shows notifications to the user if they meet the criteria specified in the notifications.json file.\n *\n * @param currentSurfaces - The surfaces present in the current project (usually for app extensions).\n * @returns - A promise that resolves when the notifications have been shown.\n */\nexport async function showNotificationsIfNeeded(currentSurfaces?: string[]): Promise<void> {\n try {\n const notifications = await getNotifications()\n const commandId = getCurrentCommandId()\n const notificationsToShow = filterNotifications(notifications.notifications, commandId, currentSurfaces)\n outputDebug(`Notifications to show: ${notificationsToShow.length}`)\n await renderNotifications(notificationsToShow)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n if (error.message === 'abort') throw new AbortSilentError()\n const errorMessage = `Error retrieving notifications: ${error.message}`\n outputDebug(errorMessage)\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(errorMessage, 'unexpected_error')\n }\n}\n\n/**\n * Renders the first 2 notifications to the user.\n *\n * @param notifications - The notifications to render.\n */\nasync function renderNotifications(notifications: Notification[]) {\n notifications.slice(0, 2).forEach((notification) => {\n const content = {\n headline: notification.title,\n body: notification.message.replaceAll('\\\\n', '\\n'),\n link: notification.cta,\n }\n switch (notification.type) {\n case 'info': {\n renderInfo(content)\n break\n }\n case 'warning': {\n renderWarning(content)\n break\n }\n case 'error': {\n renderError(content)\n throw new Error('abort')\n }\n }\n cacheStore(`notification-${notification.id}`, new Date().getTime().toString())\n })\n}\n\n/**\n * Get notifications list from cache (refreshed every hour) or fetch it if not present.\n *\n * @returns A Notifications object.\n */\nexport async function getNotifications(): Promise<Notifications> {\n const cacheKey: NotificationsKey = `notifications-${url()}`\n const rawNotifications = await cacheRetrieveOrRepopulate(cacheKey, fetchNotifications, CACHE_DURATION_IN_MS)\n const notifications: object = JSON.parse(rawNotifications)\n return NotificationsSchema.parse(notifications)\n}\n\n/**\n * Fetch notifications from GitHub.\n */\nasync function fetchNotifications(): Promise<string> {\n outputDebug(`No cached notifications found. Fetching them...`)\n const response = await fetch(url(), {signal: AbortSignal.timeout(3 * 1000)})\n if (response.status !== 200) throw new Error(`Failed to fetch notifications: ${response.statusText}`)\n return response.text() as unknown as string\n}\n\n/**\n * Filters notifications based on the version of the CLI.\n *\n * @param notifications - The notifications to filter.\n * @param commandId - The command ID to filter by.\n * @param currentSurfaces - The surfaces present in the current project (usually for app extensions).\n * @param today - The current date.\n * @param currentVersion - The current version of the CLI.\n * @returns - The filtered notifications.\n */\nexport function filterNotifications(\n notifications: Notification[],\n commandId: string,\n currentSurfaces?: string[],\n today: Date = new Date(new Date().setUTCHours(0, 0, 0, 0)),\n currentVersion: string = CLI_KIT_VERSION,\n): Notification[] {\n return notifications\n .filter((notification) => filterByVersion(notification, currentVersion))\n .filter((notifications) => filterByDate(notifications, today))\n .filter((notification) => filterByCommand(notification, commandId))\n .filter((notification) => filterBySurface(notification, commandId, currentSurfaces))\n .filter((notification) => filterByFrequency(notification))\n}\n\n/**\n * Filters notifications based on the version of the CLI.\n *\n * @param notification - The notification to filter.\n * @param currentVersion - The current version of the CLI.\n */\nfunction filterByVersion(notification: Notification, currentVersion: string) {\n const minVersion = !notification.minVersion || versionSatisfies(currentVersion, `>=${notification.minVersion}`)\n const maxVersion = !notification.maxVersion || versionSatisfies(currentVersion, `<=${notification.maxVersion}`)\n return minVersion && maxVersion\n}\n\n/**\n * Filters notifications based on the date.\n *\n * @param notification - The notification to filter.\n * @param today - The current date.\n */\nfunction filterByDate(notification: Notification, today: Date) {\n const minDate = !notification.minDate || new Date(notification.minDate) <= today\n const maxDate = !notification.maxDate || new Date(notification.maxDate) >= today\n return minDate && maxDate\n}\n\n/**\n * Filters notifications based on the command ID.\n *\n * @param notification - The notification to filter.\n * @param commandId - The command ID to filter by.\n * @returns - A boolean indicating whether the notification should be shown.\n */\nfunction filterByCommand(notification: Notification, commandId: string) {\n if (commandId === '') return true\n return !notification.commands || notification.commands.includes(commandId)\n}\n\n/**\n * Filters notifications based on the surface.\n *\n * @param notification - The notification to filter.\n * @param commandId - The command id.\n * @param surfacesFromContext - The surfaces present in the current project (usually for app extensions).\n * @returns - A boolean indicating whether the notification should be shown.\n */\nfunction filterBySurface(notification: Notification, commandId: string, surfacesFromContext?: string[]) {\n const surfaceFromCommand = commandId.split(':')[0] ?? 'all'\n const notificationSurface = notification.surface ?? 'all'\n\n if (surfacesFromContext) return surfacesFromContext.includes(notificationSurface)\n\n return notificationSurface === surfaceFromCommand || notificationSurface === 'all'\n}\n\n/**\n * Filters notifications based on the frequency.\n *\n * @param notification - The notification to filter.\n * @returns - A boolean indicating whether the notification should be shown.\n */\nfunction filterByFrequency(notification: Notification): boolean {\n if (!notification.frequency) return true\n const cacheKey: NotificationKey = `notification-${notification.id}`\n const lastShown = cacheRetrieve(cacheKey)?.value as unknown as string\n if (!lastShown) return true\n\n switch (notification.frequency) {\n case 'always': {\n return true\n }\n case 'once': {\n return false\n }\n case 'once_a_day': {\n return new Date().getTime() - Number(lastShown) > 24 * 3600 * 1000\n }\n case 'once_a_week': {\n return new Date().getTime() - Number(lastShown) > 7 * 24 * 3600 * 1000\n }\n }\n}\n\n/**\n * Returns a string with the filters from a notification, one by line.\n *\n * @param notification - The notification to get the filters from.\n * @returns A string with human-readable filters from the notification.\n */\nexport function stringifyFilters(notification: Notification): string {\n const filters = []\n if (notification.minDate) filters.push(`from ${notification.minDate}`)\n if (notification.maxDate) filters.push(`to ${notification.maxDate}`)\n if (notification.minVersion) filters.push(`from v${notification.minVersion}`)\n if (notification.maxVersion) filters.push(`to v${notification.maxVersion}`)\n if (notification.frequency === 'once') filters.push('show only once')\n if (notification.frequency === 'once_a_day') filters.push('show once a day')\n if (notification.frequency === 'once_a_week') filters.push('show once a week')\n if (notification.surface) filters.push(`surface = ${notification.surface}`)\n if (notification.commands) filters.push(`commands = ${notification.commands.join(', ')}`)\n return filters.join('\\n')\n}\n"]}
1
+ {"version":3,"file":"notifications-system.js","sourceRoot":"","sources":["../../../src/public/node/notifications-system.ts"],"names":[],"mappings":"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","sourcesContent":["import {versionSatisfies} from './node-package-manager.js'\nimport {renderError, renderInfo, renderWarning} from './ui.js'\nimport {getCurrentCommandId} from './global-context.js'\nimport {outputDebug} from './output.js'\nimport {zod} from './schema.js'\nimport {AbortSilentError} from './error.js'\nimport {isTruthy} from './context/utilities.js'\nimport {jsonOutputEnabled} from './environment.js'\nimport {CLI_KIT_VERSION} from '../common/version.js'\nimport {\n NotificationKey,\n NotificationsKey,\n cacheRetrieve,\n cacheRetrieveOrRepopulate,\n cacheStore,\n} from '../../private/node/conf-store.js'\nimport {fetch} from '@shopify/cli-kit/node/http'\n\nconst URL = 'https://cdn.shopify.com/static/cli/notifications.json'\nconst CACHE_DURATION_IN_MS = 3600 * 1000\n\nfunction url(): string {\n return process.env.SHOPIFY_CLI_NOTIFICATIONS_URL ?? URL\n}\n\nconst NotificationSchema = zod.object({\n id: zod.string(),\n message: zod.string(),\n type: zod.enum(['info', 'warning', 'error']),\n frequency: zod.enum(['always', 'once', 'once_a_day', 'once_a_week']),\n ownerChannel: zod.string(),\n cta: zod\n .object({\n label: zod.string(),\n url: zod.string().url(),\n })\n .optional(),\n title: zod.string().optional(),\n minVersion: zod.string().optional(),\n maxVersion: zod.string().optional(),\n minDate: zod.string().optional(),\n maxDate: zod.string().optional(),\n commands: zod.array(zod.string()).optional(),\n surface: zod.string().optional(),\n})\nexport type Notification = zod.infer<typeof NotificationSchema>\n\nconst NotificationsSchema = zod.object({notifications: zod.array(NotificationSchema)})\nexport type Notifications = zod.infer<typeof NotificationsSchema>\n\n/**\n * Shows notifications to the user if they meet the criteria specified in the notifications.json file.\n *\n * @param currentSurfaces - The surfaces present in the current project (usually for app extensions).\n * @param environment - Process environment variables.\n * @returns - A promise that resolves when the notifications have been shown.\n */\nexport async function showNotificationsIfNeeded(\n currentSurfaces?: string[],\n environment: NodeJS.ProcessEnv = process.env,\n): Promise<void> {\n try {\n if (skipNotifications(environment)) return\n\n const notifications = await getNotifications()\n const commandId = getCurrentCommandId()\n const notificationsToShow = filterNotifications(notifications.notifications, commandId, currentSurfaces)\n outputDebug(`Notifications to show: ${notificationsToShow.length}`)\n await renderNotifications(notificationsToShow)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n if (error.message === 'abort') throw new AbortSilentError()\n const errorMessage = `Error retrieving notifications: ${error.message}`\n outputDebug(errorMessage)\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(errorMessage, 'unexpected_error')\n }\n}\n\nfunction skipNotifications(environment: NodeJS.ProcessEnv): boolean {\n return isTruthy(environment.CI) || isTruthy(environment.SHOPIFY_UNIT_TEST) || jsonOutputEnabled(environment)\n}\n\n/**\n * Renders the first 2 notifications to the user.\n *\n * @param notifications - The notifications to render.\n */\nasync function renderNotifications(notifications: Notification[]) {\n notifications.slice(0, 2).forEach((notification) => {\n const content = {\n headline: notification.title,\n body: notification.message.replaceAll('\\\\n', '\\n'),\n link: notification.cta,\n }\n switch (notification.type) {\n case 'info': {\n renderInfo(content)\n break\n }\n case 'warning': {\n renderWarning(content)\n break\n }\n case 'error': {\n renderError(content)\n throw new Error('abort')\n }\n }\n cacheStore(`notification-${notification.id}`, new Date().getTime().toString())\n })\n}\n\n/**\n * Get notifications list from cache (refreshed every hour) or fetch it if not present.\n *\n * @returns A Notifications object.\n */\nexport async function getNotifications(): Promise<Notifications> {\n const cacheKey: NotificationsKey = `notifications-${url()}`\n const rawNotifications = await cacheRetrieveOrRepopulate(cacheKey, fetchNotifications, CACHE_DURATION_IN_MS)\n const notifications: object = JSON.parse(rawNotifications)\n return NotificationsSchema.parse(notifications)\n}\n\n/**\n * Fetch notifications from GitHub.\n */\nasync function fetchNotifications(): Promise<string> {\n outputDebug(`No cached notifications found. Fetching them...`)\n const response = await fetch(url(), {signal: AbortSignal.timeout(3 * 1000)})\n if (response.status !== 200) throw new Error(`Failed to fetch notifications: ${response.statusText}`)\n return response.text() as unknown as string\n}\n\n/**\n * Filters notifications based on the version of the CLI.\n *\n * @param notifications - The notifications to filter.\n * @param commandId - The command ID to filter by.\n * @param currentSurfaces - The surfaces present in the current project (usually for app extensions).\n * @param today - The current date.\n * @param currentVersion - The current version of the CLI.\n * @returns - The filtered notifications.\n */\nexport function filterNotifications(\n notifications: Notification[],\n commandId: string,\n currentSurfaces?: string[],\n today: Date = new Date(new Date().setUTCHours(0, 0, 0, 0)),\n currentVersion: string = CLI_KIT_VERSION,\n): Notification[] {\n return notifications\n .filter((notification) => filterByVersion(notification, currentVersion))\n .filter((notifications) => filterByDate(notifications, today))\n .filter((notification) => filterByCommand(notification, commandId))\n .filter((notification) => filterBySurface(notification, commandId, currentSurfaces))\n .filter((notification) => filterByFrequency(notification))\n}\n\n/**\n * Filters notifications based on the version of the CLI.\n *\n * @param notification - The notification to filter.\n * @param currentVersion - The current version of the CLI.\n */\nfunction filterByVersion(notification: Notification, currentVersion: string) {\n const minVersion = !notification.minVersion || versionSatisfies(currentVersion, `>=${notification.minVersion}`)\n const maxVersion = !notification.maxVersion || versionSatisfies(currentVersion, `<=${notification.maxVersion}`)\n return minVersion && maxVersion\n}\n\n/**\n * Filters notifications based on the date.\n *\n * @param notification - The notification to filter.\n * @param today - The current date.\n */\nfunction filterByDate(notification: Notification, today: Date) {\n const minDate = !notification.minDate || new Date(notification.minDate) <= today\n const maxDate = !notification.maxDate || new Date(notification.maxDate) >= today\n return minDate && maxDate\n}\n\n/**\n * Filters notifications based on the command ID.\n *\n * @param notification - The notification to filter.\n * @param commandId - The command ID to filter by.\n * @returns - A boolean indicating whether the notification should be shown.\n */\nfunction filterByCommand(notification: Notification, commandId: string) {\n if (commandId === '') return true\n return !notification.commands || notification.commands.includes(commandId)\n}\n\n/**\n * Filters notifications based on the surface.\n *\n * @param notification - The notification to filter.\n * @param commandId - The command id.\n * @param surfacesFromContext - The surfaces present in the current project (usually for app extensions).\n * @returns - A boolean indicating whether the notification should be shown.\n */\nfunction filterBySurface(notification: Notification, commandId: string, surfacesFromContext?: string[]) {\n const surfaceFromCommand = commandId.split(':')[0] ?? 'all'\n const notificationSurface = notification.surface ?? 'all'\n\n if (surfacesFromContext) return surfacesFromContext.includes(notificationSurface)\n\n return notificationSurface === surfaceFromCommand || notificationSurface === 'all'\n}\n\n/**\n * Filters notifications based on the frequency.\n *\n * @param notification - The notification to filter.\n * @returns - A boolean indicating whether the notification should be shown.\n */\nfunction filterByFrequency(notification: Notification): boolean {\n if (!notification.frequency) return true\n const cacheKey: NotificationKey = `notification-${notification.id}`\n const lastShown = cacheRetrieve(cacheKey)?.value as unknown as string\n if (!lastShown) return true\n\n switch (notification.frequency) {\n case 'always': {\n return true\n }\n case 'once': {\n return false\n }\n case 'once_a_day': {\n return new Date().getTime() - Number(lastShown) > 24 * 3600 * 1000\n }\n case 'once_a_week': {\n return new Date().getTime() - Number(lastShown) > 7 * 24 * 3600 * 1000\n }\n }\n}\n\n/**\n * Returns a string with the filters from a notification, one by line.\n *\n * @param notification - The notification to get the filters from.\n * @returns A string with human-readable filters from the notification.\n */\nexport function stringifyFilters(notification: Notification): string {\n const filters = []\n if (notification.minDate) filters.push(`from ${notification.minDate}`)\n if (notification.maxDate) filters.push(`to ${notification.maxDate}`)\n if (notification.minVersion) filters.push(`from v${notification.minVersion}`)\n if (notification.maxVersion) filters.push(`to v${notification.maxVersion}`)\n if (notification.frequency === 'once') filters.push('show only once')\n if (notification.frequency === 'once_a_day') filters.push('show once a day')\n if (notification.frequency === 'once_a_week') filters.push('show once a week')\n if (notification.surface) filters.push(`surface = ${notification.surface}`)\n if (notification.commands) filters.push(`commands = ${notification.commands.join(', ')}`)\n return filters.join('\\n')\n}\n"]}
@@ -158,18 +158,14 @@ export declare function consoleError(message: string): void;
158
158
  * @param message - The message to print.
159
159
  */
160
160
  export declare function consoleWarn(message: string): void;
161
- interface OutputWhereAppropriateOptions {
162
- skipUIEvent?: boolean;
163
- }
164
161
  /**
165
162
  * Writes a message to the appropiated logger.
166
163
  *
167
164
  * @param logLevel - The log level to use to determine if the message should be output.
168
165
  * @param logger - The logger to use to output the message.
169
166
  * @param message - The message to output.
170
- * @param options - Additional options.
171
167
  */
172
- export declare function outputWhereAppropriate(logLevel: LogLevel, logger: Logger, message: string, options?: OutputWhereAppropriateOptions): void;
168
+ export declare function outputWhereAppropriate(logLevel: LogLevel, logger: Logger, message: string): void;
173
169
  /**
174
170
  * Returns a message without styles (colors or any ANSI escape codes).
175
171
  *
@@ -192,4 +188,3 @@ export declare function shouldDisplayColors(_process?: NodeJS.Process): boolean;
192
188
  * @returns The formatted message.
193
189
  */
194
190
  export declare function formatSection(title: string, body: string): string;
195
- export {};
@@ -4,7 +4,6 @@ import { currentProcessIsGlobal } from './is-global.js';
4
4
  import colors from './colors.js';
5
5
  import { isTruthy } from './context/utilities.js';
6
6
  import { ColorContentToken, CommandContentToken, ErrorContentToken, HeadingContentToken, ItalicContentToken, JsonContentToken, LinesDiffContentToken, LinkContentToken, PathContentToken, RawContentToken, SubHeadingContentToken, } from '../../private/node/content-tokens.js';
7
- import { recordUIEvent } from '../../private/node/demo-recorder.js';
8
7
  import { tokenItemToString } from '../../private/node/ui/components/TokenizedText.js';
9
8
  import stripAnsi from 'strip-ansi';
10
9
  import { Writable } from 'stream';
@@ -338,9 +337,8 @@ export function consoleWarn(message) {
338
337
  * @param logLevel - The log level to use to determine if the message should be output.
339
338
  * @param logger - The logger to use to output the message.
340
339
  * @param message - The message to output.
341
- * @param options - Additional options.
342
340
  */
343
- export function outputWhereAppropriate(logLevel, logger, message, options = { skipUIEvent: false }) {
341
+ export function outputWhereAppropriate(logLevel, logger, message) {
344
342
  if (shouldOutput(logLevel)) {
345
343
  if (logger instanceof Writable) {
346
344
  logger.write(message);
@@ -348,8 +346,6 @@ export function outputWhereAppropriate(logLevel, logger, message, options = { sk
348
346
  else {
349
347
  logger(message, logLevel);
350
348
  }
351
- if (!options.skipUIEvent)
352
- recordUIEvent({ type: 'output', properties: { content: message } });
353
349
  }
354
350
  }
355
351
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"output.js","sourceRoot":"","sources":["../../../src/public/node/output.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable no-console */\nimport {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 {recordUIEvent} from '../../private/node/demo-recorder.js'\nimport {tokenItemToString} from '../../private/node/ui/components/TokenizedText.js'\nimport stripAnsi from 'strip-ansi'\nimport {Writable} from 'stream'\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 '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 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\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 default:\n return 30\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/no-mutable-exports\nexport let collectedLogs: {[key: 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 // console.log('clearCollectLogs')\n collectedLogs = {}\n // console.log(collectedLogs)\n}\n\n/**\n * Ouputs information to the user.\n * Info messages don't get additional formatting.\n * Note: Info messages are sent through the standard output.\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 = consoleLog): 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 output.\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 = consoleLog): 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 output.\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 = consoleLog): void {\n const message = `${colors.green('✔')} ${stringifyMessage(content)}`\n if (isUnitTest()) collectLog('completed', content)\n outputWhereAppropriate('info', logger, message)\n}\n\n/**\n * Ouputs debug information to the user. By default these output is hidden unless the user calls the CLI with --verbose.\n * Debug messages don't get additional formatting.\n * Note: Debug messages are sent through the standard output.\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 = consoleLog): void {\n if (isUnitTest()) collectLog('debug', content)\n const message = colors.gray(stringifyMessage(content))\n outputWhereAppropriate('debug', logger, `${new Date().toISOString()}: ${message}`)\n}\n\n/**\n * Outputs a warning message to the user.\n * Warning messages receive a special formatting to make them stand out in the console.\n * Note: Warning messages are sent through the standard output.\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 console.log()\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 * Prints a log message in the console.\n *\n * @param message - The message to print.\n */\nexport function consoleLog(message: string): void {\n console.log(withOrWithoutStyle(message))\n}\n\n/**\n * Prints an error message in the console.\n *\n * @param message - The message to print.\n */\nexport function consoleError(message: string): void {\n console.error(withOrWithoutStyle(message))\n}\n\n/**\n * Prints a warning message in the console.\n *\n * @param message - The message to print.\n */\nexport function consoleWarn(message: string): void {\n console.warn(withOrWithoutStyle(message))\n}\n\ninterface OutputWhereAppropriateOptions {\n skipUIEvent?: boolean\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 * @param options - Additional options.\n */\nexport function outputWhereAppropriate(\n logLevel: LogLevel,\n logger: Logger,\n message: string,\n options: OutputWhereAppropriateOptions = {skipUIEvent: false},\n): void {\n if (shouldOutput(logLevel)) {\n if (logger instanceof Writable) {\n logger.write(message)\n } else {\n logger(message, logLevel)\n }\n if (!options.skipUIEvent) recordUIEvent({type: 'output', properties: {content: message}})\n }\n}\n\n/**\n * Returns a colored or uncolored version of a message, depending on the environment.\n *\n * @param message - The message to color or not.\n * @returns The message with or without colors.\n */\nfunction withOrWithoutStyle(message: string): string {\n if (shouldDisplayColors()) {\n return message\n } else {\n return unstyled(message)\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\n/* eslint-enable no-console */\n"]}
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../../../src/public/node/output.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable no-console */\nimport {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 stripAnsi from 'strip-ansi'\nimport {Writable} from 'stream'\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 '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 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\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 default:\n return 30\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/no-mutable-exports\nexport let collectedLogs: {[key: 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 // console.log('clearCollectLogs')\n collectedLogs = {}\n // console.log(collectedLogs)\n}\n\n/**\n * Ouputs information to the user.\n * Info messages don't get additional formatting.\n * Note: Info messages are sent through the standard output.\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 = consoleLog): 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 output.\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 = consoleLog): 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 output.\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 = consoleLog): void {\n const message = `${colors.green('✔')} ${stringifyMessage(content)}`\n if (isUnitTest()) collectLog('completed', content)\n outputWhereAppropriate('info', logger, message)\n}\n\n/**\n * Ouputs debug information to the user. By default these output is hidden unless the user calls the CLI with --verbose.\n * Debug messages don't get additional formatting.\n * Note: Debug messages are sent through the standard output.\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 = consoleLog): void {\n if (isUnitTest()) collectLog('debug', content)\n const message = colors.gray(stringifyMessage(content))\n outputWhereAppropriate('debug', logger, `${new Date().toISOString()}: ${message}`)\n}\n\n/**\n * Outputs a warning message to the user.\n * Warning messages receive a special formatting to make them stand out in the console.\n * Note: Warning messages are sent through the standard output.\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 console.log()\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 * Prints a log message in the console.\n *\n * @param message - The message to print.\n */\nexport function consoleLog(message: string): void {\n console.log(withOrWithoutStyle(message))\n}\n\n/**\n * Prints an error message in the console.\n *\n * @param message - The message to print.\n */\nexport function consoleError(message: string): void {\n console.error(withOrWithoutStyle(message))\n}\n\n/**\n * Prints a warning message in the console.\n *\n * @param message - The message to print.\n */\nexport function consoleWarn(message: string): void {\n console.warn(withOrWithoutStyle(message))\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 colored or uncolored version of a message, depending on the environment.\n *\n * @param message - The message to color or not.\n * @returns The message with or without colors.\n */\nfunction withOrWithoutStyle(message: string): string {\n if (shouldDisplayColors()) {\n return message\n } else {\n return unstyled(message)\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\n/* eslint-enable no-console */\n"]}