@shopify/cli-kit 4.8.5 → 4.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/dist/private/node/analytics.js +5 -3
  2. package/dist/private/node/analytics.js.map +1 -1
  3. package/dist/private/node/api/status-checks.d.ts +7 -0
  4. package/dist/private/node/api/status-checks.js +11 -0
  5. package/dist/private/node/api/status-checks.js.map +1 -0
  6. package/dist/private/node/api.d.ts +15 -0
  7. package/dist/private/node/api.js +28 -0
  8. package/dist/private/node/api.js.map +1 -1
  9. package/dist/private/node/command-event-context.d.ts +29 -0
  10. package/dist/private/node/command-event-context.js +43 -0
  11. package/dist/private/node/command-event-context.js.map +1 -0
  12. package/dist/private/node/command-event-output.d.ts +7 -0
  13. package/dist/private/node/command-event-output.js +16 -0
  14. package/dist/private/node/command-event-output.js.map +1 -0
  15. package/dist/private/node/command-json-schema.d.ts +10 -0
  16. package/dist/private/node/command-json-schema.js +38 -0
  17. package/dist/private/node/command-json-schema.js.map +1 -0
  18. package/dist/private/node/context/agent.d.ts +1 -0
  19. package/dist/private/node/context/agent.js +44 -0
  20. package/dist/private/node/context/agent.js.map +1 -0
  21. package/dist/private/node/json-error.d.ts +23 -0
  22. package/dist/private/node/json-error.js +123 -0
  23. package/dist/private/node/json-error.js.map +1 -0
  24. package/dist/private/node/output.js +3 -1
  25. package/dist/private/node/output.js.map +1 -1
  26. package/dist/private/node/output.test.d.ts +1 -0
  27. package/dist/private/node/output.test.js +74 -0
  28. package/dist/private/node/output.test.js.map +1 -0
  29. package/dist/private/node/session/device-authorization.js +49 -15
  30. package/dist/private/node/session/device-authorization.js.map +1 -1
  31. package/dist/private/node/session/validate.js +9 -22
  32. package/dist/private/node/session/validate.js.map +1 -1
  33. package/dist/private/node/ui/alert.d.ts +1 -1
  34. package/dist/private/node/ui/alert.js +29 -3
  35. package/dist/private/node/ui/alert.js.map +1 -1
  36. package/dist/private/node/ui/components/ConcurrentOutput.d.ts +8 -1
  37. package/dist/private/node/ui/components/ConcurrentOutput.js +54 -0
  38. package/dist/private/node/ui/components/ConcurrentOutput.js.map +1 -1
  39. package/dist/private/node/ui/components/DangerousConfirmationPrompt.js +3 -3
  40. package/dist/private/node/ui/components/DangerousConfirmationPrompt.js.map +1 -1
  41. package/dist/private/node/ui/components/DangerousConfirmationPrompt.test.js +16 -1
  42. package/dist/private/node/ui/components/DangerousConfirmationPrompt.test.js.map +1 -1
  43. package/dist/private/node/ui/components/Prompts/PromptLayout.js +3 -2
  44. package/dist/private/node/ui/components/Prompts/PromptLayout.js.map +1 -1
  45. package/dist/private/node/ui/components/Prompts/PromptLayout.test.js +20 -1
  46. package/dist/private/node/ui/components/Prompts/PromptLayout.test.js.map +1 -1
  47. package/dist/private/node/ui/components/Tasks.d.ts +2 -9
  48. package/dist/private/node/ui/components/Tasks.js +5 -44
  49. package/dist/private/node/ui/components/Tasks.js.map +1 -1
  50. package/dist/private/node/ui/components/TextPrompt.js +3 -3
  51. package/dist/private/node/ui/components/TextPrompt.js.map +1 -1
  52. package/dist/private/node/ui/components/TextPrompt.test.js +15 -1
  53. package/dist/private/node/ui/components/TextPrompt.test.js.map +1 -1
  54. package/dist/private/node/ui/components/token-item.d.ts +2 -0
  55. package/dist/private/node/ui/components/token-item.js +26 -0
  56. package/dist/private/node/ui/components/token-item.js.map +1 -1
  57. package/dist/private/node/ui/hooks/use-async-and-unmount.d.ts +3 -3
  58. package/dist/private/node/ui/hooks/use-async-and-unmount.js +2 -2
  59. package/dist/private/node/ui/hooks/use-async-and-unmount.js.map +1 -1
  60. package/dist/private/node/ui/tasks.d.ts +10 -0
  61. package/dist/private/node/ui/tasks.js +68 -0
  62. package/dist/private/node/ui/tasks.js.map +1 -0
  63. package/dist/public/common/command-events.d.ts +125 -0
  64. package/dist/public/common/command-events.js +54 -0
  65. package/dist/public/common/command-events.js.map +1 -0
  66. package/dist/public/common/json-output-schema.d.ts +10 -0
  67. package/dist/public/common/json-output-schema.js +17 -0
  68. package/dist/public/common/json-output-schema.js.map +1 -0
  69. package/dist/public/common/version.d.ts +1 -1
  70. package/dist/public/common/version.js +1 -1
  71. package/dist/public/common/version.js.map +1 -1
  72. package/dist/public/node/api/admin.js +18 -1
  73. package/dist/public/node/api/admin.js.map +1 -1
  74. package/dist/public/node/api/app-management.d.ts +1 -0
  75. package/dist/public/node/api/app-management.js +4 -0
  76. package/dist/public/node/api/app-management.js.map +1 -1
  77. package/dist/public/node/api/bulk-operations/download-bulk-operation-results.d.ts +3 -3
  78. package/dist/public/node/api/bulk-operations/download-bulk-operation-results.js +5 -3
  79. package/dist/public/node/api/bulk-operations/download-bulk-operation-results.js.map +1 -1
  80. package/dist/public/node/base-command.d.ts +6 -0
  81. package/dist/public/node/base-command.js +34 -5
  82. package/dist/public/node/base-command.js.map +1 -1
  83. package/dist/public/node/cli-launcher.js +20 -2
  84. package/dist/public/node/cli-launcher.js.map +1 -1
  85. package/dist/public/node/cli.d.ts +1 -0
  86. package/dist/public/node/cli.js +2 -0
  87. package/dist/public/node/cli.js.map +1 -1
  88. package/dist/public/node/command-events.d.ts +65 -0
  89. package/dist/public/node/command-events.js +71 -0
  90. package/dist/public/node/command-events.js.map +1 -0
  91. package/dist/public/node/context/local.d.ts +6 -0
  92. package/dist/public/node/context/local.js +10 -1
  93. package/dist/public/node/context/local.js.map +1 -1
  94. package/dist/public/node/custom-oclif-loader.d.ts +6 -0
  95. package/dist/public/node/custom-oclif-loader.js +45 -19
  96. package/dist/public/node/custom-oclif-loader.js.map +1 -1
  97. package/dist/public/node/environment.d.ts +2 -1
  98. package/dist/public/node/environment.js +3 -2
  99. package/dist/public/node/environment.js.map +1 -1
  100. package/dist/public/node/error/index.d.ts +91 -0
  101. package/dist/public/node/error/index.js +266 -0
  102. package/dist/public/node/error/index.js.map +1 -0
  103. package/dist/public/node/error/schema.d.ts +472 -0
  104. package/dist/public/node/error/schema.js +54 -0
  105. package/dist/public/node/error/schema.js.map +1 -0
  106. package/dist/public/node/error/types.d.ts +9 -0
  107. package/dist/public/node/error/types.js +2 -0
  108. package/dist/public/node/error/types.js.map +1 -0
  109. package/dist/public/node/error.d.ts +1 -87
  110. package/dist/public/node/error.js +1 -252
  111. package/dist/public/node/error.js.map +1 -1
  112. package/dist/public/node/fs.d.ts +17 -3
  113. package/dist/public/node/fs.js +7 -5
  114. package/dist/public/node/fs.js.map +1 -1
  115. package/dist/public/node/json-output-schema.d.ts +26 -0
  116. package/dist/public/node/json-output-schema.js +30 -0
  117. package/dist/public/node/json-output-schema.js.map +1 -0
  118. package/dist/public/node/local-storage.d.ts +1 -0
  119. package/dist/public/node/local-storage.js +54 -21
  120. package/dist/public/node/local-storage.js.map +1 -1
  121. package/dist/public/node/monorail.d.ts +3 -1
  122. package/dist/public/node/monorail.js +1 -1
  123. package/dist/public/node/monorail.js.map +1 -1
  124. package/dist/public/node/multiple-installation-warning.d.ts +1 -1
  125. package/dist/public/node/multiple-installation-warning.js +2 -3
  126. package/dist/public/node/multiple-installation-warning.js.map +1 -1
  127. package/dist/public/node/no-input.d.ts +11 -0
  128. package/dist/public/node/no-input.js +19 -0
  129. package/dist/public/node/no-input.js.map +1 -0
  130. package/dist/public/node/output.d.ts +6 -0
  131. package/dist/public/node/output.js +40 -0
  132. package/dist/public/node/output.js.map +1 -1
  133. package/dist/public/node/path.js +3 -1
  134. package/dist/public/node/path.js.map +1 -1
  135. package/dist/public/node/system.d.ts +2 -2
  136. package/dist/public/node/system.js +8 -4
  137. package/dist/public/node/system.js.map +1 -1
  138. package/dist/public/node/testing/output.d.ts +30 -0
  139. package/dist/public/node/testing/output.js +83 -0
  140. package/dist/public/node/testing/output.js.map +1 -1
  141. package/dist/public/node/ui.d.ts +5 -1
  142. package/dist/public/node/ui.js +89 -5
  143. package/dist/public/node/ui.js.map +1 -1
  144. package/dist/public/node/upgrade.js +17 -2
  145. package/dist/public/node/upgrade.js.map +1 -1
  146. package/dist/tsconfig.tsbuildinfo +1 -1
  147. package/package.json +4 -2
@@ -1,7 +1,21 @@
1
1
  import { AbortError, BugError } from './error.js';
2
- import { fileHasWritePermissions, unixFileIsOwnedByCurrentUser } from './fs.js';
3
- import { dirname } from './path.js';
2
+ import { fileExistsSync, fileHasWritePermissions, findPathUpSync, unixFileIsOwnedByCurrentUser } from './fs.js';
3
+ import { dirname, resolvePath } from './path.js';
4
4
  import Config from 'conf';
