@shopify/cli-kit 4.6.1 → 4.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/dist/private/node/analytics/bounded-collections.js +1 -4
  2. package/dist/private/node/analytics/bounded-collections.js.map +1 -1
  3. package/dist/private/node/analytics/graphql-error-codes.d.ts +2 -2
  4. package/dist/private/node/analytics/graphql-error-codes.js +2 -2
  5. package/dist/private/node/analytics/graphql-error-codes.js.map +1 -1
  6. package/dist/private/node/analytics.js +12 -7
  7. package/dist/private/node/analytics.js.map +1 -1
  8. package/dist/private/node/api/headers.js +3 -0
  9. package/dist/private/node/api/headers.js.map +1 -1
  10. package/dist/private/node/api.js +8 -8
  11. package/dist/private/node/api.js.map +1 -1
  12. package/dist/private/node/conf-store.js +1 -1
  13. package/dist/private/node/conf-store.js.map +1 -1
  14. package/dist/private/node/content-tokens.js +27 -2
  15. package/dist/private/node/content-tokens.js.map +1 -1
  16. package/dist/private/node/otel-metrics.d.ts +1 -1
  17. package/dist/private/node/otel-metrics.js +5 -2
  18. package/dist/private/node/otel-metrics.js.map +1 -1
  19. package/dist/private/node/plugin-hints.d.ts +16 -0
  20. package/dist/private/node/plugin-hints.js +29 -0
  21. package/dist/private/node/plugin-hints.js.map +1 -0
  22. package/dist/private/node/request-ids.js +2 -3
  23. package/dist/private/node/request-ids.js.map +1 -1
  24. package/dist/private/node/session/device-authorization.js +4 -7
  25. package/dist/private/node/session/device-authorization.js.map +1 -1
  26. package/dist/private/node/session/exchange.d.ts +4 -4
  27. package/dist/private/node/session/exchange.js +21 -5
  28. package/dist/private/node/session/exchange.js.map +1 -1
  29. package/dist/private/node/testing/ui.js +18 -19
  30. package/dist/private/node/testing/ui.js.map +1 -1
  31. package/dist/private/node/ui/components/Alert.d.ts +1 -1
  32. package/dist/private/node/ui/components/Alert.js.map +1 -1
  33. package/dist/private/node/ui/components/ConcurrentOutput.test.js +2 -0
  34. package/dist/private/node/ui/components/ConcurrentOutput.test.js.map +1 -1
  35. package/dist/private/node/ui/components/DangerousConfirmationPrompt.d.ts +1 -1
  36. package/dist/private/node/ui/components/DangerousConfirmationPrompt.js.map +1 -1
  37. package/dist/private/node/ui/components/List.d.ts +1 -1
  38. package/dist/private/node/ui/components/List.js.map +1 -1
  39. package/dist/private/node/ui/components/Prompts/InfoMessage.d.ts +1 -1
  40. package/dist/private/node/ui/components/Prompts/InfoMessage.js.map +1 -1
  41. package/dist/private/node/ui/components/Prompts/InfoTable.d.ts +1 -1
  42. package/dist/private/node/ui/components/Prompts/InfoTable.js.map +1 -1
  43. package/dist/private/node/ui/components/Prompts/PromptLayout.d.ts +1 -1
  44. package/dist/private/node/ui/components/Prompts/PromptLayout.js.map +1 -1
  45. package/dist/private/node/ui/components/SingleTask.test.js +1 -0
  46. package/dist/private/node/ui/components/SingleTask.test.js.map +1 -1
  47. package/dist/private/node/ui/components/TabularData.d.ts +1 -1
  48. package/dist/private/node/ui/components/TabularData.js +2 -1
  49. package/dist/private/node/ui/components/TabularData.js.map +1 -1
  50. package/dist/private/node/ui/components/TextPrompt.d.ts +1 -1
  51. package/dist/private/node/ui/components/TextPrompt.js.map +1 -1
  52. package/dist/private/node/ui/components/TokenizedText.d.ts +1 -38
  53. package/dist/private/node/ui/components/TokenizedText.js +0 -54
  54. package/dist/private/node/ui/components/TokenizedText.js.map +1 -1
  55. package/dist/private/node/ui/components/TokenizedText.test.js +2 -1
  56. package/dist/private/node/ui/components/TokenizedText.test.js.map +1 -1
  57. package/dist/private/node/ui/components/token-item.d.ts +38 -0
  58. package/dist/private/node/ui/components/token-item.js +63 -0
  59. package/dist/private/node/ui/components/token-item.js.map +1 -0
  60. package/dist/private/node/ui/hooks/use-abort-signal.js +5 -4
  61. package/dist/private/node/ui/hooks/use-abort-signal.js.map +1 -1
  62. package/dist/private/node/ui/hooks/use-select-state.js +2 -1
  63. package/dist/private/node/ui/hooks/use-select-state.js.map +1 -1
  64. package/dist/private/node/ui/utilities.d.ts +6 -6
  65. package/dist/private/node/ui/utilities.js +1 -1
  66. package/dist/private/node/ui/utilities.js.map +1 -1
  67. package/dist/private/node/ui.js +18 -15
  68. package/dist/private/node/ui.js.map +1 -1
  69. package/dist/public/common/string.d.ts +1 -1
  70. package/dist/public/common/string.js.map +1 -1
  71. package/dist/public/common/version.d.ts +1 -1
  72. package/dist/public/common/version.js +1 -1
  73. package/dist/public/common/version.js.map +1 -1
  74. package/dist/public/node/abort.d.ts +14 -6
  75. package/dist/public/node/abort.js +7 -6
  76. package/dist/public/node/abort.js.map +1 -1
  77. package/dist/public/node/analytics.d.ts +1 -0
  78. package/dist/public/node/analytics.js +79 -32
  79. package/dist/public/node/analytics.js.map +1 -1
  80. package/dist/public/node/api/admin.js +1 -1
  81. package/dist/public/node/api/admin.js.map +1 -1
  82. package/dist/public/node/base-command.d.ts +10 -0
  83. package/dist/public/node/base-command.js +31 -8
  84. package/dist/public/node/base-command.js.map +1 -1
  85. package/dist/public/node/cli.d.ts +13 -0
  86. package/dist/public/node/cli.js +18 -2
  87. package/dist/public/node/cli.js.map +1 -1
  88. package/dist/public/node/context/local.d.ts +3 -1
  89. package/dist/public/node/context/local.js +14 -7
  90. package/dist/public/node/context/local.js.map +1 -1
  91. package/dist/public/node/custom-oclif-loader.js +19 -16
  92. package/dist/public/node/custom-oclif-loader.js.map +1 -1
  93. package/dist/public/node/doctor/framework.js +4 -5
  94. package/dist/public/node/doctor/framework.js.map +1 -1
  95. package/dist/public/node/environment.js +8 -11
  96. package/dist/public/node/environment.js.map +1 -1
  97. package/dist/public/node/error.d.ts +1 -4
  98. package/dist/public/node/error.js +20 -7
  99. package/dist/public/node/error.js.map +1 -1
  100. package/dist/public/node/git.js +7 -5
  101. package/dist/public/node/git.js.map +1 -1
  102. package/dist/public/node/global-context.js +1 -1
  103. package/dist/public/node/global-context.js.map +1 -1
  104. package/dist/public/node/hidden-folder.js +2 -4
  105. package/dist/public/node/hidden-folder.js.map +1 -1
  106. package/dist/public/node/hooks/postrun.js +1 -1
  107. package/dist/public/node/hooks/postrun.js.map +1 -1
  108. package/dist/public/node/hooks/prerun.js +5 -1
  109. package/dist/public/node/hooks/prerun.js.map +1 -1
  110. package/dist/public/node/local-storage.js +1 -0
  111. package/dist/public/node/local-storage.js.map +1 -1
  112. package/dist/public/node/metadata.d.ts +3 -0
  113. package/dist/public/node/metadata.js.map +1 -1
  114. package/dist/public/node/mimes.js +1 -3
  115. package/dist/public/node/mimes.js.map +1 -1
  116. package/dist/public/node/node-package-manager.js +31 -73
  117. package/dist/public/node/node-package-manager.js.map +1 -1
  118. package/dist/public/node/notifications-system.js +19 -3
  119. package/dist/public/node/notifications-system.js.map +1 -1
  120. package/dist/public/node/os.js +5 -10
  121. package/dist/public/node/os.js.map +1 -1
  122. package/dist/public/node/output.js +11 -20
  123. package/dist/public/node/output.js.map +1 -1
  124. package/dist/public/node/plugins/tunnel.d.ts +1 -2
  125. package/dist/public/node/plugins/tunnel.js +2 -2
  126. package/dist/public/node/plugins/tunnel.js.map +1 -1
  127. package/dist/public/node/result.js +4 -2
  128. package/dist/public/node/result.js.map +1 -1
  129. package/dist/public/node/serial-batch-processor.js +4 -3
  130. package/dist/public/node/serial-batch-processor.js.map +1 -1
  131. package/dist/public/node/store-auth-session.js +1 -1
  132. package/dist/public/node/store-auth-session.js.map +1 -1
  133. package/dist/public/node/system.d.ts +15 -1
  134. package/dist/public/node/system.js +42 -6
  135. package/dist/public/node/system.js.map +1 -1
  136. package/dist/public/node/themes/conf.js +2 -2
  137. package/dist/public/node/themes/conf.js.map +1 -1
  138. package/dist/public/node/themes/factories.js +2 -2
  139. package/dist/public/node/themes/factories.js.map +1 -1
  140. package/dist/public/node/themes/theme-manager.js +2 -0
  141. package/dist/public/node/themes/theme-manager.js.map +1 -1
  142. package/dist/public/node/themes/urls.js +7 -7
  143. package/dist/public/node/themes/urls.js.map +1 -1
  144. package/dist/public/node/toml/toml-file.js +12 -13
  145. package/dist/public/node/toml/toml-file.js.map +1 -1
  146. package/dist/public/node/ui.d.ts +1 -1
  147. package/dist/public/node/ui.js +1 -1
  148. package/dist/public/node/ui.js.map +1 -1
  149. package/dist/public/node/vendor/dev_server/dev-server-2024.js +14 -2
  150. package/dist/public/node/vendor/dev_server/dev-server-2024.js.map +1 -1
  151. package/dist/public/node/vendor/dev_server/dev-server.js +3 -0
  152. package/dist/public/node/vendor/dev_server/dev-server.js.map +1 -1
  153. package/dist/public/node/vendor/dev_server/network/index.js +1 -1
  154. package/dist/public/node/vendor/dev_server/network/index.js.map +1 -1
  155. package/dist/public/node/vendor/otel-js/export/InstantaneousMetricReader.js +1 -0
  156. package/dist/public/node/vendor/otel-js/export/InstantaneousMetricReader.js.map +1 -1
  157. package/dist/public/node/vendor/otel-js/service/BaseOtelService/BaseOtelService.js +5 -2
  158. package/dist/public/node/vendor/otel-js/service/BaseOtelService/BaseOtelService.js.map +1 -1
  159. package/dist/public/node/vendor/otel-js/service/types.d.ts +2 -2
  160. package/dist/public/node/vendor/otel-js/service/types.js.map +1 -1
  161. package/dist/public/node/vscode.js +12 -11
  162. package/dist/public/node/vscode.js.map +1 -1
  163. package/dist/tsconfig.tsbuildinfo +1 -1
  164. package/package.json +3 -9
@@ -7,6 +7,7 @@ import { updateTomlValues } from '@shopify/toml-patch';
7
7
  * Carries path and a clean message suitable for JSON output.
8
8
  */