5
+ import envPaths from 'env-paths';
6
+ function isFileSystemPermissionError(error) {
7
+ if (!(error instanceof Error))
8
+ return false;
9
+ const errorCode = error.code;
10
+ return errorCode === 'EACCES' || errorCode === 'EPERM';
11
+ }
12
+ function configPathFromInitializationError(options, error) {
13
+ if (typeof error.path === 'string') {
14
+ return error.syscall === 'mkdir' ? resolvePath(error.path, 'config.json') : resolvePath(error.path);
15
+ }
16
+ const configDirectory = options.cwd ?? (options.projectName ? envPaths(options.projectName, { suffix: 'nodejs' }).config : undefined);
17
+ return configDirectory ? resolvePath(configDirectory, 'config.json') : undefined;
18
+ }
5
19
  function deserializeJson(value) {
6
20
  // Some Windows editors encode UTF-8 files with a byte order mark, which JSON.parse does not accept.
7
21
  const valueWithoutByteOrderMark = value.replace(/^\uFEFF/, '');
@@ -15,11 +29,21 @@ function deserializeJson(value) {
15
29
  export class LocalStorage {
16
30
  config;
17
31
  constructor(options) {
18
- this.config = new Config({
19
- ...options,
20
- clearInvalidConfig: true,
21
- deserialize: (deserializeJson),
22
- });
32
+ try {
33
+ this.config = new Config({
34
+ ...options,
35
+ clearInvalidConfig: true,
36
+ deserialize: (deserializeJson),
37
+ });
38
+ }
39
+ catch (error) {
40
+ if (!isFileSystemPermissionError(error))
41
+ throw error;
42
+ const configPath = configPathFromInitializationError(options, error);
43
+ if (configPath)
44
+ this.handleError(error, 'initialize', configPath);
45
+ throw new AbortError(`Failed to access local storage (initialize): ${error}`);
46
+ }
23
47
  }
24
48
  /**
25
49
  * Get a value from the local storage.
@@ -93,32 +117,41 @@ export class LocalStorage {
93
117
  *
94
118
  * @param error - The error that occurred.
95
119
  * @param operation - The operation that failed.
120
+ * @param configPath - The local storage configuration file path.
96
121
  * @throws AbortError if the error is permission-related.
97
122
  * @throws BugError if the error is not permission-related.
98
123
  */
99
- handleError(error, operation) {
100
- if (this.isPermissionError()) {
101
- throw new AbortError(`Failed to access local storage (${operation}): ${error}`, this.tryMessage());
124
+ handleError(error, operation, configPath = this.config.path) {
125
+ if (isFileSystemPermissionError(error) || this.isPermissionError(configPath)) {
126
+ throw new AbortError(`Failed to access local storage (${operation}): ${error}`, this.tryMessage(configPath));
102
127
  }
103
128
  else {
104
- throw new BugError(`Unexpected error while accessing local storage at ${this.config.path} (${operation}): ${error}`);
129
+ throw new BugError(`Unexpected error while accessing local storage at ${configPath} (${operation}): ${error}`);
105
130
  }
106
131
  }
107
- isPermissionError() {
108
- const canAccessFile = fileHasWritePermissions(this.config.path);
109
- const canAccessFolder = fileHasWritePermissions(dirname(this.config.path));
110
- const ownsFile = unixFileIsOwnedByCurrentUser(this.config.path);
132
+ isPermissionError(configPath) {
133
+ const canAccessFile = fileHasWritePermissions(configPath);
134
+ const canAccessFolder = fileHasWritePermissions(dirname(configPath));
135
+ const ownsFile = unixFileIsOwnedByCurrentUser(configPath);
111
136
  return !canAccessFile || !canAccessFolder || ownsFile === false;
112
137
  }
113
- tryMessage() {
114
- const ownsFile = unixFileIsOwnedByCurrentUser(this.config.path);
115
- const ownsFolder = unixFileIsOwnedByCurrentUser(dirname(this.config.path));
116
- const message = [`Check that you have write permissions for`, { filePath: this.config.path }];
138
+ tryMessage(configPath) {
139
+ const configDirectory = dirname(configPath);
140
+ const configDirectoryExists = fileExistsSync(configDirectory);
141
+ const permissionsPath = configDirectoryExists
142
+ ? configPath
143
+ : (findPathUpSync('.', { cwd: configDirectory, type: 'directory' }) ?? configDirectory);
144
+ const ownsFile = fileExistsSync(configPath) ? unixFileIsOwnedByCurrentUser(configPath) : undefined;
145
+ const ownershipDirectory = configDirectoryExists ? configDirectory : permissionsPath;
146
+ const ownsFolder = unixFileIsOwnedByCurrentUser(ownershipDirectory);
147
+ const message = [`Check that you have write permissions for`, { filePath: permissionsPath }];
117
148
  if (ownsFile === false || ownsFolder === false) {
118
149
  message.push('- The file is owned by a different user. This typically happens when Shopify CLI was previously run with elevated permissions (e.g., sudo).');
119
150
  }
120
- message.push('\n\nTo resolve this, remove the Shopify CLI preferences folder:');
121
- message.push({ command: `rm -rf ${dirname(this.config.path)}` });
151
+ if (configDirectoryExists) {
152
+ message.push('\n\nTo resolve this, remove the Shopify CLI preferences folder:');
153
+ message.push({ filePath: configDirectory });
154
+ }
122
155
  return message;
123
156
  }
124
157
  }
@@ -1 +1 @@
1
- {"version":3,"file":"local-storage.js","sourceRoot":"","sources":["../../../src/public/node/local-storage.ts"],"names":[],"mappings":"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","sourcesContent":["import {AbortError, BugError} from './error.js'\nimport {fileHasWritePermissions, unixFileIsOwnedByCurrentUser} from './fs.js'\nimport {dirname} from './path.js'\nimport {TokenItem} from './ui.js'\nimport Config from 'conf'\n\nfunction deserializeJson<T>(value: string): T {\n // Some Windows editors encode UTF-8 files with a byte order mark, which JSON.parse does not accept.\n const valueWithoutByteOrderMark = value.replace(/^\\uFEFF/, '')\n return JSON.parse(valueWithoutByteOrderMark) as T\n}\n\n/**\n * A wrapper around the `conf` package that provides a strongly-typed interface\n * for accessing the local storage.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport class LocalStorage<T extends Record<string, any>> {\n private readonly config: Config<T>\n\n constructor(options: {projectName?: string; cwd?: string}) {\n this.config = new Config<T>({\n ...options,\n clearInvalidConfig: true,\n deserialize: deserializeJson<T>,\n })\n }\n\n /**\n * Get a value from the local storage.\n *\n * @param key - The key to get.\n * @returns The value.\n * @throws AbortError if a permission error occurs.\n * @throws BugError if an unexpected error occurs.\n */\n get<TKey extends keyof T>(key: TKey): T[TKey] | undefined {\n try {\n return this.config.get(key)\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n this.handleError(error, 'get')\n }\n }\n\n /**\n * Set a value in the local storage.\n *\n * @param key - The key to set.\n * @param value - The value to set.\n * @throws AbortError if a permission error occurs.\n * @throws BugError if an unexpected error occurs.\n */\n set<TKey extends keyof T>(key: TKey, value?: T[TKey]): void {\n try {\n this.config.set(key, value)\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n this.handleError(error, 'set')\n }\n }\n\n /**\n * Delete a value from the local storage.\n *\n * @param key - The key to delete.\n * @throws AbortError if a permission error occurs.\n * @throws BugError if an unexpected error occurs.\n */\n delete<TKey extends keyof T>(key: TKey): void {\n try {\n this.config.delete(key)\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n this.handleError(error, 'delete')\n }\n }\n\n /**\n * Clear the local storage (delete all values).\n *\n * @throws AbortError if a permission error occurs.\n * @throws BugError if an unexpected error occurs.\n */\n clear(): void {\n try {\n this.config.clear()\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n this.handleError(error, 'clear')\n }\n }\n\n /**\n * Handle errors from config operations.\n * If the error is permission-related, throw an AbortError with helpful hints.\n * Otherwise, throw a BugError.\n *\n * @param error - The error that occurred.\n * @param operation - The operation that failed.\n * @throws AbortError if the error is permission-related.\n * @throws BugError if the error is not permission-related.\n */\n private handleError(error: unknown, operation: string): never {\n if (this.isPermissionError()) {\n throw new AbortError(`Failed to access local storage (${operation}): ${error}`, this.tryMessage())\n } else {\n throw new BugError(\n `Unexpected error while accessing local storage at ${this.config.path} (${operation}): ${error}`,\n )\n }\n }\n\n private isPermissionError(): boolean {\n const canAccessFile = fileHasWritePermissions(this.config.path)\n const canAccessFolder = fileHasWritePermissions(dirname(this.config.path))\n const ownsFile = unixFileIsOwnedByCurrentUser(this.config.path)\n\n return !canAccessFile || !canAccessFolder || ownsFile === false\n }\n\n private tryMessage() {\n const ownsFile = unixFileIsOwnedByCurrentUser(this.config.path)\n const ownsFolder = unixFileIsOwnedByCurrentUser(dirname(this.config.path))\n\n const message: TokenItem = [`Check that you have write permissions for`, {filePath: this.config.path}]\n if (ownsFile === false || ownsFolder === false) {\n message.push(\n '- The file is owned by a different user. This typically happens when Shopify CLI was previously run with elevated permissions (e.g., sudo).',\n )\n }\n\n message.push('\\n\\nTo resolve this, remove the Shopify CLI preferences folder:')\n message.push({command: `rm -rf ${dirname(this.config.path)}`})\n\n return message\n }\n}\n"]}
1
+ {"version":3,"file":"local-storage.js","sourceRoot":"","sources":["../../../src/public/node/local-storage.ts"],"names":[],"mappings":"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","sourcesContent":["import {AbortError, BugError} from './error.js'\nimport {fileExistsSync, fileHasWritePermissions, findPathUpSync, unixFileIsOwnedByCurrentUser} from './fs.js'\nimport {dirname, resolvePath} from './path.js'\nimport {TokenItem} from './ui.js'\nimport Config from 'conf'\nimport envPaths from 'env-paths'\n\nfunction isFileSystemPermissionError(error: unknown): error is NodeJS.ErrnoException {\n if (!(error instanceof Error)) return false\n const errorCode = (error as NodeJS.ErrnoException).code\n return errorCode === 'EACCES' || errorCode === 'EPERM'\n}\n\nfunction configPathFromInitializationError(\n options: {projectName?: string; cwd?: string},\n error: NodeJS.ErrnoException,\n): string | undefined {\n if (typeof error.path === 'string') {\n return error.syscall === 'mkdir' ? resolvePath(error.path, 'config.json') : resolvePath(error.path)\n }\n\n const configDirectory =\n options.cwd ?? (options.projectName ? envPaths(options.projectName, {suffix: 'nodejs'}).config : undefined)\n return configDirectory ? resolvePath(configDirectory, 'config.json') : undefined\n}\n\nfunction deserializeJson<T>(value: string): T {\n // Some Windows editors encode UTF-8 files with a byte order mark, which JSON.parse does not accept.\n const valueWithoutByteOrderMark = value.replace(/^\\uFEFF/, '')\n return JSON.parse(valueWithoutByteOrderMark) as T\n}\n\n/**\n * A wrapper around the `conf` package that provides a strongly-typed interface\n * for accessing the local storage.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport class LocalStorage<T extends Record<string, any>> {\n private readonly config: Config<T>\n\n constructor(options: {projectName?: string; cwd?: string}) {\n try {\n this.config = new Config<T>({\n ...options,\n clearInvalidConfig: true,\n deserialize: deserializeJson<T>,\n })\n } catch (error) {\n if (!isFileSystemPermissionError(error)) throw error\n\n const configPath = configPathFromInitializationError(options, error)\n if (configPath) this.handleError(error, 'initialize', configPath)\n\n throw new AbortError(`Failed to access local storage (initialize): ${error}`)\n }\n }\n\n /**\n * Get a value from the local storage.\n *\n * @param key - The key to get.\n * @returns The value.\n * @throws AbortError if a permission error occurs.\n * @throws BugError if an unexpected error occurs.\n */\n get<TKey extends keyof T>(key: TKey): T[TKey] | undefined {\n try {\n return this.config.get(key)\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n this.handleError(error, 'get')\n }\n }\n\n /**\n * Set a value in the local storage.\n *\n * @param key - The key to set.\n * @param value - The value to set.\n * @throws AbortError if a permission error occurs.\n * @throws BugError if an unexpected error occurs.\n */\n set<TKey extends keyof T>(key: TKey, value?: T[TKey]): void {\n try {\n this.config.set(key, value)\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n this.handleError(error, 'set')\n }\n }\n\n /**\n * Delete a value from the local storage.\n *\n * @param key - The key to delete.\n * @throws AbortError if a permission error occurs.\n * @throws BugError if an unexpected error occurs.\n */\n delete<TKey extends keyof T>(key: TKey): void {\n try {\n this.config.delete(key)\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n this.handleError(error, 'delete')\n }\n }\n\n /**\n * Clear the local storage (delete all values).\n *\n * @throws AbortError if a permission error occurs.\n * @throws BugError if an unexpected error occurs.\n */\n clear(): void {\n try {\n this.config.clear()\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n this.handleError(error, 'clear')\n }\n }\n\n /**\n * Handle errors from config operations.\n * If the error is permission-related, throw an AbortError with helpful hints.\n * Otherwise, throw a BugError.\n *\n * @param error - The error that occurred.\n * @param operation - The operation that failed.\n * @param configPath - The local storage configuration file path.\n * @throws AbortError if the error is permission-related.\n * @throws BugError if the error is not permission-related.\n */\n private handleError(error: unknown, operation: string, configPath = this.config.path): never {\n if (isFileSystemPermissionError(error) || this.isPermissionError(configPath)) {\n throw new AbortError(`Failed to access local storage (${operation}): ${error}`, this.tryMessage(configPath))\n } else {\n throw new BugError(`Unexpected error while accessing local storage at ${configPath} (${operation}): ${error}`)\n }\n }\n\n private isPermissionError(configPath: string): boolean {\n const canAccessFile = fileHasWritePermissions(configPath)\n const canAccessFolder = fileHasWritePermissions(dirname(configPath))\n const ownsFile = unixFileIsOwnedByCurrentUser(configPath)\n\n return !canAccessFile || !canAccessFolder || ownsFile === false\n }\n\n private tryMessage(configPath: string) {\n const configDirectory = dirname(configPath)\n const configDirectoryExists = fileExistsSync(configDirectory)\n const permissionsPath = configDirectoryExists\n ? configPath\n : (findPathUpSync('.', {cwd: configDirectory, type: 'directory'}) ?? configDirectory)\n const ownsFile = fileExistsSync(configPath) ? unixFileIsOwnedByCurrentUser(configPath) : undefined\n const ownershipDirectory = configDirectoryExists ? configDirectory : permissionsPath\n const ownsFolder = unixFileIsOwnedByCurrentUser(ownershipDirectory)\n\n const message: TokenItem = [`Check that you have write permissions for`, {filePath: permissionsPath}]\n if (ownsFile === false || ownsFolder === false) {\n message.push(\n '- The file is owned by a different user. This typically happens when Shopify CLI was previously run with elevated permissions (e.g., sudo).',\n )\n }\n\n if (configDirectoryExists) {\n message.push('\\n\\nTo resolve this, remove the Shopify CLI preferences folder:')\n message.push({filePath: configDirectory})\n }\n\n return message\n }\n}\n"]}
@@ -2,7 +2,7 @@ import { JsonMap } from '../../private/common/json.js';
2
2
  import { DeepRequired } from '../common/ts/deep-required.js';
3
3
  export { DeepRequired };
4
4
  type Optional<T> = T | null;
5
- export declare const MONORAIL_COMMAND_TOPIC = "app_cli3_command/1.28";
5
+ export declare const MONORAIL_COMMAND_TOPIC = "app_cli3_command/1.30";
6
6
  export interface Schemas {
7
7
  [MONORAIL_COMMAND_TOPIC]: {
8
8
  sensitive: {
@@ -77,6 +77,8 @@ export interface Schemas {
77
77
  cmd_app_validate_valid?: Optional<boolean>;
78
78
  cmd_app_validate_issue_count?: Optional<number>;
79
79
  cmd_app_validate_file_count?: Optional<number>;
80
+ num_security_findings?: Optional<number>;
81
+ num_security_findings_resolved?: Optional<number>;
80
82
  cmd_dev_tunnel_type?: Optional<string>;
81
83
  cmd_dev_tunnel_custom_hash?: Optional<string>;
82
84
  cmd_dev_urls_updated?: Optional<boolean>;
@@ -2,7 +2,7 @@ import { fetch } from './http.js';
2
2
  import { outputDebug, outputContent, outputToken } from './output.js';
3
3
  const url = 'https://monorail-edge.shopifysvc.com/v1/produce';
4
4
  // This is the topic name of the main event we log to Monorail, the command tracker
5
- export const MONORAIL_COMMAND_TOPIC = 'app_cli3_command/1.28';
5
+ export const MONORAIL_COMMAND_TOPIC = 'app_cli3_command/1.30';
6
6
  const publishedCommandNames = new Set();
7
7
  /**
8
8
  * Publishes an event to Monorail.
@@ -1 +1 @@
1
- {"version":3,"file":"monorail.js","sourceRoot":"","sources":["../../../src/public/node/monorail.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,WAAW,CAAA;AAC/B,OAAO,EAAC,WAAW,EAAE,aAAa,EAAE,WAAW,EAAC,MAAM,aAAa,CAAA;AAMnE,MAAM,GAAG,GAAG,iDAAiD,CAAA;AAI7D,mFAAmF;AACnF,MAAM,CAAC,MAAM,sBAAsB,GAAG,uBAAuB,CAAA;AAqL7D,MAAM,qBAAqB,GAAG,IAAI,GAAG,EAAU,CAAA;AAE/C;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,QAAmB,EACnB,UAA8B,EAC9B,aAAoC;IAEpC,qHAAqH;IACrH,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,CAAA;IACtC,IAAI,WAAW,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;QACnD,IAAI,qBAAqB,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YAC3C,OAAO,EAAC,IAAI,EAAE,IAAI,EAAC,CAAA;QACrB,CAAC;QACD,qBAAqB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IACxC,CAAC;IAED,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAA;QACxC,MAAM,OAAO,GAAG,EAAC,GAAG,UAAU,EAAE,GAAG,aAAa,EAAC,CAAA;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAC,CAAC,CAAA;QAC3D,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,CAAC,CAAA;QAEzC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAC,EAAE,cAAc,CAAC,CAAA;QAElF,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,WAAW,CAAC,aAAa,CAAA,yBAAyB,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAA;YAC/F,OAAO,EAAC,IAAI,EAAE,IAAI,EAAC,CAAA;QACrB,CAAC;aAAM,CAAC;YACN,WAAW,CAAC,qCAAqC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAA;YACvE,OAAO,EAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,UAAU,EAAC,CAAA;QACtD,CAAC;QACD,qDAAqD;IACvD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,OAAO,GAAG,kCAAkC,CAAA;QAChD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;QAChD,CAAC;QACD,WAAW,CAAC,OAAO,CAAC,CAAA;QACpB,OAAO,EAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAC,CAAA;IACjC,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,eAAe,CAAmB,OAAU;IACnD,MAAM,MAAM,GAAG,EAAC,GAAG,OAAO,EAAC,CAAA;IAC3B,IAAI,SAAS,IAAI,MAAM,EAAE,CAAC;QACxB,MAAM,CAAC,OAAO,GAAG,MAAM,CAAA;IACzB,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,YAAY,GAAG,CAAC,WAAmB,EAAE,EAAE;IAC3C,OAAO;QACL,cAAc,EAAE,iCAAiC;QACjD,qCAAqC,EAAE,WAAW,CAAC,QAAQ,EAAE;QAC7D,kCAAkC,EAAE,WAAW,CAAC,QAAQ,EAAE;KAC3D,CAAA;AACH,CAAC,CAAA","sourcesContent":["import {fetch} from './http.js'\nimport {outputDebug, outputContent, outputToken} from './output.js'\nimport {JsonMap} from '../../private/common/json.js'\nimport {DeepRequired} from '../common/ts/deep-required.js'\n\nexport {DeepRequired}\n\nconst url = 'https://monorail-edge.shopifysvc.com/v1/produce'\n\ntype Optional<T> = T | null\n\n// This is the topic name of the main event we log to Monorail, the command tracker\nexport const MONORAIL_COMMAND_TOPIC = 'app_cli3_command/1.28'\n\nexport interface Schemas {\n [MONORAIL_COMMAND_TOPIC]: {\n sensitive: {\n args: string\n error_message?: Optional<string>\n app_name?: Optional<string>\n metadata?: Optional<string>\n store_fqdn?: Optional<string>\n cmd_all_environment_flags?: Optional<string>\n\n // Dev related commands\n cmd_dev_tunnel_custom?: Optional<string>\n\n // Environment\n env_plugin_installed_all?: Optional<string>\n env_shopify_variables?: Optional<string>\n }\n public: {\n business_platform_id?: Optional<number>\n partner_id?: Optional<number>\n store_id?: Optional<number>\n command: string\n project_type?: Optional<string>\n time_start: number\n time_end: number\n total_time: number\n success: boolean\n api_key?: Optional<string>\n cli_version: string\n uname: string\n ruby_version: string\n node_version: string\n is_employee: boolean\n store_fqdn_hash?: Optional<string>\n store_fqdn_validated?: Optional<boolean>\n store_domain?: Optional<string>\n user_id: string\n\n // Any and all commands\n cmd_all_alias_used?: Optional<string>\n cmd_all_launcher?: Optional<string>\n cmd_all_path_override?: Optional<boolean>\n cmd_all_path_override_hash?: Optional<string>\n cmd_all_plugin?: Optional<string>\n cmd_all_topic?: Optional<string>\n cmd_all_verbose?: Optional<boolean>\n cmd_all_exit?: Optional<string>\n cmd_all_force?: Optional<boolean>\n cmd_all_last_graphql_request_id?: Optional<string>\n\n cmd_all_timing_network_ms?: Optional<number>\n cmd_all_timing_prompts_ms?: Optional<number>\n cmd_all_timing_active_ms?: Optional<number>\n\n // Auto-upgrade\n env_auto_upgrade_enabled?: Optional<boolean>\n env_auto_upgrade_accepted?: Optional<boolean>\n env_auto_upgrade_skipped_reason?: Optional<string>\n env_auto_upgrade_success?: Optional<boolean>\n\n // Any extension related command\n cmd_extensions_binary_from_source?: Optional<boolean>\n\n // Scaffolding related commands\n cmd_scaffold_required_auth?: Optional<boolean>\n cmd_scaffold_template_custom?: Optional<boolean>\n cmd_scaffold_template_flavor?: Optional<string>\n cmd_scaffold_type?: Optional<string>\n cmd_scaffold_type_category?: Optional<string>\n cmd_scaffold_type_gated?: Optional<boolean>\n cmd_scaffold_type_owner?: Optional<string>\n cmd_scaffold_used_prompts_for_type?: Optional<boolean>\n\n // Used in several but not all commands\n cmd_app_dependency_installation_skipped?: Optional<boolean>\n cmd_app_reset_used?: Optional<boolean>\n cmd_app_linked_config_used?: Optional<boolean>\n cmd_app_linked_config_name?: Optional<string>\n cmd_app_linked_config_git_tracked?: Optional<boolean>\n cmd_app_all_configs_any?: Optional<boolean>\n cmd_app_all_configs_clients?: Optional<string>\n cmd_app_linked_config_source?: Optional<string>\n cmd_app_linked_config_uses_cli_managed_urls?: Optional<boolean>\n cmd_app_warning_api_key_deprecation_displayed?: Optional<boolean>\n cmd_app_deployment_mode?: Optional<string>\n cmd_app_validate_json?: Optional<boolean>\n cmd_app_validate_valid?: Optional<boolean>\n cmd_app_validate_issue_count?: Optional<number>\n cmd_app_validate_file_count?: Optional<number>\n\n // Dev related commands\n cmd_dev_tunnel_type?: Optional<string>\n cmd_dev_tunnel_custom_hash?: Optional<string>\n cmd_dev_urls_updated?: Optional<boolean>\n cmd_dev_preview_url_opened?: Optional<boolean>\n cmd_dev_graphiql_opened?: Optional<boolean>\n cmd_dev_dev_preview_toggle_used?: Optional<boolean>\n\n // Create-app related commands\n cmd_create_app_template?: Optional<string>\n cmd_create_app_template_url?: Optional<string>\n\n // Deploy related commands\n cmd_deploy_flag_message_used?: Optional<boolean>\n cmd_deploy_flag_version_used?: Optional<boolean>\n cmd_deploy_flag_source_url_used?: Optional<boolean>\n cmd_deploy_confirm_new_registrations?: Optional<number>\n cmd_deploy_confirm_updated_registrations?: Optional<number>\n cmd_deploy_confirm_removed_registrations?: Optional<number>\n cmd_deploy_confirm_cancelled?: Optional<boolean>\n cmd_deploy_confirm_time_to_complete_ms?: Optional<number>\n cmd_deploy_prompt_upgrade_to_unified_displayed?: Optional<boolean>\n cmd_deploy_prompt_upgrade_to_unified_response?: Optional<string>\n cmd_deploy_confirm_include_config_used?: Optional<boolean>\n cmd_deploy_include_config_used?: Optional<boolean>\n cmd_deploy_config_modules_breakdown?: Optional<string>\n cmd_deploy_config_modules_updated?: Optional<string>\n cmd_deploy_config_modules_added?: Optional<string>\n cmd_deploy_config_modules_deleted?: Optional<string>\n\n // Release related commands\n cmd_release_confirm_cancelled?: Optional<boolean>\n\n // App setup\n app_extensions_any?: Optional<boolean>\n app_extensions_breakdown?: Optional<string>\n app_extensions_count?: Optional<number>\n app_extensions_custom_layout?: Optional<boolean>\n app_extensions_function_any?: Optional<boolean>\n app_extensions_function_count?: Optional<number>\n app_extensions_function_custom_layout?: Optional<boolean>\n app_extensions_theme_any?: Optional<boolean>\n app_extensions_theme_count?: Optional<number>\n app_extensions_theme_custom_layout?: Optional<boolean>\n app_extensions_ui_any?: Optional<boolean>\n app_extensions_ui_count?: Optional<number>\n app_extensions_ui_custom_layout?: Optional<boolean>\n app_name_hash?: Optional<string>\n app_path_hash?: Optional<string>\n app_scopes?: Optional<string>\n app_web_backend_any?: Optional<boolean>\n app_web_backend_count?: Optional<number>\n app_web_custom_layout?: Optional<boolean>\n app_web_framework?: Optional<string>\n app_web_frontend_any?: Optional<boolean>\n app_web_frontend_count?: Optional<number>\n\n // Theme related commands\n cmd_theme_timings?: Optional<string>\n cmd_theme_errors?: Optional<string>\n cmd_theme_retries?: Optional<string>\n cmd_theme_events?: Optional<string>\n\n // Environment\n env_ci?: Optional<boolean>\n env_ci_platform?: Optional<string>\n env_device_id?: Optional<string>\n env_package_manager?: Optional<string>\n env_install_package_manager?: Optional<string>\n env_package_manager_workspaces?: Optional<boolean>\n env_plugin_installed_any_custom?: Optional<boolean>\n env_plugin_installed_shopify?: Optional<string>\n env_shell?: Optional<string>\n env_web_ide?: Optional<string>\n env_cloud?: Optional<string>\n env_is_global?: Optional<boolean>\n env_auth_method?: Optional<string>\n }\n }\n [schemaId: string]: {sensitive: JsonMap; public: JsonMap}\n}\n\n// In reality, we're normally most interested in just this from Schemas, so export it for ease of use.\n// The monorail schema itself has lots of optional values as it must be backwards-compatible. For our schema we want mandatory values instead.\nexport type MonorailEventPublic = DeepRequired<Schemas[typeof MONORAIL_COMMAND_TOPIC]['public']>\nexport type MonorailEventSensitive = Schemas[typeof MONORAIL_COMMAND_TOPIC]['sensitive']\n\ntype MonorailResult = {type: 'ok'} | {type: 'error'; message: string}\n\nconst publishedCommandNames = new Set<string>()\n\n/**\n * Publishes an event to Monorail.\n *\n * @param schemaId - The schema ID of the event to publish.\n * @param publicData - The public data to publish.\n * @param sensitiveData - The sensitive data to publish.\n * @returns A result indicating whether the event was successfully published.\n */\nexport async function publishMonorailEvent<TSchemaId extends keyof Schemas, TPayload extends Schemas[TSchemaId]>(\n schemaId: TSchemaId,\n publicData: TPayload['public'],\n sensitiveData: TPayload['sensitive'],\n): Promise<MonorailResult> {\n // If a command has already been logged, never re-log it. This is to prevent duplication caused by unexpected errors.\n const commandName = publicData.command\n if (commandName && typeof commandName === 'string') {\n if (publishedCommandNames.has(commandName)) {\n return {type: 'ok'}\n }\n publishedCommandNames.add(commandName)\n }\n\n try {\n const currentTime = new Date().getTime()\n const payload = {...publicData, ...sensitiveData}\n const body = JSON.stringify({schema_id: schemaId, payload})\n const headers = buildHeaders(currentTime)\n\n const response = await fetch(url, {method: 'POST', body, headers}, 'non-blocking')\n\n if (response.status === 200) {\n outputDebug(outputContent`Analytics event sent: ${outputToken.json(sanitizePayload(payload))}`)\n return {type: 'ok'}\n } else {\n outputDebug(`Failed to report usage analytics: ${response.statusText}`)\n return {type: 'error', message: response.statusText}\n }\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n let message = 'Failed to report usage analytics'\n if (error instanceof Error) {\n message = message.concat(`: ${error.message}`)\n }\n outputDebug(message)\n return {type: 'error', message}\n }\n}\n\n/**\n * Sanitizies the api_key from the payload and returns a new hash.\n *\n * @param payload - The public and sensitive data.\n * @returns A copy of the payload with the api_key sanitized.\n */\nfunction sanitizePayload<T extends object>(payload: T): T {\n const result = {...payload}\n if ('api_key' in result) {\n result.api_key = '****'\n }\n\n return result\n}\n\nconst buildHeaders = (currentTime: number) => {\n return {\n 'Content-Type': 'application/json; charset=utf-8',\n 'X-Monorail-Edge-Event-Created-At-Ms': currentTime.toString(),\n 'X-Monorail-Edge-Event-Sent-At-Ms': currentTime.toString(),\n }\n}\n"]}
1
+ {"version":3,"file":"monorail.js","sourceRoot":"","sources":["../../../src/public/node/monorail.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,WAAW,CAAA;AAC/B,OAAO,EAAC,WAAW,EAAE,aAAa,EAAE,WAAW,EAAC,MAAM,aAAa,CAAA;AAMnE,MAAM,GAAG,GAAG,iDAAiD,CAAA;AAI7D,mFAAmF;AACnF,MAAM,CAAC,MAAM,sBAAsB,GAAG,uBAAuB,CAAA;AAyL7D,MAAM,qBAAqB,GAAG,IAAI,GAAG,EAAU,CAAA;AAE/C;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,QAAmB,EACnB,UAA8B,EAC9B,aAAoC;IAEpC,qHAAqH;IACrH,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,CAAA;IACtC,IAAI,WAAW,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;QACnD,IAAI,qBAAqB,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YAC3C,OAAO,EAAC,IAAI,EAAE,IAAI,EAAC,CAAA;QACrB,CAAC;QACD,qBAAqB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IACxC,CAAC;IAED,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAA;QACxC,MAAM,OAAO,GAAG,EAAC,GAAG,UAAU,EAAE,GAAG,aAAa,EAAC,CAAA;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAC,CAAC,CAAA;QAC3D,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,CAAC,CAAA;QAEzC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAC,EAAE,cAAc,CAAC,CAAA;QAElF,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,WAAW,CAAC,aAAa,CAAA,yBAAyB,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAA;YAC/F,OAAO,EAAC,IAAI,EAAE,IAAI,EAAC,CAAA;QACrB,CAAC;aAAM,CAAC;YACN,WAAW,CAAC,qCAAqC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAA;YACvE,OAAO,EAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,UAAU,EAAC,CAAA;QACtD,CAAC;QACD,qDAAqD;IACvD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,OAAO,GAAG,kCAAkC,CAAA;QAChD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;QAChD,CAAC;QACD,WAAW,CAAC,OAAO,CAAC,CAAA;QACpB,OAAO,EAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAC,CAAA;IACjC,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,eAAe,CAAmB,OAAU;IACnD,MAAM,MAAM,GAAG,EAAC,GAAG,OAAO,EAAC,CAAA;IAC3B,IAAI,SAAS,IAAI,MAAM,EAAE,CAAC;QACxB,MAAM,CAAC,OAAO,GAAG,MAAM,CAAA;IACzB,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,YAAY,GAAG,CAAC,WAAmB,EAAE,EAAE;IAC3C,OAAO;QACL,cAAc,EAAE,iCAAiC;QACjD,qCAAqC,EAAE,WAAW,CAAC,QAAQ,EAAE;QAC7D,kCAAkC,EAAE,WAAW,CAAC,QAAQ,EAAE;KAC3D,CAAA;AACH,CAAC,CAAA","sourcesContent":["import {fetch} from './http.js'\nimport {outputDebug, outputContent, outputToken} from './output.js'\nimport {JsonMap} from '../../private/common/json.js'\nimport {DeepRequired} from '../common/ts/deep-required.js'\n\nexport {DeepRequired}\n\nconst url = 'https://monorail-edge.shopifysvc.com/v1/produce'\n\ntype Optional<T> = T | null\n\n// This is the topic name of the main event we log to Monorail, the command tracker\nexport const MONORAIL_COMMAND_TOPIC = 'app_cli3_command/1.30'\n\nexport interface Schemas {\n [MONORAIL_COMMAND_TOPIC]: {\n sensitive: {\n args: string\n error_message?: Optional<string>\n app_name?: Optional<string>\n metadata?: Optional<string>\n store_fqdn?: Optional<string>\n cmd_all_environment_flags?: Optional<string>\n\n // Dev related commands\n cmd_dev_tunnel_custom?: Optional<string>\n\n // Environment\n env_plugin_installed_all?: Optional<string>\n env_shopify_variables?: Optional<string>\n }\n public: {\n business_platform_id?: Optional<number>\n partner_id?: Optional<number>\n store_id?: Optional<number>\n command: string\n project_type?: Optional<string>\n time_start: number\n time_end: number\n total_time: number\n success: boolean\n api_key?: Optional<string>\n cli_version: string\n uname: string\n ruby_version: string\n node_version: string\n is_employee: boolean\n store_fqdn_hash?: Optional<string>\n store_fqdn_validated?: Optional<boolean>\n store_domain?: Optional<string>\n user_id: string\n\n // Any and all commands\n cmd_all_alias_used?: Optional<string>\n cmd_all_launcher?: Optional<string>\n cmd_all_path_override?: Optional<boolean>\n cmd_all_path_override_hash?: Optional<string>\n cmd_all_plugin?: Optional<string>\n cmd_all_topic?: Optional<string>\n cmd_all_verbose?: Optional<boolean>\n cmd_all_exit?: Optional<string>\n cmd_all_force?: Optional<boolean>\n cmd_all_last_graphql_request_id?: Optional<string>\n\n cmd_all_timing_network_ms?: Optional<number>\n cmd_all_timing_prompts_ms?: Optional<number>\n cmd_all_timing_active_ms?: Optional<number>\n\n // Auto-upgrade\n env_auto_upgrade_enabled?: Optional<boolean>\n env_auto_upgrade_accepted?: Optional<boolean>\n env_auto_upgrade_skipped_reason?: Optional<string>\n env_auto_upgrade_success?: Optional<boolean>\n\n // Any extension related command\n cmd_extensions_binary_from_source?: Optional<boolean>\n\n // Scaffolding related commands\n cmd_scaffold_required_auth?: Optional<boolean>\n cmd_scaffold_template_custom?: Optional<boolean>\n cmd_scaffold_template_flavor?: Optional<string>\n cmd_scaffold_type?: Optional<string>\n cmd_scaffold_type_category?: Optional<string>\n cmd_scaffold_type_gated?: Optional<boolean>\n cmd_scaffold_type_owner?: Optional<string>\n cmd_scaffold_used_prompts_for_type?: Optional<boolean>\n\n // Used in several but not all commands\n cmd_app_dependency_installation_skipped?: Optional<boolean>\n cmd_app_reset_used?: Optional<boolean>\n cmd_app_linked_config_used?: Optional<boolean>\n cmd_app_linked_config_name?: Optional<string>\n cmd_app_linked_config_git_tracked?: Optional<boolean>\n cmd_app_all_configs_any?: Optional<boolean>\n cmd_app_all_configs_clients?: Optional<string>\n cmd_app_linked_config_source?: Optional<string>\n cmd_app_linked_config_uses_cli_managed_urls?: Optional<boolean>\n cmd_app_warning_api_key_deprecation_displayed?: Optional<boolean>\n cmd_app_deployment_mode?: Optional<string>\n cmd_app_validate_json?: Optional<boolean>\n cmd_app_validate_valid?: Optional<boolean>\n cmd_app_validate_issue_count?: Optional<number>\n cmd_app_validate_file_count?: Optional<number>\n\n // app security commands\n num_security_findings?: Optional<number>\n num_security_findings_resolved?: Optional<number>\n\n // Dev related commands\n cmd_dev_tunnel_type?: Optional<string>\n cmd_dev_tunnel_custom_hash?: Optional<string>\n cmd_dev_urls_updated?: Optional<boolean>\n cmd_dev_preview_url_opened?: Optional<boolean>\n cmd_dev_graphiql_opened?: Optional<boolean>\n cmd_dev_dev_preview_toggle_used?: Optional<boolean>\n\n // Create-app related commands\n cmd_create_app_template?: Optional<string>\n cmd_create_app_template_url?: Optional<string>\n\n // Deploy related commands\n cmd_deploy_flag_message_used?: Optional<boolean>\n cmd_deploy_flag_version_used?: Optional<boolean>\n cmd_deploy_flag_source_url_used?: Optional<boolean>\n cmd_deploy_confirm_new_registrations?: Optional<number>\n cmd_deploy_confirm_updated_registrations?: Optional<number>\n cmd_deploy_confirm_removed_registrations?: Optional<number>\n cmd_deploy_confirm_cancelled?: Optional<boolean>\n cmd_deploy_confirm_time_to_complete_ms?: Optional<number>\n cmd_deploy_prompt_upgrade_to_unified_displayed?: Optional<boolean>\n cmd_deploy_prompt_upgrade_to_unified_response?: Optional<string>\n cmd_deploy_confirm_include_config_used?: Optional<boolean>\n cmd_deploy_include_config_used?: Optional<boolean>\n cmd_deploy_config_modules_breakdown?: Optional<string>\n cmd_deploy_config_modules_updated?: Optional<string>\n cmd_deploy_config_modules_added?: Optional<string>\n cmd_deploy_config_modules_deleted?: Optional<string>\n\n // Release related commands\n cmd_release_confirm_cancelled?: Optional<boolean>\n\n // App setup\n app_extensions_any?: Optional<boolean>\n app_extensions_breakdown?: Optional<string>\n app_extensions_count?: Optional<number>\n app_extensions_custom_layout?: Optional<boolean>\n app_extensions_function_any?: Optional<boolean>\n app_extensions_function_count?: Optional<number>\n app_extensions_function_custom_layout?: Optional<boolean>\n app_extensions_theme_any?: Optional<boolean>\n app_extensions_theme_count?: Optional<number>\n app_extensions_theme_custom_layout?: Optional<boolean>\n app_extensions_ui_any?: Optional<boolean>\n app_extensions_ui_count?: Optional<number>\n app_extensions_ui_custom_layout?: Optional<boolean>\n app_name_hash?: Optional<string>\n app_path_hash?: Optional<string>\n app_scopes?: Optional<string>\n app_web_backend_any?: Optional<boolean>\n app_web_backend_count?: Optional<number>\n app_web_custom_layout?: Optional<boolean>\n app_web_framework?: Optional<string>\n app_web_frontend_any?: Optional<boolean>\n app_web_frontend_count?: Optional<number>\n\n // Theme related commands\n cmd_theme_timings?: Optional<string>\n cmd_theme_errors?: Optional<string>\n cmd_theme_retries?: Optional<string>\n cmd_theme_events?: Optional<string>\n\n // Environment\n env_ci?: Optional<boolean>\n env_ci_platform?: Optional<string>\n env_device_id?: Optional<string>\n env_package_manager?: Optional<string>\n env_install_package_manager?: Optional<string>\n env_package_manager_workspaces?: Optional<boolean>\n env_plugin_installed_any_custom?: Optional<boolean>\n env_plugin_installed_shopify?: Optional<string>\n env_shell?: Optional<string>\n env_web_ide?: Optional<string>\n env_cloud?: Optional<string>\n env_is_global?: Optional<boolean>\n env_auth_method?: Optional<string>\n }\n }\n [schemaId: string]: {sensitive: JsonMap; public: JsonMap}\n}\n\n// In reality, we're normally most interested in just this from Schemas, so export it for ease of use.\n// The monorail schema itself has lots of optional values as it must be backwards-compatible. For our schema we want mandatory values instead.\nexport type MonorailEventPublic = DeepRequired<Schemas[typeof MONORAIL_COMMAND_TOPIC]['public']>\nexport type MonorailEventSensitive = Schemas[typeof MONORAIL_COMMAND_TOPIC]['sensitive']\n\ntype MonorailResult = {type: 'ok'} | {type: 'error'; message: string}\n\nconst publishedCommandNames = new Set<string>()\n\n/**\n * Publishes an event to Monorail.\n *\n * @param schemaId - The schema ID of the event to publish.\n * @param publicData - The public data to publish.\n * @param sensitiveData - The sensitive data to publish.\n * @returns A result indicating whether the event was successfully published.\n */\nexport async function publishMonorailEvent<TSchemaId extends keyof Schemas, TPayload extends Schemas[TSchemaId]>(\n schemaId: TSchemaId,\n publicData: TPayload['public'],\n sensitiveData: TPayload['sensitive'],\n): Promise<MonorailResult> {\n // If a command has already been logged, never re-log it. This is to prevent duplication caused by unexpected errors.\n const commandName = publicData.command\n if (commandName && typeof commandName === 'string') {\n if (publishedCommandNames.has(commandName)) {\n return {type: 'ok'}\n }\n publishedCommandNames.add(commandName)\n }\n\n try {\n const currentTime = new Date().getTime()\n const payload = {...publicData, ...sensitiveData}\n const body = JSON.stringify({schema_id: schemaId, payload})\n const headers = buildHeaders(currentTime)\n\n const response = await fetch(url, {method: 'POST', body, headers}, 'non-blocking')\n\n if (response.status === 200) {\n outputDebug(outputContent`Analytics event sent: ${outputToken.json(sanitizePayload(payload))}`)\n return {type: 'ok'}\n } else {\n outputDebug(`Failed to report usage analytics: ${response.statusText}`)\n return {type: 'error', message: response.statusText}\n }\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n let message = 'Failed to report usage analytics'\n if (error instanceof Error) {\n message = message.concat(`: ${error.message}`)\n }\n outputDebug(message)\n return {type: 'error', message}\n }\n}\n\n/**\n * Sanitizies the api_key from the payload and returns a new hash.\n *\n * @param payload - The public and sensitive data.\n * @returns A copy of the payload with the api_key sanitized.\n */\nfunction sanitizePayload<T extends object>(payload: T): T {\n const result = {...payload}\n if ('api_key' in result) {\n result.api_key = '****'\n }\n\n return result\n}\n\nconst buildHeaders = (currentTime: number) => {\n return {\n 'Content-Type': 'application/json; charset=utf-8',\n 'X-Monorail-Edge-Event-Created-At-Ms': currentTime.toString(),\n 'X-Monorail-Edge-Event-Sent-At-Ms': currentTime.toString(),\n }\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Shows a warning if there are two Shopify CLI installations found (global and local).
3
- * Won't show anything if the user included the --json flag.
3
+ * Emits a diagnostic on stderr in JSON mode.
4
4
  *
5
5
  * @param directory - The directory of the project.
6
6
  * @param dependencies - The dependencies of the project.
@@ -1,4 +1,3 @@
1
- import { jsonOutputEnabled } from './environment.js';
2
1
  import { currentProcessIsGlobal } from './is-global.js';
3
2
  import { renderInfo } from './ui.js';
4
3
  import { globalCLIVersion, localCLIVersion } from './version.js';
@@ -6,7 +5,7 @@ import { CLI_KIT_VERSION } from '../common/version.js';
6
5
  import { runAtMinimumInterval } from '../../private/node/conf-store.js';
7
6
  /**
8
7
  * Shows a warning if there are two Shopify CLI installations found (global and local).
9
- * Won't show anything if the user included the --json flag.
8
+ * Emits a diagnostic on stderr in JSON mode.
10
9
  *
11
10
  * @param directory - The directory of the project.
12
11
  * @param dependencies - The dependencies of the project.
@@ -14,7 +13,7 @@ import { runAtMinimumInterval } from '../../private/node/conf-store.js';
14
13
  export async function showMultipleCLIWarningIfNeeded(directory, dependencies) {
15
14
  // Show the warning only once per day
16
15
  await runAtMinimumInterval('warn-on-multiple-versions', { days: 1 }, async () => {
17
- if (!dependencies['@shopify/cli'] || jsonOutputEnabled())
16
+ if (!dependencies['@shopify/cli'])
18
17
  return;
19
18
  const isGlobal = currentProcessIsGlobal();
20
19
  // If running globally, use the current CLI version, otherwise fetch the global CLI version
@@ -1 +1 @@
1
- {"version":3,"file":"multiple-installation-warning.js","sourceRoot":"","sources":["../../../src/public/node/multiple-installation-warning.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,iBAAiB,EAAC,MAAM,kBAAkB,CAAA;AAClD,OAAO,EAAC,sBAAsB,EAAC,MAAM,gBAAgB,CAAA;AACrD,OAAO,EAAC,UAAU,EAAC,MAAM,SAAS,CAAA;AAClC,OAAO,EAAC,gBAAgB,EAAE,eAAe,EAAC,MAAM,cAAc,CAAA;AAC9D,OAAO,EAAC,eAAe,EAAC,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAC,oBAAoB,EAAC,MAAM,kCAAkC,CAAA;AAErE;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAClD,SAAiB,EACjB,YAAoC;IAEpC,qCAAqC;IACrC,MAAM,oBAAoB,CAAC,2BAA2B,EAAE,EAAC,IAAI,EAAE,CAAC,EAAC,EAAE,KAAK,IAAI,EAAE;QAC5E,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,IAAI,iBAAiB,EAAE;YAAE,OAAM;QAEhE,MAAM,QAAQ,GAAG,sBAAsB,EAAE,CAAA;QAEzC,2FAA2F;QAC3F,gDAAgD;QAChD,MAAM,aAAa,GAAG,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,gBAAgB,EAAE,CAAA;QAC3E,IAAI,CAAC,aAAa;YAAE,OAAM;QAE1B,gGAAgG;QAChG,+CAA+C;QAC/C,MAAM,YAAY,GAAG,QAAQ,CAAC,CAAC,CAAC,MAAM,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,eAAe,CAAA;QAClF,IAAI,CAAC,YAAY;YAAE,OAAM;QAEzB,MAAM,mBAAmB,GAAG,QAAQ,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,kBAAkB,CAAA;QAEjF,MAAM,cAAc,GAAG;YACrB,QAAQ,EAAE,+CAA+C,mBAAmB,EAAE;YAC9E,IAAI,EAAE;gBACJ,2BAA2B,aAAa,8BAA8B,YAAY;6JACmE;aACtJ;YACD,IAAI,EAAE;gBACJ,KAAK,EAAE,gCAAgC;gBACvC,GAAG,EAAE,oGAAoG;aAC1G;SACF,CAAA;QACD,UAAU,CAAC,cAAc,CAAC,CAAA;IAC5B,CAAC,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import {jsonOutputEnabled} from './environment.js'\nimport {currentProcessIsGlobal} from './is-global.js'\nimport {renderInfo} from './ui.js'\nimport {globalCLIVersion, localCLIVersion} from './version.js'\nimport {CLI_KIT_VERSION} from '../common/version.js'\nimport {runAtMinimumInterval} from '../../private/node/conf-store.js'\n\n/**\n * Shows a warning if there are two Shopify CLI installations found (global and local).\n * Won't show anything if the user included the --json flag.\n *\n * @param directory - The directory of the project.\n * @param dependencies - The dependencies of the project.\n */\nexport async function showMultipleCLIWarningIfNeeded(\n directory: string,\n dependencies: Record<string, string>,\n): Promise<void> {\n // Show the warning only once per day\n await runAtMinimumInterval('warn-on-multiple-versions', {days: 1}, async () => {\n if (!dependencies['@shopify/cli'] || jsonOutputEnabled()) return\n\n const isGlobal = currentProcessIsGlobal()\n\n // If running globally, use the current CLI version, otherwise fetch the global CLI version\n // Exit early if we can't get the global version\n const globalVersion = isGlobal ? CLI_KIT_VERSION : await globalCLIVersion()\n if (!globalVersion) return\n\n // If running globally, fetch the local version from npm list, otherwise use current CLI version\n // Exit early if we can't get the local version\n const localVersion = isGlobal ? await localCLIVersion(directory) : CLI_KIT_VERSION\n if (!localVersion) return\n\n const currentInstallation = isGlobal ? 'global installation' : 'local dependency'\n\n const warningContent = {\n headline: `Two Shopify CLI installations found – using ${currentInstallation}`,\n body: [\n `A global installation (v${globalVersion}) and a local dependency (v${localVersion}) were detected.\nWe recommend removing the @shopify/cli and @shopify/app dependencies from your package.json, unless you want to use different versions across multiple apps.`,\n ],\n link: {\n label: 'See Shopify CLI documentation.',\n url: 'https://shopify.dev/docs/apps/build/cli-for-apps#switch-to-a-global-executable-or-local-dependency',\n },\n }\n renderInfo(warningContent)\n })\n}\n"]}
1
+ {"version":3,"file":"multiple-installation-warning.js","sourceRoot":"","sources":["../../../src/public/node/multiple-installation-warning.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,sBAAsB,EAAC,MAAM,gBAAgB,CAAA;AACrD,OAAO,EAAC,UAAU,EAAC,MAAM,SAAS,CAAA;AAClC,OAAO,EAAC,gBAAgB,EAAE,eAAe,EAAC,MAAM,cAAc,CAAA;AAC9D,OAAO,EAAC,eAAe,EAAC,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAC,oBAAoB,EAAC,MAAM,kCAAkC,CAAA;AAErE;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAClD,SAAiB,EACjB,YAAoC;IAEpC,qCAAqC;IACrC,MAAM,oBAAoB,CAAC,2BAA2B,EAAE,EAAC,IAAI,EAAE,CAAC,EAAC,EAAE,KAAK,IAAI,EAAE;QAC5E,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC;YAAE,OAAM;QAEzC,MAAM,QAAQ,GAAG,sBAAsB,EAAE,CAAA;QAEzC,2FAA2F;QAC3F,gDAAgD;QAChD,MAAM,aAAa,GAAG,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,gBAAgB,EAAE,CAAA;QAC3E,IAAI,CAAC,aAAa;YAAE,OAAM;QAE1B,gGAAgG;QAChG,+CAA+C;QAC/C,MAAM,YAAY,GAAG,QAAQ,CAAC,CAAC,CAAC,MAAM,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,eAAe,CAAA;QAClF,IAAI,CAAC,YAAY;YAAE,OAAM;QAEzB,MAAM,mBAAmB,GAAG,QAAQ,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,kBAAkB,CAAA;QAEjF,MAAM,cAAc,GAAG;YACrB,QAAQ,EAAE,+CAA+C,mBAAmB,EAAE;YAC9E,IAAI,EAAE;gBACJ,2BAA2B,aAAa,8BAA8B,YAAY;6JACmE;aACtJ;YACD,IAAI,EAAE;gBACJ,KAAK,EAAE,gCAAgC;gBACvC,GAAG,EAAE,oGAAoG;aAC1G;SACF,CAAA;QACD,UAAU,CAAC,cAAc,CAAC,CAAA;IAC5B,CAAC,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import {currentProcessIsGlobal} from './is-global.js'\nimport {renderInfo} from './ui.js'\nimport {globalCLIVersion, localCLIVersion} from './version.js'\nimport {CLI_KIT_VERSION} from '../common/version.js'\nimport {runAtMinimumInterval} from '../../private/node/conf-store.js'\n\n/**\n * Shows a warning if there are two Shopify CLI installations found (global and local).\n * Emits a diagnostic on stderr in JSON mode.\n *\n * @param directory - The directory of the project.\n * @param dependencies - The dependencies of the project.\n */\nexport async function showMultipleCLIWarningIfNeeded(\n directory: string,\n dependencies: Record<string, string>,\n): Promise<void> {\n // Show the warning only once per day\n await runAtMinimumInterval('warn-on-multiple-versions', {days: 1}, async () => {\n if (!dependencies['@shopify/cli']) return\n\n const isGlobal = currentProcessIsGlobal()\n\n // If running globally, use the current CLI version, otherwise fetch the global CLI version\n // Exit early if we can't get the global version\n const globalVersion = isGlobal ? CLI_KIT_VERSION : await globalCLIVersion()\n if (!globalVersion) return\n\n // If running globally, fetch the local version from npm list, otherwise use current CLI version\n // Exit early if we can't get the local version\n const localVersion = isGlobal ? await localCLIVersion(directory) : CLI_KIT_VERSION\n if (!localVersion) return\n\n const currentInstallation = isGlobal ? 'global installation' : 'local dependency'\n\n const warningContent = {\n headline: `Two Shopify CLI installations found – using ${currentInstallation}`,\n body: [\n `A global installation (v${globalVersion}) and a local dependency (v${localVersion}) were detected.\nWe recommend removing the @shopify/cli and @shopify/app dependencies from your package.json, unless you want to use different versions across multiple apps.`,\n ],\n link: {\n label: 'See Shopify CLI documentation.',\n url: 'https://shopify.dev/docs/apps/build/cli-for-apps#switch-to-a-global-executable-or-local-dependency',\n },\n }\n renderInfo(warningContent)\n })\n}\n"]}
@@ -0,0 +1,11 @@
1
+ export declare const noInputFlag: {
2
+ 'no-input': import("@oclif/core/interfaces").BooleanFlag<boolean>;
3
+ };
4
+ /**
5
+ * Returns whether the current process explicitly disabled user input.
6
+ *
7
+ * @param argv - Process arguments to inspect.
8
+ * @param environment - Environment variables to inspect.
9
+ * @returns True when `--no-input` is active.
10
+ */
11
+ export declare function isInputDisabled(argv?: string[], environment?: NodeJS.ProcessEnv): boolean;
@@ -0,0 +1,19 @@
1
+ import { isTruthy } from './context/utilities.js';
2
+ import { Flags } from '@oclif/core';
3
+ export const noInputFlag = {
4
+ 'no-input': Flags.boolean({
5
+ description: 'Disable interactive prompts and browser authentication.',
6
+ env: 'SHOPIFY_FLAG_NO_INPUT',
7
+ }),
8
+ };
9
+ /**
10
+ * Returns whether the current process explicitly disabled user input.
11
+ *
12
+ * @param argv - Process arguments to inspect.
13
+ * @param environment - Environment variables to inspect.
14
+ * @returns True when `--no-input` is active.
15
+ */
16
+ export function isInputDisabled(argv = process.argv, environment = process.env) {
17
+ return argv.includes('--no-input') || isTruthy(environment.SHOPIFY_FLAG_NO_INPUT);
18
+ }
19
+ //# sourceMappingURL=no-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-input.js","sourceRoot":"","sources":["../../../src/public/node/no-input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,wBAAwB,CAAA;AAC/C,OAAO,EAAC,KAAK,EAAC,MAAM,aAAa,CAAA;AAEjC,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,UAAU,EAAE,KAAK,CAAC,OAAO,CAAC;QACxB,WAAW,EAAE,yDAAyD;QACtE,GAAG,EAAE,uBAAuB;KAC7B,CAAC;CACH,CAAA;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,OAAiB,OAAO,CAAC,IAAI,EAAE,cAAiC,OAAO,CAAC,GAAG;IACzG,OAAO,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,QAAQ,CAAC,WAAW,CAAC,qBAAqB,CAAC,CAAA;AACnF,CAAC","sourcesContent":["import {isTruthy} from './context/utilities.js'\nimport {Flags} from '@oclif/core'\n\nexport const noInputFlag = {\n 'no-input': Flags.boolean({\n description: 'Disable interactive prompts and browser authentication.',\n env: 'SHOPIFY_FLAG_NO_INPUT',\n }),\n}\n\n/**\n * Returns whether the current process explicitly disabled user input.\n *\n * @param argv - Process arguments to inspect.\n * @param environment - Environment variables to inspect.\n * @returns True when `--no-input` is active.\n */\nexport function isInputDisabled(argv: string[] = process.argv, environment: NodeJS.ProcessEnv = process.env): boolean {\n return argv.includes('--no-input') || isTruthy(environment.SHOPIFY_FLAG_NO_INPUT)\n}\n"]}
@@ -68,6 +68,12 @@ export declare const clearCollectedLogs: () => void;
68
68
  * @param content - The content to be output to the user.
69
69
  */
70
70
  export declare function outputResult(content: OutputMessage): void;
71
+ /**
72
+ * Waits for queued stdout writes to reach their destination before the process exits.
73
+ *
74
+ * @returns A promise that resolves when stdout has flushed.
75
+ */
76
+ export declare function flushStdout(): Promise<void>;
71
77
  /**
72
78
  * Logs information at the info level.
73
79
  * Info messages don't get additional formatting.
@@ -4,6 +4,7 @@ import colors from './colors.js';
4
4
  import { isTruthy } from './context/utilities.js';
5
5
  import { ColorContentToken, CommandContentToken, ErrorContentToken, HeadingContentToken, ItalicContentToken, JsonContentToken, LinesDiffContentToken, LinkContentToken, PathContentToken, RawContentToken, SubHeadingContentToken, } from '../../private/node/content-tokens.js';
6
6
  import { tokenItemToString } from '../../private/node/ui/components/token-item.js';
7
+ import { commandEventOutputMode, emitCommandEvent } from '../../private/node/command-event-context.js';
7
8
  import { consoleLog, consoleWarn, output } from '../../private/node/output.js';
8
9
  import stripAnsi from 'strip-ansi';
9
10
  import { Writable } from 'stream';
@@ -210,6 +211,22 @@ export const clearCollectedLogs = () => {
210
211
  export function outputResult(content) {
211
212
  output(content, 'info', consoleLog);
212
213
  }
214
+ /**
215
+ * Waits for queued stdout writes to reach their destination before the process exits.
216
+ *
217
+ * @returns A promise that resolves when stdout has flushed.
218
+ */
219
+ export async function flushStdout() {
220
+ // An empty write completes after the preceding writes, including those queued for a pipe.
221
+ await new Promise((resolve, reject) => {
222
+ process.stdout.write('', (error) => {
223
+ if (error)
224
+ reject(error);
225
+ else
226
+ resolve();
227
+ });
228
+ });
229
+ }
213
230
  /**
214
231
  * Logs information at the info level.
215
232
  * Info messages don't get additional formatting.
@@ -219,6 +236,8 @@ export function outputResult(content) {
219
236
  * @param logger - The logging function to use to output to the user.
220
237
  */
221
238
  export function outputInfo(content, logger = consoleWarn) {
239
+ if (emitJsonDiagnostic(content, 'info', logger))
240
+ return;
222
241
  const message = stringifyMessage(content);
223
242
  if (isUnitTest())
224
243
  collectLog('info', content);
@@ -233,6 +252,8 @@ export function outputInfo(content, logger = consoleWarn) {
233
252
  * @param logger - The logging function to use to output to the user.
234
253
  */
235
254
  export function outputSuccess(content, logger = consoleWarn) {
255
+ if (emitJsonDiagnostic(content, 'info', logger))
256
+ return;
236
257
  const message = colors.bold(`✅ Success! ${stringifyMessage(content)}.`);
237
258
  if (isUnitTest())
238
259
  collectLog('success', content);
@@ -247,6 +268,8 @@ export function outputSuccess(content, logger = consoleWarn) {
247
268
  * @param logger - The logging function to use to output to the user.
248
269
  */
249
270
  export function outputCompleted(content, logger = consoleWarn) {
271
+ if (emitJsonDiagnostic(content, 'info', logger))
272
+ return;
250
273
  const message = `${colors.green('✔')} ${stringifyMessage(content)}`;
251
274
  if (isUnitTest())
252
275
  collectLog('completed', content);
@@ -261,6 +284,8 @@ export function outputCompleted(content, logger = consoleWarn) {
261
284
  * @param logger - The logging function to use to output to the user.
262
285
  */
263
286
  export function outputDebug(content, logger = consoleWarn) {
287
+ if (emitJsonDiagnostic(content, 'debug', logger))
288
+ return;
264
289
  if (isUnitTest())
265
290
  collectLog('debug', content);
266
291
  if (!shouldOutput('debug'))
@@ -277,6 +302,8 @@ export function outputDebug(content, logger = consoleWarn) {
277
302
  * @param logger - The logging function to use to output to the user.
278
303
  */
279
304
  export function outputWarn(content, logger = consoleWarn) {
305
+ if (emitJsonDiagnostic(content, 'warning', logger))
306
+ return;
280
307
  if (isUnitTest())
281
308
  collectLog('warn', content);
282
309
  const message = colors.yellow(stringifyMessage(content));
@@ -286,6 +313,8 @@ export function outputWarn(content, logger = consoleWarn) {
286
313
  * Prints a new line in the terminal.
287
314
  */
288
315
  export function outputNewline() {
316
+ if (commandEventOutputMode() === 'json')
317
+ return;
289
318
  consoleWarn('');
290
319
  }
291
320
  /**
@@ -341,6 +370,17 @@ export function unstyled(message) {
341
370
  return message;
342
371
  return stripAnsi(message);
343
372
  }
373
+ function emitJsonDiagnostic(content, level, logger) {
374
+ if (logger !== consoleWarn || commandEventOutputMode() !== 'json')
375
+ return false;
376
+ if (level === 'debug' && !isUnitTest() && !shouldOutput('debug'))
377
+ return true;
378
+ const message = unstyled(stringifyMessage(content));
379
+ if (message.trim().length > 0) {
380
+ emitCommandEvent({ type: 'diagnostic', level, message });
381
+ }
382
+ return true;
383
+ }
344
384
  /**
345
385
  * Checks if the console outputs should display colors or not.
346
386
  *
@@ -1 +1 @@
1
- {"version":3,"file":"output.js","sourceRoot":"","sources":["../../../src/public/node/output.ts"],"names":[],"mappings":"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","sourcesContent":["import {isUnitTest, isVerbose} from './context/local.js'\nimport {PackageManager} from './node-package-manager.js'\nimport {currentProcessIsGlobal} from './is-global.js'\nimport {AbortSignal} from './abort.js'\nimport colors from './colors.js'\nimport {isTruthy} from './context/utilities.js'\nimport {TokenItem} from './ui.js'\nimport {\n ColorContentToken,\n CommandContentToken,\n ContentToken,\n ErrorContentToken,\n HeadingContentToken,\n ItalicContentToken,\n JsonContentToken,\n LinesDiffContentToken,\n LinkContentToken,\n PathContentToken,\n RawContentToken,\n SubHeadingContentToken,\n} from '../../private/node/content-tokens.js'\nimport {tokenItemToString} from '../../private/node/ui/components/token-item.js'\nimport {consoleLog, consoleWarn, output} from '../../private/node/output.js'\nimport stripAnsi from 'strip-ansi'\nimport {Writable} from 'stream'\n\nimport type {Change} from 'diff'\n\nexport type Logger = Writable | ((message: string, logLevel?: LogLevel) => void)\n\nexport class TokenizedString {\n value: string\n constructor(value: string) {\n this.value = value\n }\n}\n\nexport type OutputMessage = string | TokenizedString\n\nexport const outputToken = {\n raw(value: string): RawContentToken {\n return new RawContentToken(value)\n },\n genericShellCommand(value: OutputMessage): CommandContentToken {\n return new CommandContentToken(value)\n },\n json(value: unknown): JsonContentToken {\n return new JsonContentToken(value)\n },\n path(value: OutputMessage): PathContentToken {\n return new PathContentToken(value)\n },\n link(value: OutputMessage, link?: string, fallback?: string | undefined): LinkContentToken {\n return new LinkContentToken(value, link, fallback)\n },\n heading(value: OutputMessage): HeadingContentToken {\n return new HeadingContentToken(value)\n },\n subheading(value: OutputMessage): SubHeadingContentToken {\n return new SubHeadingContentToken(value)\n },\n italic(value: OutputMessage): ItalicContentToken {\n return new ItalicContentToken(value)\n },\n errorText(value: OutputMessage): ErrorContentToken {\n return new ErrorContentToken(value)\n },\n cyan(value: OutputMessage): ColorContentToken {\n return new ColorContentToken(value, colors.cyan)\n },\n yellow(value: OutputMessage): ColorContentToken {\n return new ColorContentToken(value, colors.yellow)\n },\n magenta(value: OutputMessage): ColorContentToken {\n return new ColorContentToken(value, colors.magenta)\n },\n green(value: OutputMessage): ColorContentToken {\n return new ColorContentToken(value, colors.green)\n },\n gray(value: OutputMessage): ColorContentToken {\n return new ColorContentToken(value, colors.gray)\n },\n packagejsonScript(packageManager: PackageManager, scriptName: string, ...scriptArgs: string[]): CommandContentToken {\n return new CommandContentToken(formatPackageManagerCommand(packageManager, scriptName, ...scriptArgs))\n },\n successIcon(): ColorContentToken {\n return new ColorContentToken('✔', colors.green)\n },\n failIcon(): ErrorContentToken {\n return new ErrorContentToken('✖')\n },\n linesDiff(value: Change[]): LinesDiffContentToken {\n return new LinesDiffContentToken(value)\n },\n}\n\n/**\n * Given a command and its arguments, it formats it depending on the package manager.\n *\n * @param packageManager - The package manager to use (pnpm, npm, yarn).\n * @param scriptName - The name of the script to run.\n * @param scriptArgs - The arguments to pass to the script.\n * @returns The formatted command.\n */\nexport function formatPackageManagerCommand(\n packageManager: PackageManager,\n scriptName: string,\n ...scriptArgs: string[]\n): string {\n if (currentProcessIsGlobal()) {\n return [scriptName, ...scriptArgs].join(' ')\n }\n switch (packageManager) {\n case 'pnpm':\n case 'bun':\n case 'yarn': {\n const pieces = [packageManager, scriptName, ...scriptArgs]\n return pieces.join(' ')\n }\n case 'npm': {\n const pieces = ['npm', 'run', scriptName]\n if (scriptArgs.length > 0) {\n pieces.push('--')\n pieces.push(...scriptArgs)\n }\n return pieces.join(' ')\n }\n case 'homebrew':\n case 'unknown': {\n const pieces = [scriptName, ...scriptArgs]\n return pieces.join(' ')\n }\n }\n}\n\n/**\n * Creates a tokenized string from an array of strings and tokens.\n *\n * @param strings - The strings to join.\n * @param keys - Array of tokens or strings to join.\n * @returns The tokenized string.\n */\nexport function outputContent(\n strings: TemplateStringsArray,\n ...keys: (ContentToken<unknown> | string)[]\n): TokenizedString {\n const output = strings.reduce((acc, string, i) => {\n const token = keys[i]\n let tokenValue = ''\n\n if (typeof token === 'string') {\n tokenValue = token\n } else if (token) {\n const enumTokenOutput = token.output()\n tokenValue = Array.isArray(enumTokenOutput) ? enumTokenOutput.join('') : enumTokenOutput\n }\n\n return acc + string + tokenValue\n }, '')\n return new TokenizedString(output)\n}\n\n/** Log levels. */\nexport type LogLevel = 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace' | 'silent'\n\n/**\n * It maps a level to a numeric value.\n *\n * @param level - The level for which we'll return its numeric value.\n * @returns The numeric value of the level.\n */\nfunction logLevelValue(level: LogLevel): number {\n switch (level) {\n case 'trace':\n return 10\n case 'debug':\n return 20\n case 'info':\n return 30\n case 'warn':\n return 40\n case 'error':\n return 50\n case 'fatal':\n return 60\n case 'silent':\n return 70\n }\n}\n\n/**\n * It returns the current log level (debug or info).\n *\n * @returns The log level set by the user.\n */\nfunction currentLogLevel(): LogLevel {\n if (isVerbose()) {\n return 'debug'\n } else {\n return 'info'\n }\n}\n\n/**\n * It checks if the message should be outputted or not.\n *\n * @param logLevel - The desired log level for the message.\n * @returns True if the message should be outputted, false otherwise.\n */\nfunction shouldOutput(logLevel: LogLevel): boolean {\n if (isUnitTest()) {\n return false\n }\n const currentLogLevelValue = logLevelValue(currentLogLevel())\n const messageLogLevelValue = logLevelValue(logLevel)\n return messageLogLevelValue >= currentLogLevelValue\n}\n\n// eslint-disable-next-line import-x/no-mutable-exports\nexport let collectedLogs: Record<string, string[]> = {}\n\n/**\n * Memoized value for the color check.\n */\nlet memoizedShouldDisplayColors: boolean | undefined\n\n/**\n * This is only used during UnitTesting.\n * If we are in a testing context, instead of printing the logs to the console,\n * we will store them in a variable that can be accessed from the tests.\n *\n * @param key - The key of the log.\n * @param content - The content of the log.\n */\nexport function collectLog(key: string, content: OutputMessage): void {\n const message = stripAnsi(stringifyMessage(content))\n collectedLogs.output ??= []\n collectedLogs[key] ??= []\n collectedLogs.output.push(message)\n collectedLogs[key].push(message)\n}\n\nexport const clearCollectedLogs = (): void => {\n collectedLogs = {}\n}\n\n/**\n * Outputs command result information to the user.\n * Result messages don't get additional formatting.\n * The messages are logged at info level to stdout.\n *\n * @param content - The content to be output to the user.\n */\nexport function outputResult(content: OutputMessage): void {\n output(content, 'info', consoleLog)\n}\n\n/**\n * Logs information at the info level.\n * Info messages don't get additional formatting.\n * Note: By default, info messages are sent through the standard error.\n *\n * @param content - The content to be output to the user.\n * @param logger - The logging function to use to output to the user.\n */\nexport function outputInfo(content: OutputMessage, logger: Logger = consoleWarn): void {\n const message = stringifyMessage(content)\n if (isUnitTest()) collectLog('info', content)\n outputWhereAppropriate('info', logger, message)\n}\n\n/**\n * Outputs a success message to the user.\n * Success messages receive a special formatting to make them stand out in the console.\n * Note: Success messages are sent through the standard error.\n *\n * @param content - The content to be output to the user.\n * @param logger - The logging function to use to output to the user.\n */\nexport function outputSuccess(content: OutputMessage, logger: Logger = consoleWarn): void {\n const message = colors.bold(`✅ Success! ${stringifyMessage(content)}.`)\n if (isUnitTest()) collectLog('success', content)\n outputWhereAppropriate('info', logger, message)\n}\n\n/**\n * Outputs a completed message to the user.\n * Completed message receive a special formatting to make them stand out in the console.\n * Note: Completed messages are sent through the standard error.\n *\n * @param content - The content to be output to the user.\n * @param logger - The logging function to use to output to the user.\n */\nexport function outputCompleted(content: OutputMessage, logger: Logger = consoleWarn): void {\n const message = `${colors.green('✔')} ${stringifyMessage(content)}`\n if (isUnitTest()) collectLog('completed', content)\n outputWhereAppropriate('info', logger, message)\n}\n\n/**\n * Logs a message at the debug level. By default these output is hidden unless the user calls the CLI with --verbose.\n * Debug messages don't get additional formatting.\n * Note: By default, debug messages are sent through the standard error.\n *\n * @param content - The content to be output to the user.\n * @param logger - The logging function to use to output to the user.\n */\nexport function outputDebug(content: OutputMessage, logger: Logger = consoleWarn): void {\n if (isUnitTest()) collectLog('debug', content)\n if (!shouldOutput('debug')) return\n\n const message = colors.gray(stringifyMessage(content))\n outputWhereAppropriate('debug', logger, `${new Date().toISOString()}: ${message}`)\n}\n\n/**\n * Logs a message at the warning level.\n * Warning messages receive a special formatting to make them stand out in the console.\n * Note: By default, warning messages are sent through the standard error.\n *\n * @param content - The content to be output to the user.\n * @param logger - The logging function to use to output to the user.\n */\nexport function outputWarn(content: OutputMessage, logger: Logger = consoleWarn): void {\n if (isUnitTest()) collectLog('warn', content)\n const message = colors.yellow(stringifyMessage(content))\n outputWhereAppropriate('warn', logger, message)\n}\n\n/**\n * Prints a new line in the terminal.\n */\nexport function outputNewline(): void {\n consoleWarn('')\n}\n\n/**\n * Converts a Message to string.\n *\n * @param message - The message to convert to string.\n * @returns The string representation of the message.\n */\nexport function stringifyMessage(message: OutputMessage): string {\n if (message instanceof TokenizedString) {\n return message.value\n } else {\n return message\n }\n}\n\n/**\n * Convert a TokenItem to string.\n *\n * @param item - The item to convert to string.\n * @returns The string representation of the item.\n */\nexport function itemToString(item: TokenItem): string {\n return tokenItemToString(item)\n}\n\nexport interface OutputProcess {\n /**\n * The prefix to include in the logs\n * [vite] Output coming from Vite.\n */\n prefix: string\n /**\n * A callback to invoke the process. Stdout and stderr should be used\n * to send standard output and error data that gets formatted with the\n * right prefix.\n */\n action: (stdout: Writable, stderr: Writable, signal: AbortSignal) => Promise<void>\n}\n\n/**\n * Writes a message to the appropiated logger.\n *\n * @param logLevel - The log level to use to determine if the message should be output.\n * @param logger - The logger to use to output the message.\n * @param message - The message to output.\n */\nexport function outputWhereAppropriate(logLevel: LogLevel, logger: Logger, message: string): void {\n if (shouldOutput(logLevel)) {\n if (logger instanceof Writable) {\n logger.write(message)\n } else {\n logger(message, logLevel)\n }\n }\n}\n\n/**\n * Returns a message without styles (colors or any ANSI escape codes).\n *\n * @param message - The message to remove styles from.\n * @returns The message without styles.\n */\nexport function unstyled(message: string): string {\n // Optimization: skip regex execution for strings that don't have ANSI escape codes.\n // In high-frequency paths like terminal layout calculations, this can save significant CPU time.\n if (!message.includes('\\u001b')) return message\n\n return stripAnsi(message)\n}\n\n/**\n * Checks if the console outputs should display colors or not.\n *\n * @param _process - Optional, the process-like object to use to check if the console should display colors. Defaults to the global process.\n * @returns True if the console outputs should display colors, false otherwise.\n */\nexport function shouldDisplayColors(_process = process): boolean {\n if (_process === process && memoizedShouldDisplayColors !== undefined) {\n return memoizedShouldDisplayColors\n }\n\n const {env, stdout} = _process\n const result = Object.hasOwnProperty.call(env, 'FORCE_COLOR') ? isTruthy(env.FORCE_COLOR) : Boolean(stdout.isTTY)\n\n if (_process === process) {\n memoizedShouldDisplayColors = result\n }\n\n return result\n}\n\n/**\n * Parse title and body to be a single formatted string.\n *\n * @param title - The title of the message. Will be formatted as a heading.\n * @param body - The body of the message. Will respect the original formatting.\n * @returns The formatted message.\n */\nexport function formatSection(title: string, body: string): string {\n const formattedTitle = title.toUpperCase().padEnd(35)\n return outputContent`${outputToken.heading(formattedTitle)}\\n${body}`.value\n}\n"]}
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../../../src/public/node/output.ts"],"names":[],"mappings":"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","sourcesContent":["import {isUnitTest, isVerbose} from './context/local.js'\nimport {PackageManager} from './node-package-manager.js'\nimport {currentProcessIsGlobal} from './is-global.js'\nimport {AbortSignal} from './abort.js'\nimport colors from './colors.js'\nimport {isTruthy} from './context/utilities.js'\nimport {TokenItem} from './ui.js'\nimport {\n ColorContentToken,\n CommandContentToken,\n ContentToken,\n ErrorContentToken,\n HeadingContentToken,\n ItalicContentToken,\n JsonContentToken,\n LinesDiffContentToken,\n LinkContentToken,\n PathContentToken,\n RawContentToken,\n SubHeadingContentToken,\n} from '../../private/node/content-tokens.js'\nimport {tokenItemToString} from '../../private/node/ui/components/token-item.js'\nimport {commandEventOutputMode, emitCommandEvent} from '../../private/node/command-event-context.js'\nimport {consoleLog, consoleWarn, output} from '../../private/node/output.js'\nimport stripAnsi from 'strip-ansi'\nimport {Writable} from 'stream'\n\nimport type {Change} from 'diff'\n\nexport type Logger = Writable | ((message: string, logLevel?: LogLevel) => void)\n\nexport class TokenizedString {\n value: string\n constructor(value: string) {\n this.value = value\n }\n}\n\nexport type OutputMessage = string | TokenizedString\n\nexport const outputToken = {\n raw(value: string): RawContentToken {\n return new RawContentToken(value)\n },\n genericShellCommand(value: OutputMessage): CommandContentToken {\n return new CommandContentToken(value)\n },\n json(value: unknown): JsonContentToken {\n return new JsonContentToken(value)\n },\n path(value: OutputMessage): PathContentToken {\n return new PathContentToken(value)\n },\n link(value: OutputMessage, link?: string, fallback?: string | undefined): LinkContentToken {\n return new LinkContentToken(value, link, fallback)\n },\n heading(value: OutputMessage): HeadingContentToken {\n return new HeadingContentToken(value)\n },\n subheading(value: OutputMessage): SubHeadingContentToken {\n return new SubHeadingContentToken(value)\n },\n italic(value: OutputMessage): ItalicContentToken {\n return new ItalicContentToken(value)\n },\n errorText(value: OutputMessage): ErrorContentToken {\n return new ErrorContentToken(value)\n },\n cyan(value: OutputMessage): ColorContentToken {\n return new ColorContentToken(value, colors.cyan)\n },\n yellow(value: OutputMessage): ColorContentToken {\n return new ColorContentToken(value, colors.yellow)\n },\n magenta(value: OutputMessage): ColorContentToken {\n return new ColorContentToken(value, colors.magenta)\n },\n green(value: OutputMessage): ColorContentToken {\n return new ColorContentToken(value, colors.green)\n },\n gray(value: OutputMessage): ColorContentToken {\n return new ColorContentToken(value, colors.gray)\n },\n packagejsonScript(packageManager: PackageManager, scriptName: string, ...scriptArgs: string[]): CommandContentToken {\n return new CommandContentToken(formatPackageManagerCommand(packageManager, scriptName, ...scriptArgs))\n },\n successIcon(): ColorContentToken {\n return new ColorContentToken('✔', colors.green)\n },\n failIcon(): ErrorContentToken {\n return new ErrorContentToken('✖')\n },\n linesDiff(value: Change[]): LinesDiffContentToken {\n return new LinesDiffContentToken(value)\n },\n}\n\n/**\n * Given a command and its arguments, it formats it depending on the package manager.\n *\n * @param packageManager - The package manager to use (pnpm, npm, yarn).\n * @param scriptName - The name of the script to run.\n * @param scriptArgs - The arguments to pass to the script.\n * @returns The formatted command.\n */\nexport function formatPackageManagerCommand(\n packageManager: PackageManager,\n scriptName: string,\n ...scriptArgs: string[]\n): string {\n if (currentProcessIsGlobal()) {\n return [scriptName, ...scriptArgs].join(' ')\n }\n switch (packageManager) {\n case 'pnpm':\n case 'bun':\n case 'yarn': {\n const pieces = [packageManager, scriptName, ...scriptArgs]\n return pieces.join(' ')\n }\n case 'npm': {\n const pieces = ['npm', 'run', scriptName]\n if (scriptArgs.length > 0) {\n pieces.push('--')\n pieces.push(...scriptArgs)\n }\n return pieces.join(' ')\n }\n case 'homebrew':\n case 'unknown': {\n const pieces = [scriptName, ...scriptArgs]\n return pieces.join(' ')\n }\n }\n}\n\n/**\n * Creates a tokenized string from an array of strings and tokens.\n *\n * @param strings - The strings to join.\n * @param keys - Array of tokens or strings to join.\n * @returns The tokenized string.\n */\nexport function outputContent(\n strings: TemplateStringsArray,\n ...keys: (ContentToken<unknown> | string)[]\n): TokenizedString {\n const output = strings.reduce((acc, string, i) => {\n const token = keys[i]\n let tokenValue = ''\n\n if (typeof token === 'string') {\n tokenValue = token\n } else if (token) {\n const enumTokenOutput = token.output()\n tokenValue = Array.isArray(enumTokenOutput) ? enumTokenOutput.join('') : enumTokenOutput\n }\n\n return acc + string + tokenValue\n }, '')\n return new TokenizedString(output)\n}\n\n/** Log levels. */\nexport type LogLevel = 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace' | 'silent'\n\n/**\n * It maps a level to a numeric value.\n *\n * @param level - The level for which we'll return its numeric value.\n * @returns The numeric value of the level.\n */\nfunction logLevelValue(level: LogLevel): number {\n switch (level) {\n case 'trace':\n return 10\n case 'debug':\n return 20\n case 'info':\n return 30\n case 'warn':\n return 40\n case 'error':\n return 50\n case 'fatal':\n return 60\n case 'silent':\n return 70\n }\n}\n\n/**\n * It returns the current log level (debug or info).\n *\n * @returns The log level set by the user.\n */\nfunction currentLogLevel(): LogLevel {\n if (isVerbose()) {\n return 'debug'\n } else {\n return 'info'\n }\n}\n\n/**\n * It checks if the message should be outputted or not.\n *\n * @param logLevel - The desired log level for the message.\n * @returns True if the message should be outputted, false otherwise.\n */\nfunction shouldOutput(logLevel: LogLevel): boolean {\n if (isUnitTest()) {\n return false\n }\n const currentLogLevelValue = logLevelValue(currentLogLevel())\n const messageLogLevelValue = logLevelValue(logLevel)\n return messageLogLevelValue >= currentLogLevelValue\n}\n\n// eslint-disable-next-line import-x/no-mutable-exports\nexport let collectedLogs: Record<string, string[]> = {}\n\n/**\n * Memoized value for the color check.\n */\nlet memoizedShouldDisplayColors: boolean | undefined\n\n/**\n * This is only used during UnitTesting.\n * If we are in a testing context, instead of printing the logs to the console,\n * we will store them in a variable that can be accessed from the tests.\n *\n * @param key - The key of the log.\n * @param content - The content of the log.\n */\nexport function collectLog(key: string, content: OutputMessage): void {\n const message = stripAnsi(stringifyMessage(content))\n collectedLogs.output ??= []\n collectedLogs[key] ??= []\n collectedLogs.output.push(message)\n collectedLogs[key].push(message)\n}\n\nexport const clearCollectedLogs = (): void => {\n collectedLogs = {}\n}\n\n/**\n * Outputs command result information to the user.\n * Result messages don't get additional formatting.\n * The messages are logged at info level to stdout.\n *\n * @param content - The content to be output to the user.\n */\nexport function outputResult(content: OutputMessage): void {\n output(content, 'info', consoleLog)\n}\n\n/**\n * Waits for queued stdout writes to reach their destination before the process exits.\n *\n * @returns A promise that resolves when stdout has flushed.\n */\nexport async function flushStdout(): Promise<void> {\n // An empty write completes after the preceding writes, including those queued for a pipe.\n await new Promise<void>((resolve, reject) => {\n process.stdout.write('', (error) => {\n if (error) reject(error)\n else resolve()\n })\n })\n}\n\n/**\n * Logs information at the info level.\n * Info messages don't get additional formatting.\n * Note: By default, info messages are sent through the standard error.\n *\n * @param content - The content to be output to the user.\n * @param logger - The logging function to use to output to the user.\n */\nexport function outputInfo(content: OutputMessage, logger: Logger = consoleWarn): void {\n if (emitJsonDiagnostic(content, 'info', logger)) return\n\n const message = stringifyMessage(content)\n if (isUnitTest()) collectLog('info', content)\n outputWhereAppropriate('info', logger, message)\n}\n\n/**\n * Outputs a success message to the user.\n * Success messages receive a special formatting to make them stand out in the console.\n * Note: Success messages are sent through the standard error.\n *\n * @param content - The content to be output to the user.\n * @param logger - The logging function to use to output to the user.\n */\nexport function outputSuccess(content: OutputMessage, logger: Logger = consoleWarn): void {\n if (emitJsonDiagnostic(content, 'info', logger)) return\n\n const message = colors.bold(`✅ Success! ${stringifyMessage(content)}.`)\n if (isUnitTest()) collectLog('success', content)\n outputWhereAppropriate('info', logger, message)\n}\n\n/**\n * Outputs a completed message to the user.\n * Completed message receive a special formatting to make them stand out in the console.\n * Note: Completed messages are sent through the standard error.\n *\n * @param content - The content to be output to the user.\n * @param logger - The logging function to use to output to the user.\n */\nexport function outputCompleted(content: OutputMessage, logger: Logger = consoleWarn): void {\n if (emitJsonDiagnostic(content, 'info', logger)) return\n\n const message = `${colors.green('✔')} ${stringifyMessage(content)}`\n if (isUnitTest()) collectLog('completed', content)\n outputWhereAppropriate('info', logger, message)\n}\n\n/**\n * Logs a message at the debug level. By default these output is hidden unless the user calls the CLI with --verbose.\n * Debug messages don't get additional formatting.\n * Note: By default, debug messages are sent through the standard error.\n *\n * @param content - The content to be output to the user.\n * @param logger - The logging function to use to output to the user.\n */\nexport function outputDebug(content: OutputMessage, logger: Logger = consoleWarn): void {\n if (emitJsonDiagnostic(content, 'debug', logger)) return\n\n if (isUnitTest()) collectLog('debug', content)\n if (!shouldOutput('debug')) return\n\n const message = colors.gray(stringifyMessage(content))\n outputWhereAppropriate('debug', logger, `${new Date().toISOString()}: ${message}`)\n}\n\n/**\n * Logs a message at the warning level.\n * Warning messages receive a special formatting to make them stand out in the console.\n * Note: By default, warning messages are sent through the standard error.\n *\n * @param content - The content to be output to the user.\n * @param logger - The logging function to use to output to the user.\n */\nexport function outputWarn(content: OutputMessage, logger: Logger = consoleWarn): void {\n if (emitJsonDiagnostic(content, 'warning', logger)) return\n\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 if (commandEventOutputMode() === 'json') return\n consoleWarn('')\n}\n\n/**\n * Converts a Message to string.\n *\n * @param message - The message to convert to string.\n * @returns The string representation of the message.\n */\nexport function stringifyMessage(message: OutputMessage): string {\n if (message instanceof TokenizedString) {\n return message.value\n } else {\n return message\n }\n}\n\n/**\n * Convert a TokenItem to string.\n *\n * @param item - The item to convert to string.\n * @returns The string representation of the item.\n */\nexport function itemToString(item: TokenItem): string {\n return tokenItemToString(item)\n}\n\nexport interface OutputProcess {\n /**\n * The prefix to include in the logs\n * [vite] Output coming from Vite.\n */\n prefix: string\n /**\n * A callback to invoke the process. Stdout and stderr should be used\n * to send standard output and error data that gets formatted with the\n * right prefix.\n */\n action: (stdout: Writable, stderr: Writable, signal: AbortSignal) => Promise<void>\n}\n\n/**\n * Writes a message to the appropiated logger.\n *\n * @param logLevel - The log level to use to determine if the message should be output.\n * @param logger - The logger to use to output the message.\n * @param message - The message to output.\n */\nexport function outputWhereAppropriate(logLevel: LogLevel, logger: Logger, message: string): void {\n if (shouldOutput(logLevel)) {\n if (logger instanceof Writable) {\n logger.write(message)\n } else {\n logger(message, logLevel)\n }\n }\n}\n\n/**\n * Returns a message without styles (colors or any ANSI escape codes).\n *\n * @param message - The message to remove styles from.\n * @returns The message without styles.\n */\nexport function unstyled(message: string): string {\n // Optimization: skip regex execution for strings that don't have ANSI escape codes.\n // In high-frequency paths like terminal layout calculations, this can save significant CPU time.\n if (!message.includes('\\u001b')) return message\n\n return stripAnsi(message)\n}\n\nfunction emitJsonDiagnostic(content: OutputMessage, level: 'debug' | 'info' | 'warning', logger: Logger): boolean {\n if (logger !== consoleWarn || commandEventOutputMode() !== 'json') return false\n if (level === 'debug' && !isUnitTest() && !shouldOutput('debug')) return true\n\n const message = unstyled(stringifyMessage(content))\n if (message.trim().length > 0) {\n emitCommandEvent({type: 'diagnostic', level, message})\n }\n return true\n}\n\n/**\n * Checks if the console outputs should display colors or not.\n *\n * @param _process - Optional, the process-like object to use to check if the console should display colors. Defaults to the global process.\n * @returns True if the console outputs should display colors, false otherwise.\n */\nexport function shouldDisplayColors(_process = process): boolean {\n if (_process === process && memoizedShouldDisplayColors !== undefined) {\n return memoizedShouldDisplayColors\n }\n\n const {env, stdout} = _process\n const result = Object.hasOwnProperty.call(env, 'FORCE_COLOR') ? isTruthy(env.FORCE_COLOR) : Boolean(stdout.isTTY)\n\n if (_process === process) {\n memoizedShouldDisplayColors = result\n }\n\n return result\n}\n\n/**\n * Parse title and body to be a single formatted string.\n *\n * @param title - The title of the message. Will be formatted as a heading.\n * @param body - The body of the message. Will respect the original formatting.\n * @returns The formatted message.\n */\nexport function formatSection(title: string, body: string): string {\n const formattedTitle = title.toUpperCase().padEnd(35)\n return outputContent`${outputToken.heading(formattedTitle)}\\n${body}`.value\n}\n"]}
@@ -177,7 +177,9 @@ export function sniffForPath(argv = process.argv) {
177
177
  * @returns Whether the `--json` or `-j` flag is present in the arguments.
178
178
  */
179
179
  export function sniffForJson(argv = process.argv) {
180
- return argv.includes('--json') || argv.includes('-j');
180
+ const passthroughIndex = argv.indexOf('--');
181
+ const commandArguments = passthroughIndex === -1 ? argv : argv.slice(0, passthroughIndex);
182
+ return commandArguments.includes('--json') || commandArguments.includes('-j');
181
183
  }
182
184
  /**
183
185
  * Removes any `..` traversal segments from a relative path and calls `warn`