9
9
  export class TomlFileError extends AbortError {
10
+ path;
10
11
  constructor(path, message) {
11
12
  super(message);
12
13
  this.name = 'TomlFileError';
@@ -42,8 +43,10 @@ export class TomlFile {
42
43
  file.content = file.decode(raw);
43
44
  return file;
44
45
  }
46
+ path;
47
+ content;
48
+ errors = [];
45
49
  constructor(path, content) {
46
- this.errors = [];
47
50
  this.path = path;
48
51
  this.content = content;
49
52
  }
@@ -125,12 +128,12 @@ export class TomlFile {
125
128
  decode(raw) {
126
129
  try {
127
130
  return decodeToml(raw);
128
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
129
131
  }
130
132
  catch (err) {
131
- if (err.line !== undefined && err.col !== undefined) {
132
- const description = String(err.message).split('\n')[0] ?? 'Invalid TOML';
133
- throw new TomlFileError(this.path, `${description} at row ${err.line}, col ${err.col}`);
133
+ const tomlError = err;
134
+ if (tomlError.line !== undefined && tomlError.col !== undefined) {
135
+ const description = String(tomlError.message).split('\n')[0] ?? 'Invalid TOML';
136
+ throw new TomlFileError(this.path, `${description} at row ${tomlError.line}, col ${tomlError.col}`);
134
137
  }
135
138
  throw err;
136
139
  }
@@ -145,16 +148,12 @@ export class TomlFile {
145
148
  * @returns Flattened patch entries.
146
149
  */
147
150
  function flattenToPatchEntries(obj, prefix = []) {
148
- const entries = [];
149
- for (const [key, value] of Object.entries(obj)) {
151
+ return Object.entries(obj).flatMap(([key, value]) => {
150
152
  const path = [...prefix, key];
151
153
  if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
152
- entries.push(...flattenToPatchEntries(value, path));
154
+ return flattenToPatchEntries(value, path);
153
155
  }
154
- else {
155
- entries.push([path, value]);
156
- }
157
- }
158
- return entries;
156
+ return [[path, value]];
157
+ });
159
158
  }
160
159
  //# sourceMappingURL=toml-file.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"toml-file.js","sourceRoot":"","sources":["../../../../src/public/node/toml/toml-file.ts"],"names":[],"mappings":"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","sourcesContent":["import {JsonMapType, decodeToml, encodeToml} from './codec.js'\nimport {AbortError} from '../error.js'\nimport {fileExists, readFile, writeFile} from '../fs.js'\nimport {updateTomlValues} from '@shopify/toml-patch'\n\ntype TomlPatchValue = string | number | boolean | undefined | (string | number | boolean)[]\n\n/**\n * An error on a TOML file — missing or malformed.\n * Carries path and a clean message suitable for JSON output.\n */\nexport class TomlFileError extends AbortError {\n readonly path: string\n\n constructor(path: string, message: string) {\n super(message)\n this.name = 'TomlFileError'\n this.path = path\n }\n}\n\n/**\n * General-purpose TOML file abstraction.\n *\n * Provides a unified interface for reading, patching, removing keys from, and replacing\n * the content of TOML files on disk.\n *\n * - `read` populates content from disk\n * - `patch` does surgical WASM-based edits (preserves comments and formatting)\n * - `remove` deletes a key by dotted path (preserves comments and formatting)\n * - `replace` does a full re-serialization (comments and formatting are NOT preserved).\n * - `transformRaw` applies a function to the raw TOML string on disk.\n */\nexport class TomlFile {\n /**\n * Read and parse a TOML file from disk. Throws {@link TomlFileError} if the file\n * doesn't exist or contains invalid TOML.\n *\n * @param path - Absolute path to the TOML file.\n * @returns A TomlFile instance with parsed content.\n */\n static async read(path: string): Promise<TomlFile> {\n if (!(await fileExists(path))) {\n throw new TomlFileError(path, `TOML file not found: ${path}`)\n }\n const raw = await readFile(path)\n const file = new TomlFile(path, {})\n file.content = file.decode(raw)\n return file\n }\n\n readonly path: string\n content: JsonMapType\n readonly errors: TomlFileError[] = []\n\n constructor(path: string, content: JsonMapType) {\n this.path = path\n this.content = content\n }\n\n /**\n * Surgically patch values in the TOML file, preserving comments and formatting.\n *\n * Accepts a nested object whose leaf values are set in the TOML. Intermediate tables are\n * created automatically. Setting a leaf to `undefined` removes it (use `remove()` for a\n * clearer API when deleting keys).\n *\n * @example\n * ```ts\n * await file.patch({build: {dev_store_url: 'my-store.myshopify.com'}})\n * await file.patch({application_url: 'https://example.com', auth: {redirect_urls: ['...']}})\n * ```\n */\n async patch(changes: {[key: string]: unknown}): Promise<void> {\n const patches = flattenToPatchEntries(changes)\n const raw = await readFile(this.path)\n const updated = updateTomlValues(raw, patches)\n const parsed = this.decode(updated)\n await writeFile(this.path, updated)\n this.content = parsed\n }\n\n /**\n * Remove a key from the TOML file by dotted path, preserving comments and formatting.\n *\n * @param keyPath - Dotted key path to remove (e.g. 'build.include_config_on_deploy').\n * @example\n * ```ts\n * await file.remove('build.include_config_on_deploy')\n * ```\n */\n async remove(keyPath: string): Promise<void> {\n const keys = keyPath.split('.')\n const raw = await readFile(this.path)\n const updated = updateTomlValues(raw, [[keys, undefined]])\n const parsed = this.decode(updated)\n await writeFile(this.path, updated)\n this.content = parsed\n }\n\n /**\n * Replace the entire file content. The file is fully re-serialized — comments and formatting\n * are NOT preserved.\n *\n * @param content - The new content to write.\n * @example\n * ```ts\n * await file.replace({client_id: 'abc', name: 'My App'})\n * ```\n */\n async replace(content: JsonMapType): Promise<void> {\n const encoded = encodeToml(content)\n this.decode(encoded)\n await writeFile(this.path, encoded)\n this.content = content\n }\n\n /**\n * Transform the raw TOML string on disk. Reads the file, applies the transform function\n * to the raw text, writes back, and re-parses to keep `content` in sync.\n *\n * Use this for text-level operations that can't be expressed as structured edits —\n * e.g. Injecting comments or positional insertion of keys in arrays-of-tables.\n * Subsequent `patch()` calls will preserve any comments added this way.\n *\n * @param transform - A function that receives the raw TOML string and returns the modified string.\n * @example\n * ```ts\n * await file.transformRaw((raw) => `# Header comment\\n${raw}`)\n * ```\n */\n async transformRaw(transform: (raw: string) => string): Promise<void> {\n const raw = await readFile(this.path)\n const transformed = transform(raw)\n const parsed = this.decode(transformed)\n await writeFile(this.path, transformed)\n this.content = parsed\n }\n\n private decode(raw: string): JsonMapType {\n try {\n return decodeToml(raw)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (err: any) {\n if (err.line !== undefined && err.col !== undefined) {\n const description = String(err.message).split('\\n')[0] ?? 'Invalid TOML'\n throw new TomlFileError(this.path, `${description} at row ${err.line}, col ${err.col}`)\n }\n throw err\n }\n }\n}\n\n/**\n * Flatten a nested object into an array of `[keyPath, value]` patch entries\n * suitable for `updateTomlValues`.\n *\n * @param obj - The nested object to flatten.\n * @param prefix - Key path prefix for recursion.\n * @returns Flattened patch entries.\n */\nfunction flattenToPatchEntries(obj: {[key: string]: unknown}, prefix: string[] = []): [string[], TomlPatchValue][] {\n const entries: [string[], TomlPatchValue][] = []\n for (const [key, value] of Object.entries(obj)) {\n const path = [...prefix, key]\n if (value !== null && typeof value === 'object' && !Array.isArray(value)) {\n entries.push(...flattenToPatchEntries(value as {[key: string]: unknown}, path))\n } else {\n entries.push([path, value as TomlPatchValue])\n }\n }\n return entries\n}\n"]}
1
+ {"version":3,"file":"toml-file.js","sourceRoot":"","sources":["../../../../src/public/node/toml/toml-file.ts"],"names":[],"mappings":"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","sourcesContent":["import {JsonMapType, decodeToml, encodeToml} from './codec.js'\nimport {AbortError} from '../error.js'\nimport {fileExists, readFile, writeFile} from '../fs.js'\nimport {updateTomlValues} from '@shopify/toml-patch'\n\ntype TomlPatchValue = string | number | boolean | undefined | (string | number | boolean)[]\n\n/**\n * An error on a TOML file — missing or malformed.\n * Carries path and a clean message suitable for JSON output.\n */\nexport class TomlFileError extends AbortError {\n readonly path: string\n\n constructor(path: string, message: string) {\n super(message)\n this.name = 'TomlFileError'\n this.path = path\n }\n}\n\n/**\n * General-purpose TOML file abstraction.\n *\n * Provides a unified interface for reading, patching, removing keys from, and replacing\n * the content of TOML files on disk.\n *\n * - `read` populates content from disk\n * - `patch` does surgical WASM-based edits (preserves comments and formatting)\n * - `remove` deletes a key by dotted path (preserves comments and formatting)\n * - `replace` does a full re-serialization (comments and formatting are NOT preserved).\n * - `transformRaw` applies a function to the raw TOML string on disk.\n */\nexport class TomlFile {\n /**\n * Read and parse a TOML file from disk. Throws {@link TomlFileError} if the file\n * doesn't exist or contains invalid TOML.\n *\n * @param path - Absolute path to the TOML file.\n * @returns A TomlFile instance with parsed content.\n */\n static async read(path: string): Promise<TomlFile> {\n if (!(await fileExists(path))) {\n throw new TomlFileError(path, `TOML file not found: ${path}`)\n }\n const raw = await readFile(path)\n const file = new TomlFile(path, {})\n file.content = file.decode(raw)\n return file\n }\n\n readonly path: string\n content: JsonMapType\n readonly errors: TomlFileError[] = []\n\n constructor(path: string, content: JsonMapType) {\n this.path = path\n this.content = content\n }\n\n /**\n * Surgically patch values in the TOML file, preserving comments and formatting.\n *\n * Accepts a nested object whose leaf values are set in the TOML. Intermediate tables are\n * created automatically. Setting a leaf to `undefined` removes it (use `remove()` for a\n * clearer API when deleting keys).\n *\n * @example\n * ```ts\n * await file.patch({build: {dev_store_url: 'my-store.myshopify.com'}})\n * await file.patch({application_url: 'https://example.com', auth: {redirect_urls: ['...']}})\n * ```\n */\n async patch(changes: {[key: string]: unknown}): Promise<void> {\n const patches = flattenToPatchEntries(changes)\n const raw = await readFile(this.path)\n const updated = updateTomlValues(raw, patches)\n const parsed = this.decode(updated)\n await writeFile(this.path, updated)\n this.content = parsed\n }\n\n /**\n * Remove a key from the TOML file by dotted path, preserving comments and formatting.\n *\n * @param keyPath - Dotted key path to remove (e.g. 'build.include_config_on_deploy').\n * @example\n * ```ts\n * await file.remove('build.include_config_on_deploy')\n * ```\n */\n async remove(keyPath: string): Promise<void> {\n const keys = keyPath.split('.')\n const raw = await readFile(this.path)\n const updated = updateTomlValues(raw, [[keys, undefined]])\n const parsed = this.decode(updated)\n await writeFile(this.path, updated)\n this.content = parsed\n }\n\n /**\n * Replace the entire file content. The file is fully re-serialized — comments and formatting\n * are NOT preserved.\n *\n * @param content - The new content to write.\n * @example\n * ```ts\n * await file.replace({client_id: 'abc', name: 'My App'})\n * ```\n */\n async replace(content: JsonMapType): Promise<void> {\n const encoded = encodeToml(content)\n this.decode(encoded)\n await writeFile(this.path, encoded)\n this.content = content\n }\n\n /**\n * Transform the raw TOML string on disk. Reads the file, applies the transform function\n * to the raw text, writes back, and re-parses to keep `content` in sync.\n *\n * Use this for text-level operations that can't be expressed as structured edits —\n * e.g. Injecting comments or positional insertion of keys in arrays-of-tables.\n * Subsequent `patch()` calls will preserve any comments added this way.\n *\n * @param transform - A function that receives the raw TOML string and returns the modified string.\n * @example\n * ```ts\n * await file.transformRaw((raw) => `# Header comment\\n${raw}`)\n * ```\n */\n async transformRaw(transform: (raw: string) => string): Promise<void> {\n const raw = await readFile(this.path)\n const transformed = transform(raw)\n const parsed = this.decode(transformed)\n await writeFile(this.path, transformed)\n this.content = parsed\n }\n\n private decode(raw: string): JsonMapType {\n try {\n return decodeToml(raw)\n } catch (err) {\n const tomlError = err as {line?: number; col?: number; message?: string}\n if (tomlError.line !== undefined && tomlError.col !== undefined) {\n const description = String(tomlError.message).split('\\n')[0] ?? 'Invalid TOML'\n throw new TomlFileError(this.path, `${description} at row ${tomlError.line}, col ${tomlError.col}`)\n }\n throw err\n }\n }\n}\n\n/**\n * Flatten a nested object into an array of `[keyPath, value]` patch entries\n * suitable for `updateTomlValues`.\n *\n * @param obj - The nested object to flatten.\n * @param prefix - Key path prefix for recursion.\n * @returns Flattened patch entries.\n */\nfunction flattenToPatchEntries(obj: {[key: string]: unknown}, prefix: string[] = []): [string[], TomlPatchValue][] {\n return Object.entries(obj).flatMap(([key, value]) => {\n const path = [...prefix, key]\n if (value !== null && typeof value === 'object' && !Array.isArray(value)) {\n return flattenToPatchEntries(value as {[key: string]: unknown}, path)\n }\n return [[path, value as TomlPatchValue]]\n })\n}\n"]}
@@ -6,7 +6,7 @@ import { AlertOptions } from '../../private/node/ui/alert.js';
6
6
  import { CustomSection } from '../../private/node/ui/components/Alert.js';
7
7
  import ScalarDict from '../../private/node/ui/components/Table/ScalarDict.js';
8
8
  import { TableColumn, TableProps } from '../../private/node/ui/components/Table/Table.js';
9
- import { Token, InlineToken, LinkToken, ListToken, TokenItem } from '../../private/node/ui/components/TokenizedText.js';
9
+ import { type InlineToken, type LinkToken, type ListToken, type Token, type TokenItem } from '../../private/node/ui/components/token-item.js';
10
10
  import { DangerousConfirmationPromptProps } from '../../private/node/ui/components/DangerousConfirmationPrompt.js';
11
11
  import { SelectPromptProps } from '../../private/node/ui/components/SelectPrompt.js';
12
12
  import { Task } from '../../private/node/ui/components/Tasks.js';
@@ -9,7 +9,7 @@ import { handleCtrlC, render, renderOnce } from '../../private/node/ui.js';
9
9
  import { alert } from '../../private/node/ui/alert.js';
10
10
  import { FatalError } from '../../private/node/ui/components/FatalError.js';
11
11
  import { Table } from '../../private/node/ui/components/Table/Table.js';
12
- import { tokenItemToString, } from '../../private/node/ui/components/TokenizedText.js';
12
+ import { tokenItemToString, } from '../../private/node/ui/components/token-item.js';
13
13
  import { DangerousConfirmationPrompt, } from '../../private/node/ui/components/DangerousConfirmationPrompt.js';
14
14
  import { SelectPrompt } from '../../private/node/ui/components/SelectPrompt.js';
15
15
  import { Tasks } from '../../private/node/ui/components/Tasks.js';
@@ -1 +1 @@
1
- {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../../src/public/node/ui.tsx"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable tsdoc/syntax */\nimport {AbortError, AbortSilentError, FatalError as Fatal} from './error.js'\nimport {outputContent, outputDebug, outputToken, TokenizedString} from './output.js'\nimport {terminalSupportsPrompting} from './system.js'\nimport {AbortController} from './abort.js'\nimport {runWithTimer} from './metadata.js'\nimport {ConcurrentOutput, ConcurrentOutputProps} from '../../private/node/ui/components/ConcurrentOutput.js'\nimport {handleCtrlC, render, renderOnce} from '../../private/node/ui.js'\nimport {alert, AlertOptions} from '../../private/node/ui/alert.js'\nimport {CustomSection} from '../../private/node/ui/components/Alert.js'\nimport {FatalError} from '../../private/node/ui/components/FatalError.js'\nimport ScalarDict from '../../private/node/ui/components/Table/ScalarDict.js'\nimport {Table, TableColumn, TableProps} from '../../private/node/ui/components/Table/Table.js'\nimport {\n Token,\n tokenItemToString,\n InlineToken,\n LinkToken,\n ListToken,\n TokenItem,\n} from '../../private/node/ui/components/TokenizedText.js'\nimport {\n DangerousConfirmationPrompt,\n DangerousConfirmationPromptProps,\n} from '../../private/node/ui/components/DangerousConfirmationPrompt.js'\nimport {SelectPrompt, SelectPromptProps} from '../../private/node/ui/components/SelectPrompt.js'\nimport {Tasks, Task} from '../../private/node/ui/components/Tasks.js'\nimport {TextPrompt, TextPromptProps} from '../../private/node/ui/components/TextPrompt.js'\nimport {AutocompletePromptProps, AutocompletePrompt} from '../../private/node/ui/components/AutocompletePrompt.js'\nimport {InfoTableSection} from '../../private/node/ui/components/Prompts/InfoTable.js'\nimport {InfoMessageProps} from '../../private/node/ui/components/Prompts/InfoMessage.js'\nimport {SingleTask} from '../../private/node/ui/components/SingleTask.js'\n\nimport React from 'react'\nimport {Key as InkKey, RenderOptions} from 'ink'\n\ntype PartialBy<T, TKey extends keyof T> = Omit<T, TKey> & Partial<Pick<T, TKey>>\n\ninterface UIDebugOptions {\n /** If true, don't check if the current terminal is interactive or not */\n skipTTYCheck?: boolean\n}\nconst defaultUIDebugOptions: UIDebugOptions = {\n skipTTYCheck: false,\n}\n\nexport interface RenderConcurrentOptions extends PartialBy<ConcurrentOutputProps, 'abortSignal'> {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders output from concurrent processes to the terminal with {@link ConcurrentOutput}.\n * @example\n * 00:00:00 │ backend │ first backend message\n * 00:00:00 │ backend │ second backend message\n * 00:00:00 │ backend │ third backend message\n * 00:00:00 │ frontend │ first frontend message\n * 00:00:00 │ frontend │ second frontend message\n * 00:00:00 │ frontend │ third frontend message\n *\n */\nexport async function renderConcurrent({renderOptions, ...props}: RenderConcurrentOptions) {\n const abortSignal = props.abortSignal ?? new AbortController().signal\n\n return render(<ConcurrentOutput {...props} abortSignal={abortSignal} />, renderOptions)\n}\n\nexport type AlertCustomSection = CustomSection\nexport type RenderAlertOptions = Omit<AlertOptions, 'type'>\n\n/**\n * Renders an information banner to the console.\n * @example Basic\n * ╭─ info ───────────────────────────────────────────────────╮\n * │ │\n * │ CLI update available. │\n * │ │\n * │ Run `npm run shopify upgrade`. │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n *\n * @example Complete\n * ╭─ info ───────────────────────────────────────────────────╮\n * │ │\n * │ my-app initialized and ready to build. │\n * │ │\n * │ Next steps │\n * │ • Run `cd verification-app` │\n * │ • To preview your project, run `npm app dev` │\n * │ • To add extensions, run `npm generate extension` │\n * │ │\n * │ Reference │\n * │ • Run `npm shopify help` │\n * │ • Dev docs [1] │\n * │ │\n * │ Custom section │\n * │ • Item 1 [2] │\n * │ • Item 2 │\n * │ • Item 3 [3] │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * [1] https://shopify.dev\n * [2] https://www.google.com/search?q=jh56t9l34kpo35tw8s28hn7s9s2xvzla01d8cn6j7yq&rlz=1C1GCEU_enUS832US832&oq=jh56t9l34kpo35tw8s28hn7s9s2xvzla01d8cn6j7yq&aqs=chrome.0.35i39l2j0l4j46j69i60.2711j0j7&sourceid=chrome&ie=UTF-8\n * [3] https://shopify.com\n *\n */\nexport function renderInfo(options: RenderAlertOptions) {\n return alert({...options, type: 'info'})\n}\n\n/**\n * Renders a success banner to the console.\n * @example Basic\n * ╭─ success ────────────────────────────────────────────────╮\n * │ │\n * │ CLI updated. │\n * │ │\n * │ You are now running version 3.47. │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n *\n * @example Complete\n * ╭─ success ────────────────────────────────────────────────╮\n * │ │\n * │ Deployment successful. │\n * │ │\n * │ Your extensions have been uploaded to your Shopify │\n * │ Partners Dashboard. │\n * │ │\n * │ Next steps │\n * │ • See your deployment and set it live [1] │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * [1] https://partners.shopify.com/1797046/apps/4523695/deployments\n *\n */\nexport function renderSuccess(options: RenderAlertOptions) {\n return alert({...options, type: 'success'})\n}\n\n/**\n * Renders a warning banner to the console.\n * @example Basic\n * ╭─ warning ────────────────────────────────────────────────╮\n * │ │\n * │ You have reached your limit of checkout extensions for │\n * │ this app. │\n * │ │\n * │ You can free up space for a new one by deleting an │\n * │ existing one. │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n *\n * @example Complete\n * ╭─ warning ────────────────────────────────────────────────╮\n * │ │\n * │ Required access scope update. │\n * │ │\n * │ The deadline for re-selecting your app scopes is May │\n * │ 1, 2022. │\n * │ │\n * │ Reference │\n * │ • Dev docs [1] │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * [1] https://shopify.dev/app/scopes\n *\n */\nexport function renderWarning(options: RenderAlertOptions) {\n return alert({...options, type: 'warning'})\n}\n\n/**\n * Renders an error banner to the console.\n * @example\n * ╭─ error ──────────────────────────────────────────────────╮\n * │ │\n * │ Version couldn't be released. │\n * │ │\n * │ This version needs to be submitted for review and │\n * │ approved by Shopify before it can be released. │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n *\n */\nexport function renderError(options: RenderAlertOptions) {\n return alert({...options, type: 'error'})\n}\n\ninterface RenderFatalErrorOptions {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders a Fatal error to the console inside a banner.\n * @example Basic\n * ╭─ error ──────────────────────────────────────────────────╮\n * │ │\n * │ Something went wrong. │\n * │ │\n * │ To investigate the issue, examine this stack trace: │\n * │ at _compile (internal/modules/cjs/loader.js:1137) │\n * │ at js (internal/modules/cjs/loader.js:1157) │\n * │ at load (internal/modules/cjs/loader.js:985) │\n * │ at _load (internal/modules/cjs/loader.js:878) │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n *\n * @example Complete\n * ╭─ error ──────────────────────────────────────────────────╮\n * │ │\n * │ No Organization found │\n * │ │\n * │ Next steps │\n * │ • Have you created a Shopify Partners organization │\n * │ [1]? │\n * │ • Have you confirmed your accounts from the emails │\n * │ you received? │\n * │ • Need to connect to a different App or │\n * │ organization? Run the command again with `--reset` │\n * │ │\n * │ amortizable-marketplace-ext │\n * │ • Some other error │\n * │ Validation errors │\n * │ • Missing expected key(s). │\n * │ │\n * │ amortizable-marketplace-ext-2 │\n * │ • Something was not found │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * [1] https://partners.shopify.com/signup\n *\n */\n\nexport function renderFatalError(error: Fatal, {renderOptions}: RenderFatalErrorOptions = {}) {\n return renderOnce(<FatalError error={error} />, {logLevel: 'error', renderOptions})\n}\n\nexport interface RenderSelectPromptOptions<T> extends Omit<SelectPromptProps<T>, 'onSubmit'> {\n isConfirmationPrompt?: boolean\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders a select prompt to the console.\n * @example\n * ? Associate your project with the org Castile Ventures?\n *\n * ┃ Add\n * ┃ • new-ext\n * ┃\n * ┃ Remove\n * ┃ • integrated-demand-ext\n * ┃ • order-discount\n *\n * Automations\n * > fifth\n * sixth\n *\n * Merchant Admin\n * eighth\n * ninth\n *\n * Other\n * first\n * second\n * third (limit reached)\n * fourth\n * seventh\n * tenth\n *\n * Press ↑↓ arrows to select, enter to confirm.\n *\n */\n\nexport async function renderSelectPrompt<T>(\n {renderOptions, isConfirmationPrompt, ...props}: RenderSelectPromptOptions<T>,\n uiDebugOptions: UIDebugOptions = defaultUIDebugOptions,\n): Promise<T> {\n throwInNonTTY({message: props.message, stdin: renderOptions?.stdin}, uiDebugOptions)\n\n return runWithTimer('cmd_all_timing_prompts_ms')(async () => {\n let selectedValue: T\n await render(\n <SelectPrompt\n {...props}\n onSubmit={(value: T) => {\n selectedValue = value\n }}\n />,\n {\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n return selectedValue!\n })\n}\n\nexport interface RenderConfirmationPromptOptions extends Pick<\n SelectPromptProps<boolean>,\n 'message' | 'infoTable' | 'infoMessage' | 'abortSignal'\n> {\n confirmationMessage?: string\n cancellationMessage?: string\n renderOptions?: RenderOptions\n defaultValue?: boolean\n}\n\n/**\n * Renders a confirmation prompt to the console.\n * @example\n * ? Delete the following themes from the store?\n *\n * ┃ Info message title\n * ┃\n * ┃ Info message body\n * ┃\n * ┃ • first theme (#1)\n * ┃ • second theme (#2)\n *\n * > (y) Yes, confirm changes\n * (n) Cancel\n *\n * Press ↑↓ arrows to select, enter or a shortcut to\n * confirm.\n *\n */\nexport async function renderConfirmationPrompt({\n message,\n infoTable,\n confirmationMessage = 'Yes, confirm',\n cancellationMessage = 'No, cancel',\n renderOptions,\n defaultValue = true,\n abortSignal,\n infoMessage,\n}: RenderConfirmationPromptOptions): Promise<boolean> {\n const choices = [\n {\n label: confirmationMessage,\n value: true,\n key: 'y',\n },\n {\n label: cancellationMessage,\n value: false,\n key: 'n',\n },\n ]\n\n return renderSelectPrompt({\n choices,\n message,\n infoTable,\n renderOptions,\n defaultValue,\n isConfirmationPrompt: true,\n abortSignal,\n infoMessage,\n })\n}\n\nexport interface RenderAutocompleteOptions<T> extends PartialBy<\n Omit<AutocompletePromptProps<T>, 'onSubmit'>,\n 'search'\n> {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders an autocomplete prompt to the console.\n * @example\n * ? Select a template: Type to search...\n *\n * ┃ Info message title\n * ┃\n * ┃ Info message body\n *\n * > first\n * second\n * third\n * fourth\n * fifth\n * sixth\n * seventh\n * eighth\n * ninth\n * tenth\n * eleventh\n * twelfth\n * thirteenth\n * fourteenth\n * fifteenth\n * sixteenth\n * seventeenth\n * eighteenth\n * nineteenth (disabled)\n * twentieth\n * twenty-first\n * twenty-second\n * twenty-third\n * twenty-fourth\n * twenty-fifth\n *\n * Press ↑↓ arrows to select, enter to confirm.\n *\n */\n\nexport async function renderAutocompletePrompt<T>(\n {renderOptions, ...props}: RenderAutocompleteOptions<T>,\n uiDebugOptions: UIDebugOptions = defaultUIDebugOptions,\n): Promise<T> {\n throwInNonTTY({message: props.message, stdin: renderOptions?.stdin}, uiDebugOptions)\n\n // The default search filters in-memory choices synchronously, so it doesn't need\n // throttling. Skipping the throttle makes the keystroke-to-result latency feel\n // instant. Callers that supply their own (typically remote/paginated) search keep\n // the component's default throttle unless they opt out via `searchDebounceMs`.\n const usingDefaultSearch = props.search === undefined\n const newProps = {\n search(term: string) {\n const lowerTerm = term.toLowerCase()\n return Promise.resolve({\n data: props.choices.filter((item) => {\n return item.label.toLowerCase().includes(lowerTerm) || item.group?.toLowerCase().includes(lowerTerm)\n }),\n })\n },\n ...(usingDefaultSearch ? {searchDebounceMs: 0} : {}),\n ...props,\n }\n\n return runWithTimer('cmd_all_timing_prompts_ms')(async () => {\n let selectedValue: T | undefined\n await render(\n <AutocompletePrompt\n {...newProps}\n onSubmit={(value: T) => {\n selectedValue = value\n }}\n />,\n {\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n\n if (selectedValue === undefined) {\n throw new Error(\n 'Prompt was interrupted before a selection was made. This can happen if the process received a signal, was terminated, or the prompt was aborted.',\n )\n }\n\n return selectedValue\n })\n}\n\ninterface RenderTableOptions<T extends ScalarDict> extends TableProps<T> {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders a table to the console.\n * @example\n * ID Name email\n * ── ────────── ─────────────\n * 1 John Doe jon@doe.com\n * 2 Jane Doe jane@doe.com\n * 3 John Smith jon@smith.com\n */\nexport function renderTable<T extends ScalarDict>({renderOptions, ...props}: RenderTableOptions<T>) {\n return renderOnce(<Table {...props} />, {renderOptions})\n}\n\ninterface RenderTasksOptions {\n renderOptions?: RenderOptions\n noProgressBar?: boolean\n}\n\n/**\n * Runs async tasks and displays their progress to the console.\n * @example\n * Installing dependencies ...\n */\n\nexport async function renderTasks<TContext>(\n tasks: Task<TContext>[],\n {renderOptions, noProgressBar}: RenderTasksOptions = {},\n): Promise<TContext> {\n let taskResult: TContext\n await render(\n <Tasks\n tasks={tasks}\n onComplete={(ctx) => {\n taskResult = ctx\n }}\n noProgressBar={noProgressBar}\n />,\n {\n stdout: process.stderr as unknown as NodeJS.WriteStream,\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n return taskResult!\n}\n\nexport interface RenderSingleTaskOptions<T> {\n title: TokenizedString\n task: (updateStatus: (status: TokenizedString) => void) => Promise<T>\n onAbort?: () => void\n renderOptions?: RenderOptions\n}\n\n/**\n * Awaits a single task and displays a loading bar while it's in progress. The task's result is returned.\n * @param options - Configuration object\n * @param options.title - The initial title to display with the loading bar\n * @param options.task - The async task to execute. Receives an updateStatus callback to change the displayed title.\n * @param options.renderOptions - Optional render configuration\n * @returns The result of the task\n * @example\n * Loading app ...\n */\nexport async function renderSingleTask<T>({\n title,\n task,\n onAbort,\n renderOptions,\n}: RenderSingleTaskOptions<T>): Promise<T> {\n let taskResult: T\n await render(\n <SingleTask\n title={title}\n task={task}\n onComplete={(result) => {\n taskResult = result\n }}\n onAbort={onAbort}\n />,\n {\n stdout: process.stderr as unknown as NodeJS.WriteStream,\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n return taskResult!\n}\n\nexport interface RenderTextPromptOptions extends Omit<TextPromptProps, 'onSubmit'> {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders a text prompt to the console.\n * @example\n * ? App project name (can be changed later):\n * > expansive commerce app\n * ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\n *\n */\n\nexport async function renderTextPrompt(\n {renderOptions, ...props}: RenderTextPromptOptions,\n uiDebugOptions: UIDebugOptions = defaultUIDebugOptions,\n): Promise<string> {\n throwInNonTTY({message: props.message, stdin: renderOptions?.stdin}, uiDebugOptions)\n\n return runWithTimer('cmd_all_timing_prompts_ms')(async () => {\n let enteredText = ''\n await render(\n <TextPrompt\n {...props}\n onSubmit={(value: string) => {\n enteredText = value\n }}\n />,\n {\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n return enteredText\n })\n}\n\nexport interface RenderDangerousConfirmationPromptOptions extends Omit<DangerousConfirmationPromptProps, 'onSubmit'> {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders a dangerous confirmation prompt to the console, forcing the user to\n * type a confirmation string to proceed.\n * @example\n * ? Release a new version of nightly-app-2023-06-19?\n *\n * ┃ Includes:\n * ┃ + web-px (new)\n * ┃ + sub-ui-ext\n * ┃ + theme-app-ext\n * ┃ + paymentify (from Partner Dashboard)\n * ┃\n * ┃ Removes:\n * ┃ - prod-discount-fun\n * ┃\n * ┃ This can permanently delete app user data.\n *\n * Type nightly-app-2023-06-19 to confirm, or press Escape\n * to cancel.\n * > █\n * ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\n *\n */\n\nexport async function renderDangerousConfirmationPrompt(\n {renderOptions, ...props}: RenderDangerousConfirmationPromptOptions,\n uiDebugOptions: UIDebugOptions = defaultUIDebugOptions,\n): Promise<boolean> {\n throwInNonTTY({message: props.message, stdin: renderOptions?.stdin}, uiDebugOptions)\n\n return runWithTimer('cmd_all_timing_prompts_ms')(async () => {\n let confirmed: boolean\n await render(\n <DangerousConfirmationPrompt\n {...props}\n onSubmit={(value: boolean) => {\n confirmed = value\n }}\n />,\n {\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n return confirmed!\n })\n}\n\n/** Waits for any key to be pressed except Ctrl+C which will terminate the process. */\n\nexport const keypress = async (stdin = process.stdin, uiDebugOptions: UIDebugOptions = defaultUIDebugOptions) => {\n throwInNonTTY({message: 'Press any key'}, uiDebugOptions)\n\n return runWithTimer('cmd_all_timing_prompts_ms')(() => {\n return new Promise((resolve, reject) => {\n const handler = (buffer: Buffer) => {\n stdin.setRawMode(false)\n\n const bytes = Array.from(buffer)\n\n if (bytes.length && bytes[0] === 3) {\n outputDebug('Canceled keypress, User pressed CTRL+C')\n reject(new AbortSilentError())\n }\n stdin.unref()\n process.nextTick(resolve)\n }\n\n stdin.setRawMode(true)\n stdin.once('data', handler)\n\n // We want to indicate that we're still using stdin, so that the process\n // doesn't exit early.\n stdin.ref()\n })\n })\n}\n\ninterface IsTTYOptions {\n stdin?: NodeJS.ReadStream\n uiDebugOptions?: UIDebugOptions\n}\n\nexport function isTTY({stdin = undefined, uiDebugOptions = defaultUIDebugOptions}: IsTTYOptions = {}) {\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- false should fall through to stdin/terminalSupportsPrompting\n return Boolean(uiDebugOptions.skipTTYCheck || stdin || terminalSupportsPrompting())\n}\n\ninterface ThrowInNonTTYOptions {\n message: TokenItem\n stdin?: NodeJS.ReadStream\n}\n\nfunction throwInNonTTY({message, stdin = undefined}: ThrowInNonTTYOptions, uiDebugOptions: UIDebugOptions) {\n if (isTTY({stdin, uiDebugOptions})) return\n\n const promptText = tokenItemToString(message)\n const errorMessage = `Failed to prompt:\n\n${outputContent`${outputToken.cyan(promptText)}`.value}\n\nThis usually happens when running a command non-interactively, for example in a CI environment, or when piping to or from another process.`\n throw new AbortError(\n errorMessage,\n 'To resolve this, specify the option in the command, or run the command in an interactive environment such as your local terminal.',\n )\n}\n\nexport type Key = InkKey\nexport type InfoMessage = InfoMessageProps['message']\nexport {Token, Task, TokenItem, InlineToken, LinkToken, TableColumn, InfoTableSection, ListToken, render, handleCtrlC}\n"]}
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../../src/public/node/ui.tsx"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable tsdoc/syntax */\nimport {AbortError, AbortSilentError, FatalError as Fatal} from './error.js'\nimport {outputContent, outputDebug, outputToken, TokenizedString} from './output.js'\nimport {terminalSupportsPrompting} from './system.js'\nimport {AbortController} from './abort.js'\nimport {runWithTimer} from './metadata.js'\nimport {ConcurrentOutput, ConcurrentOutputProps} from '../../private/node/ui/components/ConcurrentOutput.js'\nimport {handleCtrlC, render, renderOnce} from '../../private/node/ui.js'\nimport {alert, AlertOptions} from '../../private/node/ui/alert.js'\nimport {CustomSection} from '../../private/node/ui/components/Alert.js'\nimport {FatalError} from '../../private/node/ui/components/FatalError.js'\nimport ScalarDict from '../../private/node/ui/components/Table/ScalarDict.js'\nimport {Table, TableColumn, TableProps} from '../../private/node/ui/components/Table/Table.js'\nimport {\n tokenItemToString,\n type InlineToken,\n type LinkToken,\n type ListToken,\n type Token,\n type TokenItem,\n} from '../../private/node/ui/components/token-item.js'\nimport {\n DangerousConfirmationPrompt,\n DangerousConfirmationPromptProps,\n} from '../../private/node/ui/components/DangerousConfirmationPrompt.js'\nimport {SelectPrompt, SelectPromptProps} from '../../private/node/ui/components/SelectPrompt.js'\nimport {Tasks, Task} from '../../private/node/ui/components/Tasks.js'\nimport {TextPrompt, TextPromptProps} from '../../private/node/ui/components/TextPrompt.js'\nimport {AutocompletePromptProps, AutocompletePrompt} from '../../private/node/ui/components/AutocompletePrompt.js'\nimport {InfoTableSection} from '../../private/node/ui/components/Prompts/InfoTable.js'\nimport {InfoMessageProps} from '../../private/node/ui/components/Prompts/InfoMessage.js'\nimport {SingleTask} from '../../private/node/ui/components/SingleTask.js'\n\nimport React from 'react'\nimport {Key as InkKey, RenderOptions} from 'ink'\n\ntype PartialBy<T, TKey extends keyof T> = Omit<T, TKey> & Partial<Pick<T, TKey>>\n\ninterface UIDebugOptions {\n /** If true, don't check if the current terminal is interactive or not */\n skipTTYCheck?: boolean\n}\nconst defaultUIDebugOptions: UIDebugOptions = {\n skipTTYCheck: false,\n}\n\nexport interface RenderConcurrentOptions extends PartialBy<ConcurrentOutputProps, 'abortSignal'> {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders output from concurrent processes to the terminal with {@link ConcurrentOutput}.\n * @example\n * 00:00:00 │ backend │ first backend message\n * 00:00:00 │ backend │ second backend message\n * 00:00:00 │ backend │ third backend message\n * 00:00:00 │ frontend │ first frontend message\n * 00:00:00 │ frontend │ second frontend message\n * 00:00:00 │ frontend │ third frontend message\n *\n */\nexport async function renderConcurrent({renderOptions, ...props}: RenderConcurrentOptions) {\n const abortSignal = props.abortSignal ?? new AbortController().signal\n\n return render(<ConcurrentOutput {...props} abortSignal={abortSignal} />, renderOptions)\n}\n\nexport type AlertCustomSection = CustomSection\nexport type RenderAlertOptions = Omit<AlertOptions, 'type'>\n\n/**\n * Renders an information banner to the console.\n * @example Basic\n * ╭─ info ───────────────────────────────────────────────────╮\n * │ │\n * │ CLI update available. │\n * │ │\n * │ Run `npm run shopify upgrade`. │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n *\n * @example Complete\n * ╭─ info ───────────────────────────────────────────────────╮\n * │ │\n * │ my-app initialized and ready to build. │\n * │ │\n * │ Next steps │\n * │ • Run `cd verification-app` │\n * │ • To preview your project, run `npm app dev` │\n * │ • To add extensions, run `npm generate extension` │\n * │ │\n * │ Reference │\n * │ • Run `npm shopify help` │\n * │ • Dev docs [1] │\n * │ │\n * │ Custom section │\n * │ • Item 1 [2] │\n * │ • Item 2 │\n * │ • Item 3 [3] │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * [1] https://shopify.dev\n * [2] https://www.google.com/search?q=jh56t9l34kpo35tw8s28hn7s9s2xvzla01d8cn6j7yq&rlz=1C1GCEU_enUS832US832&oq=jh56t9l34kpo35tw8s28hn7s9s2xvzla01d8cn6j7yq&aqs=chrome.0.35i39l2j0l4j46j69i60.2711j0j7&sourceid=chrome&ie=UTF-8\n * [3] https://shopify.com\n *\n */\nexport function renderInfo(options: RenderAlertOptions) {\n return alert({...options, type: 'info'})\n}\n\n/**\n * Renders a success banner to the console.\n * @example Basic\n * ╭─ success ────────────────────────────────────────────────╮\n * │ │\n * │ CLI updated. │\n * │ │\n * │ You are now running version 3.47. │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n *\n * @example Complete\n * ╭─ success ────────────────────────────────────────────────╮\n * │ │\n * │ Deployment successful. │\n * │ │\n * │ Your extensions have been uploaded to your Shopify │\n * │ Partners Dashboard. │\n * │ │\n * │ Next steps │\n * │ • See your deployment and set it live [1] │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * [1] https://partners.shopify.com/1797046/apps/4523695/deployments\n *\n */\nexport function renderSuccess(options: RenderAlertOptions) {\n return alert({...options, type: 'success'})\n}\n\n/**\n * Renders a warning banner to the console.\n * @example Basic\n * ╭─ warning ────────────────────────────────────────────────╮\n * │ │\n * │ You have reached your limit of checkout extensions for │\n * │ this app. │\n * │ │\n * │ You can free up space for a new one by deleting an │\n * │ existing one. │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n *\n * @example Complete\n * ╭─ warning ────────────────────────────────────────────────╮\n * │ │\n * │ Required access scope update. │\n * │ │\n * │ The deadline for re-selecting your app scopes is May │\n * │ 1, 2022. │\n * │ │\n * │ Reference │\n * │ • Dev docs [1] │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * [1] https://shopify.dev/app/scopes\n *\n */\nexport function renderWarning(options: RenderAlertOptions) {\n return alert({...options, type: 'warning'})\n}\n\n/**\n * Renders an error banner to the console.\n * @example\n * ╭─ error ──────────────────────────────────────────────────╮\n * │ │\n * │ Version couldn't be released. │\n * │ │\n * │ This version needs to be submitted for review and │\n * │ approved by Shopify before it can be released. │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n *\n */\nexport function renderError(options: RenderAlertOptions) {\n return alert({...options, type: 'error'})\n}\n\ninterface RenderFatalErrorOptions {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders a Fatal error to the console inside a banner.\n * @example Basic\n * ╭─ error ──────────────────────────────────────────────────╮\n * │ │\n * │ Something went wrong. │\n * │ │\n * │ To investigate the issue, examine this stack trace: │\n * │ at _compile (internal/modules/cjs/loader.js:1137) │\n * │ at js (internal/modules/cjs/loader.js:1157) │\n * │ at load (internal/modules/cjs/loader.js:985) │\n * │ at _load (internal/modules/cjs/loader.js:878) │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n *\n * @example Complete\n * ╭─ error ──────────────────────────────────────────────────╮\n * │ │\n * │ No Organization found │\n * │ │\n * │ Next steps │\n * │ • Have you created a Shopify Partners organization │\n * │ [1]? │\n * │ • Have you confirmed your accounts from the emails │\n * │ you received? │\n * │ • Need to connect to a different App or │\n * │ organization? Run the command again with `--reset` │\n * │ │\n * │ amortizable-marketplace-ext │\n * │ • Some other error │\n * │ Validation errors │\n * │ • Missing expected key(s). │\n * │ │\n * │ amortizable-marketplace-ext-2 │\n * │ • Something was not found │\n * │ │\n * ╰──────────────────────────────────────────────────────────╯\n * [1] https://partners.shopify.com/signup\n *\n */\n\nexport function renderFatalError(error: Fatal, {renderOptions}: RenderFatalErrorOptions = {}) {\n return renderOnce(<FatalError error={error} />, {logLevel: 'error', renderOptions})\n}\n\nexport interface RenderSelectPromptOptions<T> extends Omit<SelectPromptProps<T>, 'onSubmit'> {\n isConfirmationPrompt?: boolean\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders a select prompt to the console.\n * @example\n * ? Associate your project with the org Castile Ventures?\n *\n * ┃ Add\n * ┃ • new-ext\n * ┃\n * ┃ Remove\n * ┃ • integrated-demand-ext\n * ┃ • order-discount\n *\n * Automations\n * > fifth\n * sixth\n *\n * Merchant Admin\n * eighth\n * ninth\n *\n * Other\n * first\n * second\n * third (limit reached)\n * fourth\n * seventh\n * tenth\n *\n * Press ↑↓ arrows to select, enter to confirm.\n *\n */\n\nexport async function renderSelectPrompt<T>(\n {renderOptions, isConfirmationPrompt, ...props}: RenderSelectPromptOptions<T>,\n uiDebugOptions: UIDebugOptions = defaultUIDebugOptions,\n): Promise<T> {\n throwInNonTTY({message: props.message, stdin: renderOptions?.stdin}, uiDebugOptions)\n\n return runWithTimer('cmd_all_timing_prompts_ms')(async () => {\n let selectedValue: T\n await render(\n <SelectPrompt\n {...props}\n onSubmit={(value: T) => {\n selectedValue = value\n }}\n />,\n {\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n return selectedValue!\n })\n}\n\nexport interface RenderConfirmationPromptOptions extends Pick<\n SelectPromptProps<boolean>,\n 'message' | 'infoTable' | 'infoMessage' | 'abortSignal'\n> {\n confirmationMessage?: string\n cancellationMessage?: string\n renderOptions?: RenderOptions\n defaultValue?: boolean\n}\n\n/**\n * Renders a confirmation prompt to the console.\n * @example\n * ? Delete the following themes from the store?\n *\n * ┃ Info message title\n * ┃\n * ┃ Info message body\n * ┃\n * ┃ • first theme (#1)\n * ┃ • second theme (#2)\n *\n * > (y) Yes, confirm changes\n * (n) Cancel\n *\n * Press ↑↓ arrows to select, enter or a shortcut to\n * confirm.\n *\n */\nexport async function renderConfirmationPrompt({\n message,\n infoTable,\n confirmationMessage = 'Yes, confirm',\n cancellationMessage = 'No, cancel',\n renderOptions,\n defaultValue = true,\n abortSignal,\n infoMessage,\n}: RenderConfirmationPromptOptions): Promise<boolean> {\n const choices = [\n {\n label: confirmationMessage,\n value: true,\n key: 'y',\n },\n {\n label: cancellationMessage,\n value: false,\n key: 'n',\n },\n ]\n\n return renderSelectPrompt({\n choices,\n message,\n infoTable,\n renderOptions,\n defaultValue,\n isConfirmationPrompt: true,\n abortSignal,\n infoMessage,\n })\n}\n\nexport interface RenderAutocompleteOptions<T> extends PartialBy<\n Omit<AutocompletePromptProps<T>, 'onSubmit'>,\n 'search'\n> {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders an autocomplete prompt to the console.\n * @example\n * ? Select a template: Type to search...\n *\n * ┃ Info message title\n * ┃\n * ┃ Info message body\n *\n * > first\n * second\n * third\n * fourth\n * fifth\n * sixth\n * seventh\n * eighth\n * ninth\n * tenth\n * eleventh\n * twelfth\n * thirteenth\n * fourteenth\n * fifteenth\n * sixteenth\n * seventeenth\n * eighteenth\n * nineteenth (disabled)\n * twentieth\n * twenty-first\n * twenty-second\n * twenty-third\n * twenty-fourth\n * twenty-fifth\n *\n * Press ↑↓ arrows to select, enter to confirm.\n *\n */\n\nexport async function renderAutocompletePrompt<T>(\n {renderOptions, ...props}: RenderAutocompleteOptions<T>,\n uiDebugOptions: UIDebugOptions = defaultUIDebugOptions,\n): Promise<T> {\n throwInNonTTY({message: props.message, stdin: renderOptions?.stdin}, uiDebugOptions)\n\n // The default search filters in-memory choices synchronously, so it doesn't need\n // throttling. Skipping the throttle makes the keystroke-to-result latency feel\n // instant. Callers that supply their own (typically remote/paginated) search keep\n // the component's default throttle unless they opt out via `searchDebounceMs`.\n const usingDefaultSearch = props.search === undefined\n const newProps = {\n search(term: string) {\n const lowerTerm = term.toLowerCase()\n return Promise.resolve({\n data: props.choices.filter((item) => {\n return item.label.toLowerCase().includes(lowerTerm) || item.group?.toLowerCase().includes(lowerTerm)\n }),\n })\n },\n ...(usingDefaultSearch ? {searchDebounceMs: 0} : {}),\n ...props,\n }\n\n return runWithTimer('cmd_all_timing_prompts_ms')(async () => {\n let selectedValue: T | undefined\n await render(\n <AutocompletePrompt\n {...newProps}\n onSubmit={(value: T) => {\n selectedValue = value\n }}\n />,\n {\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n\n if (selectedValue === undefined) {\n throw new Error(\n 'Prompt was interrupted before a selection was made. This can happen if the process received a signal, was terminated, or the prompt was aborted.',\n )\n }\n\n return selectedValue\n })\n}\n\ninterface RenderTableOptions<T extends ScalarDict> extends TableProps<T> {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders a table to the console.\n * @example\n * ID Name email\n * ── ────────── ─────────────\n * 1 John Doe jon@doe.com\n * 2 Jane Doe jane@doe.com\n * 3 John Smith jon@smith.com\n */\nexport function renderTable<T extends ScalarDict>({renderOptions, ...props}: RenderTableOptions<T>) {\n return renderOnce(<Table {...props} />, {renderOptions})\n}\n\ninterface RenderTasksOptions {\n renderOptions?: RenderOptions\n noProgressBar?: boolean\n}\n\n/**\n * Runs async tasks and displays their progress to the console.\n * @example\n * Installing dependencies ...\n */\n\nexport async function renderTasks<TContext>(\n tasks: Task<TContext>[],\n {renderOptions, noProgressBar}: RenderTasksOptions = {},\n): Promise<TContext> {\n let taskResult: TContext\n await render(\n <Tasks\n tasks={tasks}\n onComplete={(ctx) => {\n taskResult = ctx\n }}\n noProgressBar={noProgressBar}\n />,\n {\n stdout: process.stderr as unknown as NodeJS.WriteStream,\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n return taskResult!\n}\n\nexport interface RenderSingleTaskOptions<T> {\n title: TokenizedString\n task: (updateStatus: (status: TokenizedString) => void) => Promise<T>\n onAbort?: () => void\n renderOptions?: RenderOptions\n}\n\n/**\n * Awaits a single task and displays a loading bar while it's in progress. The task's result is returned.\n * @param options - Configuration object\n * @param options.title - The initial title to display with the loading bar\n * @param options.task - The async task to execute. Receives an updateStatus callback to change the displayed title.\n * @param options.renderOptions - Optional render configuration\n * @returns The result of the task\n * @example\n * Loading app ...\n */\nexport async function renderSingleTask<T>({\n title,\n task,\n onAbort,\n renderOptions,\n}: RenderSingleTaskOptions<T>): Promise<T> {\n let taskResult: T\n await render(\n <SingleTask\n title={title}\n task={task}\n onComplete={(result) => {\n taskResult = result\n }}\n onAbort={onAbort}\n />,\n {\n stdout: process.stderr as unknown as NodeJS.WriteStream,\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n return taskResult!\n}\n\nexport interface RenderTextPromptOptions extends Omit<TextPromptProps, 'onSubmit'> {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders a text prompt to the console.\n * @example\n * ? App project name (can be changed later):\n * > expansive commerce app\n * ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\n *\n */\n\nexport async function renderTextPrompt(\n {renderOptions, ...props}: RenderTextPromptOptions,\n uiDebugOptions: UIDebugOptions = defaultUIDebugOptions,\n): Promise<string> {\n throwInNonTTY({message: props.message, stdin: renderOptions?.stdin}, uiDebugOptions)\n\n return runWithTimer('cmd_all_timing_prompts_ms')(async () => {\n let enteredText = ''\n await render(\n <TextPrompt\n {...props}\n onSubmit={(value: string) => {\n enteredText = value\n }}\n />,\n {\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n return enteredText\n })\n}\n\nexport interface RenderDangerousConfirmationPromptOptions extends Omit<DangerousConfirmationPromptProps, 'onSubmit'> {\n renderOptions?: RenderOptions\n}\n\n/**\n * Renders a dangerous confirmation prompt to the console, forcing the user to\n * type a confirmation string to proceed.\n * @example\n * ? Release a new version of nightly-app-2023-06-19?\n *\n * ┃ Includes:\n * ┃ + web-px (new)\n * ┃ + sub-ui-ext\n * ┃ + theme-app-ext\n * ┃ + paymentify (from Partner Dashboard)\n * ┃\n * ┃ Removes:\n * ┃ - prod-discount-fun\n * ┃\n * ┃ This can permanently delete app user data.\n *\n * Type nightly-app-2023-06-19 to confirm, or press Escape\n * to cancel.\n * > █\n * ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔\n *\n */\n\nexport async function renderDangerousConfirmationPrompt(\n {renderOptions, ...props}: RenderDangerousConfirmationPromptOptions,\n uiDebugOptions: UIDebugOptions = defaultUIDebugOptions,\n): Promise<boolean> {\n throwInNonTTY({message: props.message, stdin: renderOptions?.stdin}, uiDebugOptions)\n\n return runWithTimer('cmd_all_timing_prompts_ms')(async () => {\n let confirmed: boolean\n await render(\n <DangerousConfirmationPrompt\n {...props}\n onSubmit={(value: boolean) => {\n confirmed = value\n }}\n />,\n {\n ...renderOptions,\n exitOnCtrlC: false,\n },\n )\n return confirmed!\n })\n}\n\n/** Waits for any key to be pressed except Ctrl+C which will terminate the process. */\n\nexport const keypress = async (stdin = process.stdin, uiDebugOptions: UIDebugOptions = defaultUIDebugOptions) => {\n throwInNonTTY({message: 'Press any key'}, uiDebugOptions)\n\n return runWithTimer('cmd_all_timing_prompts_ms')(() => {\n return new Promise((resolve, reject) => {\n const handler = (buffer: Buffer) => {\n stdin.setRawMode(false)\n\n const bytes = Array.from(buffer)\n\n if (bytes.length && bytes[0] === 3) {\n outputDebug('Canceled keypress, User pressed CTRL+C')\n reject(new AbortSilentError())\n }\n stdin.unref()\n process.nextTick(resolve)\n }\n\n stdin.setRawMode(true)\n stdin.once('data', handler)\n\n // We want to indicate that we're still using stdin, so that the process\n // doesn't exit early.\n stdin.ref()\n })\n })\n}\n\ninterface IsTTYOptions {\n stdin?: NodeJS.ReadStream\n uiDebugOptions?: UIDebugOptions\n}\n\nexport function isTTY({stdin = undefined, uiDebugOptions = defaultUIDebugOptions}: IsTTYOptions = {}) {\n // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- false should fall through to stdin/terminalSupportsPrompting\n return Boolean(uiDebugOptions.skipTTYCheck || stdin || terminalSupportsPrompting())\n}\n\ninterface ThrowInNonTTYOptions {\n message: TokenItem\n stdin?: NodeJS.ReadStream\n}\n\nfunction throwInNonTTY({message, stdin = undefined}: ThrowInNonTTYOptions, uiDebugOptions: UIDebugOptions) {\n if (isTTY({stdin, uiDebugOptions})) return\n\n const promptText = tokenItemToString(message)\n const errorMessage = `Failed to prompt:\n\n${outputContent`${outputToken.cyan(promptText)}`.value}\n\nThis usually happens when running a command non-interactively, for example in a CI environment, or when piping to or from another process.`\n throw new AbortError(\n errorMessage,\n 'To resolve this, specify the option in the command, or run the command in an interactive environment such as your local terminal.',\n )\n}\n\nexport type Key = InkKey\nexport type InfoMessage = InfoMessageProps['message']\nexport {Token, Task, TokenItem, InlineToken, LinkToken, TableColumn, InfoTableSection, ListToken, render, handleCtrlC}\n"]}
@@ -1,7 +1,7 @@
1
1
  import { assertConnectable, getIpFromHosts } from './network/index.js';
2
2
  import { assertCompatibleEnvironment } from './env.js';
3
- import * as ni from 'network-interfaces';
4
3
  import fs from 'node:fs';
4
+ import os from 'node:os';
5
5
  const NON_SHOP_PREFIXES = ['admin', 'app', 'dev', 'shopify'];
6
6
  const BACKEND_PORT = 8080;
7
7
  /**
@@ -42,13 +42,25 @@ function assertRunning2024(projectName) {
42
42
  function getBackendIp(projectName) {
43
43
  try {
44
44
  const backendIp = resolveBackendHost(projectName);
45
- ni.fromIp(backendIp, { internal: true, ipVersion: 4 });
45
+ assertInternalIpv4Address(backendIp);
46
46
  return backendIp;
47
47
  }
48
48
  catch (error) {
49
49
  throw new Error(`DevServer for '${projectName}' is not running: \`dev up ${projectName}\` to start it.`);
50
50
  }
51
51
  }
52
+ // NOTE TO UPDATERS: this IP validation exists only in this vendored copy. Upstream
53
+ // (Shopify/dev_server) resolves a hostname with getBackendHost and never validates IPs.
54
+ // The check was added when vendoring, first with the `network-interfaces` package and
55
+ // later with this dependency-free helper. Keep it if you sync a newer version of the file.
56
+ function assertInternalIpv4Address(ip) {
57
+ const matches = Object.values(os.networkInterfaces())
58
+ .flat()
59
+ .some((iface) => iface?.internal && iface.family === 'IPv4' && iface.address === ip);
60
+ if (!matches) {
61
+ throw new Error(`No internal IPv4 network interface has the address '${ip}'`);
62
+ }
63
+ }
52
64
  function resolveBackendHost(name) {
53
65
  let host;
54
66
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"dev-server-2024.js","sourceRoot":"","sources":["../../../../../src/public/node/vendor/dev_server/dev-server-2024.ts"],"names":[],"mappings":"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","sourcesContent":["import {assertConnectable, getIpFromHosts} from './network/index.js'\nimport {assertCompatibleEnvironment} from './env.js'\nimport * as ni from 'network-interfaces'\nimport fs from 'node:fs'\n\nimport type {HostOptions} from './types.js'\n\nconst NON_SHOP_PREFIXES = ['admin', 'app', 'dev', 'shopify']\nconst BACKEND_PORT = 8080\n\n/**\n *\n * @param projectName\n */\nexport function createServer(projectName: string) {\n return {\n host: (options: HostOptions = {}) => host(projectName, options),\n url: (options: HostOptions = {}) => url(projectName, options),\n }\n}\n\nfunction host(projectName: string, options: HostOptions = {}): string {\n assertCompatibleEnvironment()\n ;(assertRunningOverride || assertRunning2024)(projectName)\n\n const prefix = (options.nonstandardHostPrefix || projectName).replace(/_/g, '-')\n\n if (projectName === 'shopify') {\n if (prefix.endsWith('-dev-api')) {\n const shopName = prefix.replace('-dev-api', '')\n return `${shopName}.dev-api.shop.dev`\n }\n if (!NON_SHOP_PREFIXES.includes(prefix)) {\n return `${prefix}.my.shop.dev`\n }\n }\n return `${prefix}.shop.dev`\n}\n\nfunction url(projectName: string, options: HostOptions = {}): string {\n return `https://${host(projectName, options)}`\n}\n\nfunction assertRunning2024(projectName: string): void {\n assertConnectable({\n projectName,\n addr: getBackendIp(projectName),\n port: BACKEND_PORT,\n })\n}\n\nfunction getBackendIp(projectName: string): string {\n try {\n const backendIp = resolveBackendHost(projectName)\n ni.fromIp(backendIp, {internal: true, ipVersion: 4})\n\n return backendIp\n } catch (error) {\n throw new Error(`DevServer for '${projectName}' is not running: \\`dev up ${projectName}\\` to start it.`)\n }\n}\n\nfunction resolveBackendHost(name: string): string {\n let host: string\n try {\n host = fs.readlinkSync(`/opt/nginx/etc/manifest/${name}/current`)\n } catch (error) {\n host = `${name}.root.shopify.dev.internal`\n }\n\n try {\n return getIpFromHosts(host)\n } catch {\n return host\n }\n}\n\n// Allow overrides for more concise test setup. Meh.\nlet assertRunningOverride: typeof assertRunning2024 | undefined\n\n/**\n *\n * @param override\n */\nexport function setAssertRunning(override: typeof assertRunningOverride) {\n assertRunningOverride = override\n}\n"]}
1
+ {"version":3,"file":"dev-server-2024.js","sourceRoot":"","sources":["../../../../../src/public/node/vendor/dev_server/dev-server-2024.ts"],"names":[],"mappings":"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","sourcesContent":["import {assertConnectable, getIpFromHosts} from './network/index.js'\nimport {assertCompatibleEnvironment} from './env.js'\nimport fs from 'node:fs'\nimport os from 'node:os'\n\nimport type {HostOptions} from './types.js'\n\nconst NON_SHOP_PREFIXES = ['admin', 'app', 'dev', 'shopify']\nconst BACKEND_PORT = 8080\n\n/**\n *\n * @param projectName\n */\nexport function createServer(projectName: string) {\n return {\n host: (options: HostOptions = {}) => host(projectName, options),\n url: (options: HostOptions = {}) => url(projectName, options),\n }\n}\n\nfunction host(projectName: string, options: HostOptions = {}): string {\n assertCompatibleEnvironment()\n ;(assertRunningOverride || assertRunning2024)(projectName)\n\n const prefix = (options.nonstandardHostPrefix || projectName).replace(/_/g, '-')\n\n if (projectName === 'shopify') {\n if (prefix.endsWith('-dev-api')) {\n const shopName = prefix.replace('-dev-api', '')\n return `${shopName}.dev-api.shop.dev`\n }\n if (!NON_SHOP_PREFIXES.includes(prefix)) {\n return `${prefix}.my.shop.dev`\n }\n }\n return `${prefix}.shop.dev`\n}\n\nfunction url(projectName: string, options: HostOptions = {}): string {\n return `https://${host(projectName, options)}`\n}\n\nfunction assertRunning2024(projectName: string): void {\n assertConnectable({\n projectName,\n addr: getBackendIp(projectName),\n port: BACKEND_PORT,\n })\n}\n\nfunction getBackendIp(projectName: string): string {\n try {\n const backendIp = resolveBackendHost(projectName)\n assertInternalIpv4Address(backendIp)\n\n return backendIp\n } catch (error) {\n throw new Error(`DevServer for '${projectName}' is not running: \\`dev up ${projectName}\\` to start it.`)\n }\n}\n\n// NOTE TO UPDATERS: this IP validation exists only in this vendored copy. Upstream\n// (Shopify/dev_server) resolves a hostname with getBackendHost and never validates IPs.\n// The check was added when vendoring, first with the `network-interfaces` package and\n// later with this dependency-free helper. Keep it if you sync a newer version of the file.\nfunction assertInternalIpv4Address(ip: string): void {\n const matches = Object.values(os.networkInterfaces())\n .flat()\n .some((iface) => iface?.internal && iface.family === 'IPv4' && iface.address === ip)\n if (!matches) {\n throw new Error(`No internal IPv4 network interface has the address '${ip}'`)\n }\n}\n\nfunction resolveBackendHost(name: string): string {\n let host: string\n try {\n host = fs.readlinkSync(`/opt/nginx/etc/manifest/${name}/current`)\n } catch (error) {\n host = `${name}.root.shopify.dev.internal`\n }\n\n try {\n return getIpFromHosts(host)\n } catch {\n return host\n }\n}\n\n// Allow overrides for more concise test setup. Meh.\nlet assertRunningOverride: typeof assertRunning2024 | undefined\n\n/**\n *\n * @param override\n */\nexport function setAssertRunning(override: typeof assertRunningOverride) {\n assertRunningOverride = override\n}\n"]}
@@ -3,6 +3,8 @@ import { createServer as createServer2016 } from './dev-server-2016.js';
3
3
  import fs from 'node:fs';
4
4
  export { isDevServerEnvironment } from './env.js';
5
5
  export class DevServer {
6
+ projectName;
7
+ serverImpl;
6
8
  constructor(projectName) {
7
9
  this.projectName = projectName;
8
10
  if (projectName === 'shopify') {
@@ -18,6 +20,7 @@ export class DevServer {
18
20
  }
19
21
  }
20
22
  export class DevServerCore {
23
+ serverImpl;
21
24
  constructor() {
22
25
  this.serverImpl = inferProjectServer('shopify');
23
26
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dev-server.js","sourceRoot":"","sources":["../../../../../src/public/node/vendor/dev_server/dev-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,IAAI,gBAAgB,EAAC,MAAM,sBAAsB,CAAA;AACrE,OAAO,EAAC,YAAY,IAAI,gBAAgB,EAAC,MAAM,sBAAsB,CAAA;AACrE,OAAO,EAAE,MAAM,SAAS,CAAA;AAIxB,OAAO,EAAC,sBAAsB,EAAC,MAAM,UAAU,CAAA;AAE/C,MAAM,OAAO,SAAS;IAGpB,YAA6B,WAAmB;QAAnB,gBAAW,GAAX,WAAW,CAAQ;QAC9C,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAA;QAC3E,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAA;IACnD,CAAC;IAED,IAAI,CAAC,OAAqB;QACxB,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACtC,CAAC;IAED,GAAG,CAAC,OAAqB;QACvB,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IACrC,CAAC;CACF;AAED,MAAM,OAAO,aAAa;IAGxB;QACE,IAAI,CAAC,UAAU,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAA;IACjD,CAAC;IAED,IAAI,CAAC,MAAc;QACjB,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAC,qBAAqB,EAAE,MAAM,EAAC,CAAC,CAAA;IAC9D,CAAC;IAED,GAAG,CAAC,MAAc;QAChB,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAC,qBAAqB,EAAE,MAAM,EAAC,CAAC,CAAA;IAC7D,CAAC;CACF;AAED,MAAM,uBAAuB,GAAG,yCAAyC,CAAA;AAEzE,SAAS,kBAAkB,CAAC,WAAmB;IAC7C,IAAI,oCAAoC,CAAC,WAAW,CAAC,EAAE,CAAC;QACtD,OAAO,gBAAgB,CAAC,WAAW,CAAC,CAAA;IACtC,CAAC;SAAM,CAAC;QACN,OAAO,gBAAgB,CAAC,WAAW,CAAC,CAAA;IACtC,CAAC;AACH,CAAC;AAED,SAAS,oCAAoC,CAAC,WAAmB;IAC/D,IAAI,CAAC;QACH,EAAE,CAAC,UAAU,CAAC,uBAAuB,CAAC,CAAA;QAEtC,IAAI,CAAC;YACH,EAAE,CAAC,UAAU,CAAC,2BAA2B,WAAW,uBAAuB,CAAC,CAAA;YAC5E,OAAO,KAAK,CAAA;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC","sourcesContent":["import {createServer as createServer2024} from './dev-server-2024.js'\nimport {createServer as createServer2016} from './dev-server-2016.js'\nimport fs from 'node:fs'\n\nimport type {DevServer as DevServerType, DevServerCore as DevServerCoreType, HostOptions} from './types.js'\n\nexport {isDevServerEnvironment} from './env.js'\n\nexport class DevServer implements DevServerType {\n private readonly serverImpl: DevServerType\n\n constructor(private readonly projectName: string) {\n if (projectName === 'shopify') {\n throw new Error(\"Use `import {DevServerCore}` for the 'shopify' project\")\n }\n this.serverImpl = inferProjectServer(projectName)\n }\n\n host(options?: HostOptions) {\n return this.serverImpl.host(options)\n }\n\n url(options?: HostOptions) {\n return this.serverImpl.url(options)\n }\n}\n\nexport class DevServerCore implements DevServerCoreType {\n private readonly serverImpl: DevServerType\n\n constructor() {\n this.serverImpl = inferProjectServer('shopify')\n }\n\n host(prefix: string) {\n return this.serverImpl.host({nonstandardHostPrefix: prefix})\n }\n\n url(prefix: string) {\n return this.serverImpl.url({nonstandardHostPrefix: prefix})\n }\n}\n\nconst INFERENCE_MODE_SENTINEL = '/opt/dev/misc/dev-server-inference-mode'\n\nfunction inferProjectServer(projectName: string) {\n if (inferenceModeAndProjectIsEdition2016(projectName)) {\n return createServer2016(projectName)\n } else {\n return createServer2024(projectName)\n }\n}\n\nfunction inferenceModeAndProjectIsEdition2016(projectName: string): boolean {\n try {\n fs.accessSync(INFERENCE_MODE_SENTINEL)\n\n try {\n fs.accessSync(`/opt/nginx/etc/manifest/${projectName}/current/edition-2024`)\n return false\n } catch {\n return true\n }\n } catch {\n return false\n }\n}\n"]}
1
+ {"version":3,"file":"dev-server.js","sourceRoot":"","sources":["../../../../../src/public/node/vendor/dev_server/dev-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,IAAI,gBAAgB,EAAC,MAAM,sBAAsB,CAAA;AACrE,OAAO,EAAC,YAAY,IAAI,gBAAgB,EAAC,MAAM,sBAAsB,CAAA;AACrE,OAAO,EAAE,MAAM,SAAS,CAAA;AAIxB,OAAO,EAAC,sBAAsB,EAAC,MAAM,UAAU,CAAA;AAE/C,MAAM,OAAO,SAAS;IAGS;IAFZ,UAAU,CAAe;IAE1C,YAA6B,WAAmB;QAAnB,gBAAW,GAAX,WAAW,CAAQ;QAC9C,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAA;QAC3E,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAA;IACnD,CAAC;IAED,IAAI,CAAC,OAAqB;QACxB,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACtC,CAAC;IAED,GAAG,CAAC,OAAqB;QACvB,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IACrC,CAAC;CACF;AAED,MAAM,OAAO,aAAa;IACP,UAAU,CAAe;IAE1C;QACE,IAAI,CAAC,UAAU,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAA;IACjD,CAAC;IAED,IAAI,CAAC,MAAc;QACjB,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAC,qBAAqB,EAAE,MAAM,EAAC,CAAC,CAAA;IAC9D,CAAC;IAED,GAAG,CAAC,MAAc;QAChB,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAC,qBAAqB,EAAE,MAAM,EAAC,CAAC,CAAA;IAC7D,CAAC;CACF;AAED,MAAM,uBAAuB,GAAG,yCAAyC,CAAA;AAEzE,SAAS,kBAAkB,CAAC,WAAmB;IAC7C,IAAI,oCAAoC,CAAC,WAAW,CAAC,EAAE,CAAC;QACtD,OAAO,gBAAgB,CAAC,WAAW,CAAC,CAAA;IACtC,CAAC;SAAM,CAAC;QACN,OAAO,gBAAgB,CAAC,WAAW,CAAC,CAAA;IACtC,CAAC;AACH,CAAC;AAED,SAAS,oCAAoC,CAAC,WAAmB;IAC/D,IAAI,CAAC;QACH,EAAE,CAAC,UAAU,CAAC,uBAAuB,CAAC,CAAA;QAEtC,IAAI,CAAC;YACH,EAAE,CAAC,UAAU,CAAC,2BAA2B,WAAW,uBAAuB,CAAC,CAAA;YAC5E,OAAO,KAAK,CAAA;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC","sourcesContent":["import {createServer as createServer2024} from './dev-server-2024.js'\nimport {createServer as createServer2016} from './dev-server-2016.js'\nimport fs from 'node:fs'\n\nimport type {DevServer as DevServerType, DevServerCore as DevServerCoreType, HostOptions} from './types.js'\n\nexport {isDevServerEnvironment} from './env.js'\n\nexport class DevServer implements DevServerType {\n private readonly serverImpl: DevServerType\n\n constructor(private readonly projectName: string) {\n if (projectName === 'shopify') {\n throw new Error(\"Use `import {DevServerCore}` for the 'shopify' project\")\n }\n this.serverImpl = inferProjectServer(projectName)\n }\n\n host(options?: HostOptions) {\n return this.serverImpl.host(options)\n }\n\n url(options?: HostOptions) {\n return this.serverImpl.url(options)\n }\n}\n\nexport class DevServerCore implements DevServerCoreType {\n private readonly serverImpl: DevServerType\n\n constructor() {\n this.serverImpl = inferProjectServer('shopify')\n }\n\n host(prefix: string) {\n return this.serverImpl.host({nonstandardHostPrefix: prefix})\n }\n\n url(prefix: string) {\n return this.serverImpl.url({nonstandardHostPrefix: prefix})\n }\n}\n\nconst INFERENCE_MODE_SENTINEL = '/opt/dev/misc/dev-server-inference-mode'\n\nfunction inferProjectServer(projectName: string) {\n if (inferenceModeAndProjectIsEdition2016(projectName)) {\n return createServer2016(projectName)\n } else {\n return createServer2024(projectName)\n }\n}\n\nfunction inferenceModeAndProjectIsEdition2016(projectName: string): boolean {\n try {\n fs.accessSync(INFERENCE_MODE_SENTINEL)\n\n try {\n fs.accessSync(`/opt/nginx/etc/manifest/${projectName}/current/edition-2024`)\n return false\n } catch {\n return true\n }\n } catch {\n return false\n }\n}\n"]}
@@ -9,7 +9,7 @@ let checkPort;
9
9
  * @param options
10
10
  */
11
11
  export function assertConnectable(options) {
12
- checkPort || (checkPort = getCheckPortHelper());
12
+ checkPort ||= getCheckPortHelper();
13
13
  const { port, addr, timeout = DEFAULT_CONNECT_TIMEOUT } = options;
14
14
  try {
15
15
  const normalizedAddr = addr === 'localhost' ? '127.0.0.1' : addr;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../src/public/node/vendor/dev_server/network/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,oBAAoB,CAAA;AAE5C,OAAO,EAAC,cAAc,EAAC,MAAM,WAAW,CAAA;AASxC,MAAM,uBAAuB,GAAG,IAAI,CAAA;AACpC,kFAAkF;AAClF,gDAAgD;AAChD,IAAI,SAAgD,CAAA;AAEpD;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAA4B;IAC5D,SAAS,KAAT,SAAS,GAAK,kBAAkB,EAAE,EAAA;IAElC,MAAM,EAAC,IAAI,EAAE,IAAI,EAAE,OAAO,GAAG,uBAAuB,EAAC,GAAG,OAAO,CAAA;IAC/D,IAAI,CAAC;QACH,MAAM,cAAc,GAAG,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAA;QAChE,MAAM,OAAO,GAAG,SAAS,CAAC,cAAc,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;QACxD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,kBAAkB,OAAO,CAAC,WAAW,uBAAuB,IAAI,MAAM,IAAI,cAAc,OAAO,CAAC,WAAW,iBAAiB,CAC7H,CAAA;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,wBAAwB,OAAO,CAAC,WAAW,QAAQ,IAAI,MAAM,IAAI,YAAY,GAAG,GAAG,CAAC,CAAA;IACtG,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB;IACrC,SAAS,GAAG,kBAAkB,EAAE,CAAA;AAClC,CAAC;AAED,SAAS,kBAAkB;IACzB,OAAO,iBAAiB,CAAA;AAC1B,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAe,EAAE,IAAY,EAAE,OAAe;IACvE,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE;QAC1E,OAAO;QACP,KAAK,EAAE,QAAQ;KAChB,CAAC,CAAA;IAEF,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,CAAA;AAC5B,CAAC","sourcesContent":["import {spawnSync} from 'node:child_process'\n\nexport {getIpFromHosts} from './host.js'\n\nexport interface ConnectionArguments {\n projectName: string\n addr: string\n port: number\n timeout?: number\n}\n\nconst DEFAULT_CONNECT_TIMEOUT = 1000\n// Skip initialization on module load to prevent Spin trying to load a macOS dylib\n// (port checks should never run on Spin anyway)\nlet checkPort: ReturnType<typeof getCheckPortHelper>\n\n/**\n *\n * @param options\n */\nexport function assertConnectable(options: ConnectionArguments): void {\n checkPort ||= getCheckPortHelper()\n\n const {port, addr, timeout = DEFAULT_CONNECT_TIMEOUT} = options\n try {\n const normalizedAddr = addr === 'localhost' ? '127.0.0.1' : addr\n const running = checkPort(normalizedAddr, port, timeout)\n if (!running) {\n throw new Error(\n `DevServer for '${options.projectName}' is not running on ${port} / ${addr}: \\`dev up ${options.projectName}\\` to start it.`,\n )\n }\n } catch (err) {\n throw new Error(`DevServer check for '${options.projectName}' on ${port} / ${addr} failed (${err})`)\n }\n}\n\n/**\n *\n */\nexport function TEST_testResetCheckPort(): void {\n checkPort = getCheckPortHelper()\n}\n\nfunction getCheckPortHelper(): (addr: string, port: number, timeout: number) => boolean {\n return fallbackCheckPort\n}\n\nfunction fallbackCheckPort(address: string, port: number, timeout: number): boolean {\n const result = spawnSync('nc', ['-z', '-w', '1', address, port.toString()], {\n timeout,\n stdio: 'ignore',\n })\n\n return result.status === 0\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../src/public/node/vendor/dev_server/network/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,oBAAoB,CAAA;AAE5C,OAAO,EAAC,cAAc,EAAC,MAAM,WAAW,CAAA;AASxC,MAAM,uBAAuB,GAAG,IAAI,CAAA;AACpC,kFAAkF;AAClF,gDAAgD;AAChD,IAAI,SAAgD,CAAA;AAEpD;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAA4B;IAC5D,SAAS,KAAK,kBAAkB,EAAE,CAAA;IAElC,MAAM,EAAC,IAAI,EAAE,IAAI,EAAE,OAAO,GAAG,uBAAuB,EAAC,GAAG,OAAO,CAAA;IAC/D,IAAI,CAAC;QACH,MAAM,cAAc,GAAG,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAA;QAChE,MAAM,OAAO,GAAG,SAAS,CAAC,cAAc,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;QACxD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,kBAAkB,OAAO,CAAC,WAAW,uBAAuB,IAAI,MAAM,IAAI,cAAc,OAAO,CAAC,WAAW,iBAAiB,CAC7H,CAAA;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,wBAAwB,OAAO,CAAC,WAAW,QAAQ,IAAI,MAAM,IAAI,YAAY,GAAG,GAAG,CAAC,CAAA;IACtG,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB;IACrC,SAAS,GAAG,kBAAkB,EAAE,CAAA;AAClC,CAAC;AAED,SAAS,kBAAkB;IACzB,OAAO,iBAAiB,CAAA;AAC1B,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAe,EAAE,IAAY,EAAE,OAAe;IACvE,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE;QAC1E,OAAO;QACP,KAAK,EAAE,QAAQ;KAChB,CAAC,CAAA;IAEF,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,CAAA;AAC5B,CAAC","sourcesContent":["import {spawnSync} from 'node:child_process'\n\nexport {getIpFromHosts} from './host.js'\n\nexport interface ConnectionArguments {\n projectName: string\n addr: string\n port: number\n timeout?: number\n}\n\nconst DEFAULT_CONNECT_TIMEOUT = 1000\n// Skip initialization on module load to prevent Spin trying to load a macOS dylib\n// (port checks should never run on Spin anyway)\nlet checkPort: ReturnType<typeof getCheckPortHelper>\n\n/**\n *\n * @param options\n */\nexport function assertConnectable(options: ConnectionArguments): void {\n checkPort ||= getCheckPortHelper()\n\n const {port, addr, timeout = DEFAULT_CONNECT_TIMEOUT} = options\n try {\n const normalizedAddr = addr === 'localhost' ? '127.0.0.1' : addr\n const running = checkPort(normalizedAddr, port, timeout)\n if (!running) {\n throw new Error(\n `DevServer for '${options.projectName}' is not running on ${port} / ${addr}: \\`dev up ${options.projectName}\\` to start it.`,\n )\n }\n } catch (err) {\n throw new Error(`DevServer check for '${options.projectName}' on ${port} / ${addr} failed (${err})`)\n }\n}\n\n/**\n *\n */\nexport function TEST_testResetCheckPort(): void {\n checkPort = getCheckPortHelper()\n}\n\nfunction getCheckPortHelper(): (addr: string, port: number, timeout: number) => boolean {\n return fallbackCheckPort\n}\n\nfunction fallbackCheckPort(address: string, port: number, timeout: number): boolean {\n const result = spawnSync('nc', ['-z', '-w', '1', address, port.toString()], {\n timeout,\n stdio: 'ignore',\n })\n\n return result.status === 0\n}\n"]}
@@ -3,6 +3,7 @@ import { MetricReader } from '@opentelemetry/sdk-metrics';
3
3
  import { ExportResultCode } from '@opentelemetry/core';
4
4
  import { diag } from '@opentelemetry/api';
5
5
  export class InstantaneousMetricReader extends MetricReader {
6
+ _exporter;
6
7
  constructor({ exporter, throttleLimit }) {
7
8
  super({
8
9
  aggregationSelector: exporter.selectAggregation?.bind(exporter),
@@ -1 +1 @@
1
- {"version":3,"file":"InstantaneousMetricReader.js","sourceRoot":"","sources":["../../../../../../src/public/node/vendor/otel-js/export/InstantaneousMetricReader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,sBAAsB,CAAA;AAC7C,OAAO,EAAC,YAAY,EAAC,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAC,gBAAgB,EAAC,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAC,IAAI,EAAC,MAAM,oBAAoB,CAAA;AAevC,MAAM,OAAO,yBAA0B,SAAQ,YAAY;IAGzD,YAAY,EAAC,QAAQ,EAAE,aAAa,EAAmC;QACrE,KAAK,CAAC;YACJ,mBAAmB,EAAE,QAAQ,CAAC,iBAAiB,EAAE,IAAI,CAAC,QAAQ,CAAC;YAC/D,8BAA8B,EAAE,QAAQ,CAAC,4BAA4B,EAAE,IAAI,CAAC,QAAQ,CAAC;SACtF,CAAC,CAAA;QACF,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAA;QAEzB,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,CAAA;IAChE,CAAC;IAES,KAAK,CAAC,YAAY;QAC1B,MAAM,EAAC,eAAe,EAAE,MAAM,EAAC,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAExD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,IAAI,CAAC,KAAK,CAAC,sDAAsD,EAAE,GAAG,MAAM,CAAC,CAAA;QAC/E,CAAC;QAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC,MAAM,EAAE,EAAE;gBAChD,IAAI,MAAM,CAAC,IAAI,KAAK,gBAAgB,CAAC,OAAO,EAAE,CAAC;oBAC7C,IAAI,CAAC,KAAK,CAAC,kDAAkD,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;gBAC9E,CAAC;gBACD,OAAO,EAAE,CAAA;YACX,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC;IAES,KAAK,CAAC,UAAU;QACxB,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAA;IACjC,CAAC;CACF","sourcesContent":["import {throttle} from '../utils/throttle.js'\nimport {MetricReader} from '@opentelemetry/sdk-metrics'\nimport {ExportResultCode} from '@opentelemetry/core'\nimport {diag} from '@opentelemetry/api'\nimport type {PushMetricExporter} from '@opentelemetry/sdk-metrics'\n\nexport interface InstantaneousMetricReaderOptions {\n /**\n * The backing exporter for the metric reader.\n */\n exporter: PushMetricExporter\n\n /**\n * How much the export should be throttled in milliseconds.\n */\n throttleLimit: number\n}\n\nexport class InstantaneousMetricReader extends MetricReader {\n private readonly _exporter: PushMetricExporter\n\n constructor({exporter, throttleLimit}: InstantaneousMetricReaderOptions) {\n super({\n aggregationSelector: exporter.selectAggregation?.bind(exporter),\n aggregationTemporalitySelector: exporter.selectAggregationTemporality?.bind(exporter),\n })\n this._exporter = exporter\n\n this.onForceFlush = throttle(this.onForceFlush, throttleLimit)\n }\n\n protected async onForceFlush(): Promise<void> {\n const {resourceMetrics, errors} = await this.collect({})\n\n if (errors.length > 0) {\n diag.error('InstantaneousMetricReader: metrics collection errors', ...errors)\n }\n\n return new Promise((resolve) => {\n this._exporter.export(resourceMetrics, (result) => {\n if (result.code !== ExportResultCode.SUCCESS) {\n diag.error('InstantaneousMetricReader: metrics export failed', result.error)\n }\n resolve()\n })\n })\n }\n\n protected async onShutdown(): Promise<void> {\n await this._exporter.shutdown()\n }\n}\n"]}
1
+ {"version":3,"file":"InstantaneousMetricReader.js","sourceRoot":"","sources":["../../../../../../src/public/node/vendor/otel-js/export/InstantaneousMetricReader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,sBAAsB,CAAA;AAC7C,OAAO,EAAC,YAAY,EAAC,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAC,gBAAgB,EAAC,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAC,IAAI,EAAC,MAAM,oBAAoB,CAAA;AAevC,MAAM,OAAO,yBAA0B,SAAQ,YAAY;IACxC,SAAS,CAAoB;IAE9C,YAAY,EAAC,QAAQ,EAAE,aAAa,EAAmC;QACrE,KAAK,CAAC;YACJ,mBAAmB,EAAE,QAAQ,CAAC,iBAAiB,EAAE,IAAI,CAAC,QAAQ,CAAC;YAC/D,8BAA8B,EAAE,QAAQ,CAAC,4BAA4B,EAAE,IAAI,CAAC,QAAQ,CAAC;SACtF,CAAC,CAAA;QACF,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAA;QAEzB,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,CAAA;IAChE,CAAC;IAES,KAAK,CAAC,YAAY;QAC1B,MAAM,EAAC,eAAe,EAAE,MAAM,EAAC,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAExD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,IAAI,CAAC,KAAK,CAAC,sDAAsD,EAAE,GAAG,MAAM,CAAC,CAAA;QAC/E,CAAC;QAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC,MAAM,EAAE,EAAE;gBAChD,IAAI,MAAM,CAAC,IAAI,KAAK,gBAAgB,CAAC,OAAO,EAAE,CAAC;oBAC7C,IAAI,CAAC,KAAK,CAAC,kDAAkD,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;gBAC9E,CAAC;gBACD,OAAO,EAAE,CAAA;YACX,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC;IAES,KAAK,CAAC,UAAU;QACxB,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAA;IACjC,CAAC;CACF","sourcesContent":["import {throttle} from '../utils/throttle.js'\nimport {MetricReader} from '@opentelemetry/sdk-metrics'\nimport {ExportResultCode} from '@opentelemetry/core'\nimport {diag} from '@opentelemetry/api'\nimport type {PushMetricExporter} from '@opentelemetry/sdk-metrics'\n\nexport interface InstantaneousMetricReaderOptions {\n /**\n * The backing exporter for the metric reader.\n */\n exporter: PushMetricExporter\n\n /**\n * How much the export should be throttled in milliseconds.\n */\n throttleLimit: number\n}\n\nexport class InstantaneousMetricReader extends MetricReader {\n private readonly _exporter: PushMetricExporter\n\n constructor({exporter, throttleLimit}: InstantaneousMetricReaderOptions) {\n super({\n aggregationSelector: exporter.selectAggregation?.bind(exporter),\n aggregationTemporalitySelector: exporter.selectAggregationTemporality?.bind(exporter),\n })\n this._exporter = exporter\n\n this.onForceFlush = throttle(this.onForceFlush, throttleLimit)\n }\n\n protected async onForceFlush(): Promise<void> {\n const {resourceMetrics, errors} = await this.collect({})\n\n if (errors.length > 0) {\n diag.error('InstantaneousMetricReader: metrics collection errors', ...errors)\n }\n\n return new Promise((resolve) => {\n this._exporter.export(resourceMetrics, (result) => {\n if (result.code !== ExportResultCode.SUCCESS) {\n diag.error('InstantaneousMetricReader: metrics export failed', result.error)\n }\n resolve()\n })\n })\n }\n\n protected async onShutdown(): Promise<void> {\n await this._exporter.shutdown()\n }\n}\n"]}
@@ -3,6 +3,11 @@ import { isValidMetricName } from '../../utils/validators.js';
3
3
  import { ExplicitBucketHistogramAggregation, View } from '@opentelemetry/sdk-metrics';
4
4
  const instrumentationScope = 'opentelemetry-js-shopify-web';
5
5
  export class BaseOtelService {
6
+ serviceName;
7
+ prefixMetric;
8
+ meterProvider;
9
+ metrics = new Map();
10
+ recordListeners = new Set();
6
11
  /**
7
12
  * Bootstraps an Otel exporter which can send Otel metrics to a dedicated Shopify supported collector endpoint.
8
13
  *
@@ -14,8 +19,6 @@ export class BaseOtelService {
14
19
  * @param root0.meterProvider
15
20
  */
16
21
  constructor({ serviceName, prefixMetric = false, metrics = {}, onRecord, meterProvider }) {
17
- this.metrics = new Map();
18
- this.recordListeners = new Set();
19
22
  if (!serviceName) {
20
23
  throw new Error('Service name is required.');
21
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"BaseOtelService.js","sourceRoot":"","sources":["../../../../../../../src/public/node/vendor/otel-js/service/BaseOtelService/BaseOtelService.ts"],"names":[],"mappings":"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","sourcesContent":["import {MetricInstrumentType} from '../types.js'\nimport {isValidMetricName} from '../../utils/validators.js'\nimport {ExplicitBucketHistogramAggregation, View} from '@opentelemetry/sdk-metrics'\nimport type {MetricAttributes} from '@opentelemetry/api'\nimport type {MeterProvider, ViewOptions} from '@opentelemetry/sdk-metrics'\n\nimport type {\n MetricDescriptor,\n MetricRecording,\n MetricsConfig,\n OnRecordCallback,\n OtelService,\n RecordMetricFunction,\n} from '../types.js'\n\nconst instrumentationScope = 'opentelemetry-js-shopify-web'\n\nexport interface BaseOtelServiceOptions {\n /**\n * Service name is a unique name for an application/service.\n */\n serviceName: string\n\n /**\n * If this is set to true then the service name is prefixed to every metric.\n */\n prefixMetric?: boolean\n\n /**\n * Metrics to register on startup.\n */\n metrics?: MetricsConfig\n\n /**\n * Called when a metric is recorded. `addOnRecord` can also be used to add\n * listeners anytime.\n */\n onRecord?: OnRecordCallback\n\n /**\n * Override the default meter provider.\n */\n meterProvider?: MeterProvider\n}\n\nexport class BaseOtelService implements OtelService {\n readonly serviceName: string\n readonly prefixMetric: boolean\n\n protected readonly meterProvider: MeterProvider\n protected readonly metrics: Map<string, RecordMetricFunction> = new Map()\n protected readonly recordListeners = new Set<OnRecordCallback>()\n\n /**\n * Bootstraps an Otel exporter which can send Otel metrics to a dedicated Shopify supported collector endpoint.\n *\n * @param root0\n * @param root0.serviceName\n * @param root0.prefixMetric\n * @param root0.metrics\n * @param root0.onRecord\n * @param root0.meterProvider\n */\n constructor({serviceName, prefixMetric = false, metrics = {}, onRecord, meterProvider}: BaseOtelServiceOptions) {\n if (!serviceName) {\n throw new Error('Service name is required.')\n }\n this.serviceName = serviceName\n\n this.prefixMetric = prefixMetric\n if (onRecord) this.addOnRecord(onRecord)\n\n if (!meterProvider) {\n throw new Error('MeterProvider is required.')\n }\n this.meterProvider = meterProvider\n\n this.register(metrics)\n }\n\n getMeterProvider(): MeterProvider {\n return this.meterProvider\n }\n\n addView(viewOptions: ViewOptions) {\n // The API to register view is not yet exposed. We need to use the private\n // property to register a new view after the initial instantiation.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(this.meterProvider as any)._sharedState?.viewRegistry?.addView?.(new View(viewOptions))\n }\n\n record(metricName: string, value: number, labels?: MetricAttributes): void {\n const recordMetric = this.metrics.get(metricName)\n if (!recordMetric) {\n throw new Error(\n `Service ${this.serviceName} has no metrics registered for name: ${metricName}. Can't record value for unknown metric.`,\n )\n }\n recordMetric(value, labels)\n }\n\n registerMetric(metricName: string, {type, ...options}: MetricDescriptor): void {\n if (this.metrics.has(metricName)) {\n return\n }\n const meter = this.meterProvider.getMeter(instrumentationScope)\n const name = this.prefixMetric ? `${this.serviceName}_${metricName}` : metricName\n\n if (!isValidMetricName(name)) {\n return\n }\n\n const createInstrument = () => {\n switch (type) {\n case MetricInstrumentType.Counter:\n return meter.createCounter(name, options)\n case MetricInstrumentType.UpDownCounter:\n return meter.createUpDownCounter(name, options)\n case MetricInstrumentType.Histogram: {\n if ('boundaries' in options) {\n this.addView({\n instrumentName: name,\n aggregation: new ExplicitBucketHistogramAggregation(options.boundaries, true),\n })\n }\n return meter.createHistogram(name, options)\n }\n }\n }\n\n // Lazy instantiate the instrument so we don't create it if we don't need to\n this.metrics.set(metricName, (firstValue: number, firstLabels?: MetricAttributes) => {\n const instrument = createInstrument()\n const record = (value: number, labels?: MetricAttributes) => {\n const [finalValue, finalLabels] = this.notifyRecordListeners(\n metricName,\n value,\n // ensures an new object is created so we don't mutate the original\n {...labels},\n )\n if ('record' in instrument) {\n instrument.record(finalValue, finalLabels)\n } else {\n instrument.add(finalValue, finalLabels)\n }\n // We flush metrics after every record - we do not await as we fire & forget.\n // Catch any export errors to prevent unhandled rejections from crashing the CLI\n void this.meterProvider.forceFlush({}).catch(() => {})\n }\n record(firstValue, firstLabels)\n this.metrics.set(metricName, record)\n })\n }\n\n register(metrics: MetricsConfig) {\n Object.entries(metrics).forEach(([metricName, options]) => {\n this.registerMetric(metricName, options)\n })\n }\n\n addOnRecord(onRecord: OnRecordCallback): () => void {\n this.recordListeners.add(onRecord)\n return () => {\n this.recordListeners.delete(onRecord)\n }\n }\n\n removeOnRecord(onRecord: OnRecordCallback): void {\n this.recordListeners.delete(onRecord)\n }\n\n shutdown(): Promise<void> {\n this.metrics.clear()\n this.recordListeners.clear()\n return this.meterProvider.shutdown()\n }\n\n protected notifyRecordListeners(metricName: string, initialValue: number, initialLabels: MetricAttributes) {\n return Array.from(this.recordListeners).reduce<MetricRecording>(\n (recordArgs, listener) => {\n return listener(metricName, ...recordArgs) || recordArgs\n },\n [initialValue, initialLabels],\n )\n }\n}\n"]}
1
+ {"version":3,"file":"BaseOtelService.js","sourceRoot":"","sources":["../../../../../../../src/public/node/vendor/otel-js/service/BaseOtelService/BaseOtelService.ts"],"names":[],"mappings":"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","sourcesContent":["import {MetricInstrumentType} from '../types.js'\nimport {isValidMetricName} from '../../utils/validators.js'\nimport {ExplicitBucketHistogramAggregation, View} from '@opentelemetry/sdk-metrics'\nimport type {MetricAttributes} from '@opentelemetry/api'\nimport type {MeterProvider, ViewOptions} from '@opentelemetry/sdk-metrics'\n\nimport type {\n MetricDescriptor,\n MetricRecording,\n MetricsConfig,\n OnRecordCallback,\n OtelService,\n RecordMetricFunction,\n} from '../types.js'\n\nconst instrumentationScope = 'opentelemetry-js-shopify-web'\n\nexport interface BaseOtelServiceOptions {\n /**\n * Service name is a unique name for an application/service.\n */\n serviceName: string\n\n /**\n * If this is set to true then the service name is prefixed to every metric.\n */\n prefixMetric?: boolean\n\n /**\n * Metrics to register on startup.\n */\n metrics?: MetricsConfig\n\n /**\n * Called when a metric is recorded. `addOnRecord` can also be used to add\n * listeners anytime.\n */\n onRecord?: OnRecordCallback\n\n /**\n * Override the default meter provider.\n */\n meterProvider?: MeterProvider\n}\n\nexport class BaseOtelService implements OtelService {\n readonly serviceName: string\n readonly prefixMetric: boolean\n\n protected readonly meterProvider: MeterProvider\n protected readonly metrics: Map<string, RecordMetricFunction> = new Map()\n protected readonly recordListeners = new Set<OnRecordCallback>()\n\n /**\n * Bootstraps an Otel exporter which can send Otel metrics to a dedicated Shopify supported collector endpoint.\n *\n * @param root0\n * @param root0.serviceName\n * @param root0.prefixMetric\n * @param root0.metrics\n * @param root0.onRecord\n * @param root0.meterProvider\n */\n constructor({serviceName, prefixMetric = false, metrics = {}, onRecord, meterProvider}: BaseOtelServiceOptions) {\n if (!serviceName) {\n throw new Error('Service name is required.')\n }\n this.serviceName = serviceName\n\n this.prefixMetric = prefixMetric\n if (onRecord) this.addOnRecord(onRecord)\n\n if (!meterProvider) {\n throw new Error('MeterProvider is required.')\n }\n this.meterProvider = meterProvider\n\n this.register(metrics)\n }\n\n getMeterProvider(): MeterProvider {\n return this.meterProvider\n }\n\n addView(viewOptions: ViewOptions) {\n // The API to register view is not yet exposed. We need to use the private\n // property to register a new view after the initial instantiation.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(this.meterProvider as any)._sharedState?.viewRegistry?.addView?.(new View(viewOptions))\n }\n\n record(metricName: string, value: number, labels?: MetricAttributes): void {\n const recordMetric = this.metrics.get(metricName)\n if (!recordMetric) {\n throw new Error(\n `Service ${this.serviceName} has no metrics registered for name: ${metricName}. Can't record value for unknown metric.`,\n )\n }\n recordMetric(value, labels)\n }\n\n registerMetric(metricName: string, {type, ...options}: MetricDescriptor): void {\n if (this.metrics.has(metricName)) {\n return\n }\n const meter = this.meterProvider.getMeter(instrumentationScope)\n const name = this.prefixMetric ? `${this.serviceName}_${metricName}` : metricName\n\n if (!isValidMetricName(name)) {\n return\n }\n\n const createInstrument = () => {\n switch (type) {\n case MetricInstrumentType.Counter:\n return meter.createCounter(name, options)\n case MetricInstrumentType.UpDownCounter:\n return meter.createUpDownCounter(name, options)\n case MetricInstrumentType.Histogram: {\n if ('boundaries' in options) {\n this.addView({\n instrumentName: name,\n aggregation: new ExplicitBucketHistogramAggregation(options.boundaries, true),\n })\n }\n return meter.createHistogram(name, options)\n }\n }\n }\n\n // Lazy instantiate the instrument so we don't create it if we don't need to\n this.metrics.set(metricName, (firstValue: number, firstLabels?: MetricAttributes) => {\n const instrument = createInstrument()\n const record = (value: number, labels?: MetricAttributes) => {\n const [finalValue, finalLabels] = this.notifyRecordListeners(\n metricName,\n value,\n // ensures an new object is created so we don't mutate the original\n {...labels},\n )\n if ('record' in instrument) {\n instrument.record(finalValue, finalLabels)\n } else {\n instrument.add(finalValue, finalLabels)\n }\n // We flush metrics after every record - we do not await as we fire & forget.\n // Catch any export errors to prevent unhandled rejections from crashing the CLI\n void this.meterProvider.forceFlush({}).catch(() => {})\n }\n record(firstValue, firstLabels)\n this.metrics.set(metricName, record)\n })\n }\n\n register(metrics: MetricsConfig) {\n Object.entries(metrics).forEach(([metricName, options]) => {\n this.registerMetric(metricName, options)\n })\n }\n\n addOnRecord(onRecord: OnRecordCallback): () => void {\n this.recordListeners.add(onRecord)\n return () => {\n this.recordListeners.delete(onRecord)\n }\n }\n\n removeOnRecord(onRecord: OnRecordCallback): void {\n this.recordListeners.delete(onRecord)\n }\n\n shutdown(): Promise<void> {\n this.metrics.clear()\n this.recordListeners.clear()\n return this.meterProvider.shutdown()\n }\n\n protected notifyRecordListeners(metricName: string, initialValue: number, initialLabels: MetricAttributes) {\n return Array.from(this.recordListeners).reduce<MetricRecording>(\n (recordArgs, listener) => {\n return listener(metricName, ...recordArgs) || recordArgs\n },\n [initialValue, initialLabels],\n )\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
- import type { Counter, Histogram, MeterProvider, MetricAttributes, MetricOptions, UpDownCounter } from '@opentelemetry/api';
2
- import type { ViewOptions } from '@opentelemetry/sdk-metrics';
1
+ import type { Counter, Histogram, MetricAttributes, MetricOptions, UpDownCounter } from '@opentelemetry/api';
2
+ import type { MeterProvider, ViewOptions } from '@opentelemetry/sdk-metrics';
3
3
  export type CustomMetricLabels<TLabels extends Record<TKeys, MetricAttributes>, TKeys extends string = keyof TLabels & string> = {
4
4
  [P in TKeys]: TLabels[P] extends MetricAttributes ? TLabels[P] : never;
5
5
  };
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../../src/public/node/vendor/otel-js/service/types.ts"],"names":[],"mappings":"AA8BA,MAAM,CAAN,IAAY,oBAIX;AAJD,WAAY,oBAAoB;IAC9B,+CAAuB,CAAA;IACvB,2CAAmB,CAAA;IACnB,uDAA+B,CAAA;AACjC,CAAC,EAJW,oBAAoB,KAApB,oBAAoB,QAI/B","sourcesContent":["import type {\n Counter,\n Histogram,\n MeterProvider,\n MetricAttributes,\n MetricOptions,\n UpDownCounter,\n} from '@opentelemetry/api'\nimport type {ViewOptions} from '@opentelemetry/sdk-metrics'\n\nexport type CustomMetricLabels<\n TLabels extends Record<TKeys, MetricAttributes>,\n TKeys extends string = keyof TLabels & string,\n> = {\n [P in TKeys]: TLabels[P] extends MetricAttributes ? TLabels[P] : never\n}\n\nexport type MetricRecording<TAttributes extends MetricAttributes = MetricAttributes> = [value: number, labels?: TAttributes]\n\nexport type RecordMetricFunction<TAttributes extends MetricAttributes = MetricAttributes> = (\n ...args: MetricRecording<TAttributes>\n) => void\n\nexport type OnRecordCallback<TAttributes extends MetricAttributes = MetricAttributes> = (\n metricName: string,\n ...args: MetricRecording<TAttributes>\n) => MetricRecording<TAttributes> | void\n\nexport type MetricInstrument = Histogram | Counter | UpDownCounter\n\nexport enum MetricInstrumentType {\n Histogram = 'Histogram',\n Counter = 'Counter',\n UpDownCounter = 'UpDownCounter',\n}\n\nexport type MetricDescriptor = MetricOptions &\n (\n | {\n type: MetricInstrumentType.Histogram\n /**\n * Boundaries are required for Histograms.\n */\n boundaries: number[]\n }\n | {\n type: MetricInstrumentType.Counter | MetricInstrumentType.UpDownCounter\n }\n )\n\nexport type MetricsConfig = Record<string, MetricDescriptor>\n\nexport interface OtelService {\n readonly serviceName: string\n\n getMeterProvider(): MeterProvider\n\n addView(viewOptions: ViewOptions): void\n\n record<TAttributes extends MetricAttributes = MetricAttributes>(...args: Parameters<OnRecordCallback<TAttributes>>): void\n\n /**\n * `onRecord` callback is called when a metric is recorded.\n * Returns a function to unsubscribe.\n */\n addOnRecord(onRecord: OnRecordCallback): () => void\n\n removeOnRecord(onRecord: OnRecordCallback): void\n\n registerMetric(metricName: string, options: MetricDescriptor): void\n\n register(metrics: MetricsConfig): void\n\n shutdown(): Promise<void>\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../../src/public/node/vendor/otel-js/service/types.ts"],"names":[],"mappings":"AA6BA,MAAM,CAAN,IAAY,oBAIX;AAJD,WAAY,oBAAoB;IAC9B,+CAAuB,CAAA;IACvB,2CAAmB,CAAA;IACnB,uDAA+B,CAAA;AACjC,CAAC,EAJW,oBAAoB,KAApB,oBAAoB,QAI/B","sourcesContent":["import type {\n Counter,\n Histogram,\n MetricAttributes,\n MetricOptions,\n UpDownCounter,\n} from '@opentelemetry/api'\nimport type {MeterProvider, ViewOptions} from '@opentelemetry/sdk-metrics'\n\nexport type CustomMetricLabels<\n TLabels extends Record<TKeys, MetricAttributes>,\n TKeys extends string = keyof TLabels & string,\n> = {\n [P in TKeys]: TLabels[P] extends MetricAttributes ? TLabels[P] : never\n}\n\nexport type MetricRecording<TAttributes extends MetricAttributes = MetricAttributes> = [value: number, labels?: TAttributes]\n\nexport type RecordMetricFunction<TAttributes extends MetricAttributes = MetricAttributes> = (\n ...args: MetricRecording<TAttributes>\n) => void\n\nexport type OnRecordCallback<TAttributes extends MetricAttributes = MetricAttributes> = (\n metricName: string,\n ...args: MetricRecording<TAttributes>\n) => MetricRecording<TAttributes> | void\n\nexport type MetricInstrument = Histogram | Counter | UpDownCounter\n\nexport enum MetricInstrumentType {\n Histogram = 'Histogram',\n Counter = 'Counter',\n UpDownCounter = 'UpDownCounter',\n}\n\nexport type MetricDescriptor = MetricOptions &\n (\n | {\n type: MetricInstrumentType.Histogram\n /**\n * Boundaries are required for Histograms.\n */\n boundaries: number[]\n }\n | {\n type: MetricInstrumentType.Counter | MetricInstrumentType.UpDownCounter\n }\n )\n\nexport type MetricsConfig = Record<string, MetricDescriptor>\n\nexport interface OtelService {\n readonly serviceName: string\n\n getMeterProvider(): MeterProvider\n\n addView(viewOptions: ViewOptions): void\n\n record<TAttributes extends MetricAttributes = MetricAttributes>(...args: Parameters<OnRecordCallback<TAttributes>>): void\n\n /**\n * `onRecord` callback is called when a metric is recorded.\n * Returns a function to unsubscribe.\n */\n addOnRecord(onRecord: OnRecordCallback): () => void\n\n removeOnRecord(onRecord: OnRecordCallback): void\n\n registerMetric(metricName: string, options: MetricDescriptor): void\n\n register(metrics: MetricsConfig): void\n\n shutdown(): Promise<void>\n}\n"]}
@@ -25,18 +25,19 @@ export async function addRecommendedExtensions(directory, recommendations) {
25
25
  outputDebug(outputContent `Adding VSCode recommended extensions at ${outputToken.path(directory)}:
26
26
  ${outputToken.json(recommendations)}
27
27
  `);
28
+ if (!(await isVSCode(directory))) {
29
+ return;
30
+ }
28
31
  const extensionsPath = joinPath(directory, '.vscode/extensions.json');
29
- if (await isVSCode(directory)) {
30
- let originalExtensionsJson = { recommendations: [] };
31
- if (await fileExists(extensionsPath)) {
32
- const originalExtensionsFile = await readFile(extensionsPath);
33
- originalExtensionsJson = JSON.parse(originalExtensionsFile);
34
- }
35
- const newExtensionsJson = {
36
- ...originalExtensionsJson,
37
- recommendations: [...originalExtensionsJson.recommendations, ...recommendations],
38
- };
39
- await writeFile(extensionsPath, JSON.stringify(newExtensionsJson, null, 2));
32
+ let originalExtensionsJson = { recommendations: [] };
33
+ if (await fileExists(extensionsPath)) {
34
+ const originalExtensionsFile = await readFile(extensionsPath);
35
+ originalExtensionsJson = JSON.parse(originalExtensionsFile);
40
36
  }
37
+ const newExtensionsJson = {
38
+ ...originalExtensionsJson,
39
+ recommendations: [...originalExtensionsJson.recommendations, ...recommendations],
40
+ };
41
+ await writeFile(extensionsPath, JSON.stringify(newExtensionsJson, null, 2));
41
42
  }
42
43
  //# sourceMappingURL=vscode.js.map