@shopify/cli-kit 4.8.5 → 4.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/private/node/analytics.js +5 -3
- package/dist/private/node/analytics.js.map +1 -1
- package/dist/private/node/api/status-checks.d.ts +7 -0
- package/dist/private/node/api/status-checks.js +11 -0
- package/dist/private/node/api/status-checks.js.map +1 -0
- package/dist/private/node/api.d.ts +15 -0
- package/dist/private/node/api.js +28 -0
- package/dist/private/node/api.js.map +1 -1
- package/dist/private/node/command-event-context.d.ts +29 -0
- package/dist/private/node/command-event-context.js +43 -0
- package/dist/private/node/command-event-context.js.map +1 -0
- package/dist/private/node/command-event-output.d.ts +7 -0
- package/dist/private/node/command-event-output.js +16 -0
- package/dist/private/node/command-event-output.js.map +1 -0
- package/dist/private/node/command-json-schema.d.ts +10 -0
- package/dist/private/node/command-json-schema.js +38 -0
- package/dist/private/node/command-json-schema.js.map +1 -0
- package/dist/private/node/context/agent.d.ts +1 -0
- package/dist/private/node/context/agent.js +44 -0
- package/dist/private/node/context/agent.js.map +1 -0
- package/dist/private/node/json-error.d.ts +23 -0
- package/dist/private/node/json-error.js +123 -0
- package/dist/private/node/json-error.js.map +1 -0
- package/dist/private/node/output.js +3 -1
- package/dist/private/node/output.js.map +1 -1
- package/dist/private/node/output.test.d.ts +1 -0
- package/dist/private/node/output.test.js +74 -0
- package/dist/private/node/output.test.js.map +1 -0
- package/dist/private/node/session/device-authorization.js +49 -15
- package/dist/private/node/session/device-authorization.js.map +1 -1
- package/dist/private/node/session/validate.js +9 -22
- package/dist/private/node/session/validate.js.map +1 -1
- package/dist/private/node/ui/alert.d.ts +1 -1
- package/dist/private/node/ui/alert.js +29 -3
- package/dist/private/node/ui/alert.js.map +1 -1
- package/dist/private/node/ui/components/ConcurrentOutput.d.ts +8 -1
- package/dist/private/node/ui/components/ConcurrentOutput.js +54 -0
- package/dist/private/node/ui/components/ConcurrentOutput.js.map +1 -1
- package/dist/private/node/ui/components/DangerousConfirmationPrompt.js +3 -3
- package/dist/private/node/ui/components/DangerousConfirmationPrompt.js.map +1 -1
- package/dist/private/node/ui/components/DangerousConfirmationPrompt.test.js +16 -1
- package/dist/private/node/ui/components/DangerousConfirmationPrompt.test.js.map +1 -1
- package/dist/private/node/ui/components/Prompts/PromptLayout.js +3 -2
- package/dist/private/node/ui/components/Prompts/PromptLayout.js.map +1 -1
- package/dist/private/node/ui/components/Prompts/PromptLayout.test.js +20 -1
- package/dist/private/node/ui/components/Prompts/PromptLayout.test.js.map +1 -1
- package/dist/private/node/ui/components/Tasks.d.ts +2 -9
- package/dist/private/node/ui/components/Tasks.js +5 -44
- package/dist/private/node/ui/components/Tasks.js.map +1 -1
- package/dist/private/node/ui/components/TextPrompt.js +3 -3
- package/dist/private/node/ui/components/TextPrompt.js.map +1 -1
- package/dist/private/node/ui/components/TextPrompt.test.js +15 -1
- package/dist/private/node/ui/components/TextPrompt.test.js.map +1 -1
- package/dist/private/node/ui/components/token-item.d.ts +2 -0
- package/dist/private/node/ui/components/token-item.js +26 -0
- package/dist/private/node/ui/components/token-item.js.map +1 -1
- package/dist/private/node/ui/hooks/use-async-and-unmount.d.ts +3 -3
- package/dist/private/node/ui/hooks/use-async-and-unmount.js +2 -2
- package/dist/private/node/ui/hooks/use-async-and-unmount.js.map +1 -1
- package/dist/private/node/ui/tasks.d.ts +10 -0
- package/dist/private/node/ui/tasks.js +68 -0
- package/dist/private/node/ui/tasks.js.map +1 -0
- package/dist/public/common/command-events.d.ts +125 -0
- package/dist/public/common/command-events.js +54 -0
- package/dist/public/common/command-events.js.map +1 -0
- package/dist/public/common/json-output-schema.d.ts +10 -0
- package/dist/public/common/json-output-schema.js +17 -0
- package/dist/public/common/json-output-schema.js.map +1 -0
- package/dist/public/common/version.d.ts +1 -1
- package/dist/public/common/version.js +1 -1
- package/dist/public/common/version.js.map +1 -1
- package/dist/public/node/api/admin.js +18 -1
- package/dist/public/node/api/admin.js.map +1 -1
- package/dist/public/node/api/app-management.d.ts +1 -0
- package/dist/public/node/api/app-management.js +4 -0
- package/dist/public/node/api/app-management.js.map +1 -1
- package/dist/public/node/api/bulk-operations/download-bulk-operation-results.d.ts +3 -3
- package/dist/public/node/api/bulk-operations/download-bulk-operation-results.js +5 -3
- package/dist/public/node/api/bulk-operations/download-bulk-operation-results.js.map +1 -1
- package/dist/public/node/base-command.d.ts +6 -0
- package/dist/public/node/base-command.js +34 -5
- package/dist/public/node/base-command.js.map +1 -1
- package/dist/public/node/cli-launcher.js +20 -2
- package/dist/public/node/cli-launcher.js.map +1 -1
- package/dist/public/node/cli.d.ts +1 -0
- package/dist/public/node/cli.js +2 -0
- package/dist/public/node/cli.js.map +1 -1
- package/dist/public/node/command-events.d.ts +65 -0
- package/dist/public/node/command-events.js +71 -0
- package/dist/public/node/command-events.js.map +1 -0
- package/dist/public/node/context/local.d.ts +6 -0
- package/dist/public/node/context/local.js +10 -1
- package/dist/public/node/context/local.js.map +1 -1
- package/dist/public/node/custom-oclif-loader.d.ts +6 -0
- package/dist/public/node/custom-oclif-loader.js +45 -19
- package/dist/public/node/custom-oclif-loader.js.map +1 -1
- package/dist/public/node/environment.d.ts +2 -1
- package/dist/public/node/environment.js +3 -2
- package/dist/public/node/environment.js.map +1 -1
- package/dist/public/node/error/index.d.ts +91 -0
- package/dist/public/node/error/index.js +266 -0
- package/dist/public/node/error/index.js.map +1 -0
- package/dist/public/node/error/schema.d.ts +472 -0
- package/dist/public/node/error/schema.js +54 -0
- package/dist/public/node/error/schema.js.map +1 -0
- package/dist/public/node/error/types.d.ts +9 -0
- package/dist/public/node/error/types.js +2 -0
- package/dist/public/node/error/types.js.map +1 -0
- package/dist/public/node/error.d.ts +1 -87
- package/dist/public/node/error.js +1 -252
- package/dist/public/node/error.js.map +1 -1
- package/dist/public/node/fs.d.ts +17 -3
- package/dist/public/node/fs.js +7 -5
- package/dist/public/node/fs.js.map +1 -1
- package/dist/public/node/json-output-schema.d.ts +26 -0
- package/dist/public/node/json-output-schema.js +30 -0
- package/dist/public/node/json-output-schema.js.map +1 -0
- package/dist/public/node/local-storage.d.ts +1 -0
- package/dist/public/node/local-storage.js +54 -21
- package/dist/public/node/local-storage.js.map +1 -1
- package/dist/public/node/monorail.d.ts +3 -1
- package/dist/public/node/monorail.js +1 -1
- package/dist/public/node/monorail.js.map +1 -1
- package/dist/public/node/multiple-installation-warning.d.ts +1 -1
- package/dist/public/node/multiple-installation-warning.js +2 -3
- package/dist/public/node/multiple-installation-warning.js.map +1 -1
- package/dist/public/node/no-input.d.ts +11 -0
- package/dist/public/node/no-input.js +19 -0
- package/dist/public/node/no-input.js.map +1 -0
- package/dist/public/node/output.d.ts +6 -0
- package/dist/public/node/output.js +40 -0
- package/dist/public/node/output.js.map +1 -1
- package/dist/public/node/path.js +3 -1
- package/dist/public/node/path.js.map +1 -1
- package/dist/public/node/system.d.ts +2 -2
- package/dist/public/node/system.js +8 -4
- package/dist/public/node/system.js.map +1 -1
- package/dist/public/node/testing/output.d.ts +30 -0
- package/dist/public/node/testing/output.js +83 -0
- package/dist/public/node/testing/output.js.map +1 -1
- package/dist/public/node/ui.d.ts +5 -1
- package/dist/public/node/ui.js +89 -5
- package/dist/public/node/ui.js.map +1 -1
- package/dist/public/node/upgrade.js +17 -2
- package/dist/public/node/upgrade.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path.js","sourceRoot":"","sources":["../../../src/public/node/path.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n relative,\n dirname as patheDirname,\n join,\n normalize,\n resolve,\n basename as basenamePathe,\n extname as extnamePathe,\n parse,\n isAbsolute,\n} from 'pathe'\nimport {fileURLToPath} from 'url'\n// eslint-disable-next-line n/prefer-global/url\nimport type {URL} from 'url'\n\n/**\n * Joins a list of paths together.\n *\n * @param paths - Paths to join.\n * @returns Joined path.\n */\nexport function joinPath(...paths: string[]): string {\n return join(...paths)\n}\n\n/**\n * Normalizes a path.\n *\n * @param path - Path to normalize.\n * @returns Normalized path.\n */\nexport function normalizePath(path: string): string {\n return normalize(path)\n}\n\n/**\n * Resolves a list of paths together.\n *\n * @param paths - Paths to resolve.\n * @returns Resolved path.\n */\nexport function resolvePath(...paths: string[]): string {\n return resolve(...paths)\n}\n\n/**\n * Returns the relative path from one path to another.\n *\n * @param from - Path to resolve from.\n * @param to - Path to resolve to.\n * @returns Relative path.\n */\nexport function relativePath(from: string, to: string): string {\n return relative(from, to)\n}\n\n/**\n * Returns whether the path is absolute.\n *\n * @param path - Path to check.\n * @returns Whether the path is absolute.\n */\nexport function isAbsolutePath(path: string): boolean {\n return isAbsolute(path)\n}\n\n/**\n * Returns the directory name of a path.\n *\n * @param path - Path to get the directory name of.\n * @returns Directory name.\n */\nexport function dirname(path: string): string {\n return patheDirname(path)\n}\n\n/**\n * Returns the base name of a path.\n *\n * @param path - Path to get the base name of.\n * @param ext - Optional extension to remove from the result.\n * @returns Base name.\n */\nexport function basename(path: string, ext?: string): string {\n return basenamePathe(path, ext)\n}\n\n/**\n * Returns the extension of the path.\n *\n * @param path - Path to get the extension of.\n * @returns Extension.\n */\nexport function extname(path: string): string {\n return extnamePathe(path)\n}\n\n/**\n * Parses a path into its components (root, dir, base, ext, name).\n *\n * @param path - Path to parse.\n * @returns Parsed path object.\n */\nexport function parsePath(path: string): {root: string; dir: string; base: string; ext: string; name: string} {\n return parse(path)\n}\n\n/**\n * Returns the longest common parent directory of two absolute paths.\n *\n * @param first - First absolute path.\n * @param second - Second absolute path.\n * @returns The common parent directory, or '/' if they share only the root.\n */\nexport function commonParentDirectory(first: string, second: string): string {\n const firstParts = first.split(/\\/+|\\\\+/)\n const secondParts = second.split(/\\/+|\\\\+/)\n let i = 0\n while (i < firstParts.length && i < secondParts.length && firstParts[i] === secondParts[i]) {\n i++\n }\n return i > 1 ? firstParts.slice(0, i).join('/') : '/'\n}\n\n/**\n * Given an absolute filesystem path, it makes it relative to\n * the current working directory. This is useful when logging paths\n * to allow the users to click on the file and let the OS open it\n * in the editor of choice.\n *\n * @param path - Path to relativize.\n * @param dir - Current working directory.\n * @returns Relativized path.\n */\nexport function relativizePath(path: string, dir: string = cwd()): string {\n const result = commonParentDirectory(path, dir)\n const relativePath = relative(dir, path)\n const relativeComponents = relativePath.split('/').filter((component) => component === '..').length\n if (result === '/' || relativePath === '' || relativeComponents > 2) {\n return path\n } else {\n return relativePath\n }\n}\n\n/**\n * Given 2 paths, it returns whether the second path is a subpath of the first path.\n *\n * @param mainPath - The main path.\n * @param subpath - The subpath.\n * @returns Whether the subpath is a subpath of the main path.\n */\nexport function isSubpath(mainPath: string, subpath: string): boolean {\n const relativePath = relative(mainPath, subpath)\n return !relativePath.startsWith('..') && !isAbsolutePath(relativePath)\n}\n\n/**\n * Given a module's import.meta.url it returns the directory containing the module.\n *\n * @param moduleURL - The value of import.meta.url in the context of the caller module.\n * @returns The path to the directory containing the caller module.\n */\nexport function moduleDirectory(moduleURL: string | URL): string {\n return dirname(fileURLToPath(moduleURL))\n}\n\n/**\n * When running a script using `npm run`, something interesting happens. If the current\n * folder does not have a `package.json` or a `node_modules` folder, npm will traverse\n * the directory tree upwards until it finds one. Then it will run the script and set\n * `process.cwd()` to that folder, while the actual path is stored in the INIT_CWD\n * environment variable (see here: https://docs.npmjs.com/cli/v9/commands/npm-run-script#description).\n *\n * @returns The path to the current working directory.\n */\nexport function cwd(): string {\n // eslint-disable-next-line @shopify/cli/no-process-cwd\n return normalize(process.env.INIT_CWD || process.cwd()) // eslint-disable-line @typescript-eslint/prefer-nullish-coalescing -- empty env var should fall through\n}\n\n/**\n * Tries to get the value of the `--path` argument, if provided.\n *\n * @param argv - The arguments to search for the `--path` argument.\n * @returns The value of the `--path` argument, if provided.\n */\nexport function sniffForPath(argv = process.argv): string | undefined {\n const pathFlagIndex = argv.indexOf('--path')\n if (pathFlagIndex === -1) {\n const pathArg = argv.find((arg) => arg.startsWith('--path='))\n return pathArg?.split('=')[1]\n }\n const pathFlag = argv[pathFlagIndex + 1]\n if (!pathFlag || pathFlag.startsWith('-')) return\n return pathFlag\n}\n\n/**\n * Returns whether the `--json` or `-j` flags are present in the arguments.\n *\n * @param argv - The arguments to search for the `--json` and `-j` flags.\n * @returns Whether the `--json` or `-j` flag is present in the arguments.\n */\nexport function sniffForJson(argv = process.argv): boolean {\n return argv.includes('--json') || argv.includes('-j')\n}\n\n/**\n * Removes any `..` traversal segments from a relative path and calls `warn`\n * if any were stripped. Normal `..` that cancel out within the path (e.g.\n * `foo/../bar` → `bar`) are collapsed but never allowed to escape the root.\n * Both `/` and `\\` are treated as separators for cross-platform safety.\n *\n * @param input - The relative path to sanitize.\n * @param warn - Called with a human-readable warning when traversal segments are removed.\n * @returns The sanitized path (may be an empty string if all segments were traversal).\n */\nexport function sanitizeRelativePath(input: string, warn: (msg: string) => void): string {\n const segments = input.replace(/\\\\/g, '/').split('/')\n const stack: string[] = []\n let stripped = false\n for (const seg of segments) {\n if (seg === '..') {\n stripped = true\n stack.pop()\n } else if (seg !== '.') {\n stack.push(seg)\n }\n }\n const result = stack.join('/')\n if (stripped) {\n warn(`Warning: path '${input}' contains '..' traversal — sanitized to '${result || '.'}'\\n`)\n }\n return result\n}\n"]}
|
|
1
|
+
{"version":3,"file":"path.js","sourceRoot":"","sources":["../../../src/public/node/path.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n relative,\n dirname as patheDirname,\n join,\n normalize,\n resolve,\n basename as basenamePathe,\n extname as extnamePathe,\n parse,\n isAbsolute,\n} from 'pathe'\nimport {fileURLToPath} from 'url'\n// eslint-disable-next-line n/prefer-global/url\nimport type {URL} from 'url'\n\n/**\n * Joins a list of paths together.\n *\n * @param paths - Paths to join.\n * @returns Joined path.\n */\nexport function joinPath(...paths: string[]): string {\n return join(...paths)\n}\n\n/**\n * Normalizes a path.\n *\n * @param path - Path to normalize.\n * @returns Normalized path.\n */\nexport function normalizePath(path: string): string {\n return normalize(path)\n}\n\n/**\n * Resolves a list of paths together.\n *\n * @param paths - Paths to resolve.\n * @returns Resolved path.\n */\nexport function resolvePath(...paths: string[]): string {\n return resolve(...paths)\n}\n\n/**\n * Returns the relative path from one path to another.\n *\n * @param from - Path to resolve from.\n * @param to - Path to resolve to.\n * @returns Relative path.\n */\nexport function relativePath(from: string, to: string): string {\n return relative(from, to)\n}\n\n/**\n * Returns whether the path is absolute.\n *\n * @param path - Path to check.\n * @returns Whether the path is absolute.\n */\nexport function isAbsolutePath(path: string): boolean {\n return isAbsolute(path)\n}\n\n/**\n * Returns the directory name of a path.\n *\n * @param path - Path to get the directory name of.\n * @returns Directory name.\n */\nexport function dirname(path: string): string {\n return patheDirname(path)\n}\n\n/**\n * Returns the base name of a path.\n *\n * @param path - Path to get the base name of.\n * @param ext - Optional extension to remove from the result.\n * @returns Base name.\n */\nexport function basename(path: string, ext?: string): string {\n return basenamePathe(path, ext)\n}\n\n/**\n * Returns the extension of the path.\n *\n * @param path - Path to get the extension of.\n * @returns Extension.\n */\nexport function extname(path: string): string {\n return extnamePathe(path)\n}\n\n/**\n * Parses a path into its components (root, dir, base, ext, name).\n *\n * @param path - Path to parse.\n * @returns Parsed path object.\n */\nexport function parsePath(path: string): {root: string; dir: string; base: string; ext: string; name: string} {\n return parse(path)\n}\n\n/**\n * Returns the longest common parent directory of two absolute paths.\n *\n * @param first - First absolute path.\n * @param second - Second absolute path.\n * @returns The common parent directory, or '/' if they share only the root.\n */\nexport function commonParentDirectory(first: string, second: string): string {\n const firstParts = first.split(/\\/+|\\\\+/)\n const secondParts = second.split(/\\/+|\\\\+/)\n let i = 0\n while (i < firstParts.length && i < secondParts.length && firstParts[i] === secondParts[i]) {\n i++\n }\n return i > 1 ? firstParts.slice(0, i).join('/') : '/'\n}\n\n/**\n * Given an absolute filesystem path, it makes it relative to\n * the current working directory. This is useful when logging paths\n * to allow the users to click on the file and let the OS open it\n * in the editor of choice.\n *\n * @param path - Path to relativize.\n * @param dir - Current working directory.\n * @returns Relativized path.\n */\nexport function relativizePath(path: string, dir: string = cwd()): string {\n const result = commonParentDirectory(path, dir)\n const relativePath = relative(dir, path)\n const relativeComponents = relativePath.split('/').filter((component) => component === '..').length\n if (result === '/' || relativePath === '' || relativeComponents > 2) {\n return path\n } else {\n return relativePath\n }\n}\n\n/**\n * Given 2 paths, it returns whether the second path is a subpath of the first path.\n *\n * @param mainPath - The main path.\n * @param subpath - The subpath.\n * @returns Whether the subpath is a subpath of the main path.\n */\nexport function isSubpath(mainPath: string, subpath: string): boolean {\n const relativePath = relative(mainPath, subpath)\n return !relativePath.startsWith('..') && !isAbsolutePath(relativePath)\n}\n\n/**\n * Given a module's import.meta.url it returns the directory containing the module.\n *\n * @param moduleURL - The value of import.meta.url in the context of the caller module.\n * @returns The path to the directory containing the caller module.\n */\nexport function moduleDirectory(moduleURL: string | URL): string {\n return dirname(fileURLToPath(moduleURL))\n}\n\n/**\n * When running a script using `npm run`, something interesting happens. If the current\n * folder does not have a `package.json` or a `node_modules` folder, npm will traverse\n * the directory tree upwards until it finds one. Then it will run the script and set\n * `process.cwd()` to that folder, while the actual path is stored in the INIT_CWD\n * environment variable (see here: https://docs.npmjs.com/cli/v9/commands/npm-run-script#description).\n *\n * @returns The path to the current working directory.\n */\nexport function cwd(): string {\n // eslint-disable-next-line @shopify/cli/no-process-cwd\n return normalize(process.env.INIT_CWD || process.cwd()) // eslint-disable-line @typescript-eslint/prefer-nullish-coalescing -- empty env var should fall through\n}\n\n/**\n * Tries to get the value of the `--path` argument, if provided.\n *\n * @param argv - The arguments to search for the `--path` argument.\n * @returns The value of the `--path` argument, if provided.\n */\nexport function sniffForPath(argv = process.argv): string | undefined {\n const pathFlagIndex = argv.indexOf('--path')\n if (pathFlagIndex === -1) {\n const pathArg = argv.find((arg) => arg.startsWith('--path='))\n return pathArg?.split('=')[1]\n }\n const pathFlag = argv[pathFlagIndex + 1]\n if (!pathFlag || pathFlag.startsWith('-')) return\n return pathFlag\n}\n\n/**\n * Returns whether the `--json` or `-j` flags are present in the arguments.\n *\n * @param argv - The arguments to search for the `--json` and `-j` flags.\n * @returns Whether the `--json` or `-j` flag is present in the arguments.\n */\nexport function sniffForJson(argv = process.argv): boolean {\n const passthroughIndex = argv.indexOf('--')\n const commandArguments = passthroughIndex === -1 ? argv : argv.slice(0, passthroughIndex)\n return commandArguments.includes('--json') || commandArguments.includes('-j')\n}\n\n/**\n * Removes any `..` traversal segments from a relative path and calls `warn`\n * if any were stripped. Normal `..` that cancel out within the path (e.g.\n * `foo/../bar` → `bar`) are collapsed but never allowed to escape the root.\n * Both `/` and `\\` are treated as separators for cross-platform safety.\n *\n * @param input - The relative path to sanitize.\n * @param warn - Called with a human-readable warning when traversal segments are removed.\n * @returns The sanitized path (may be an empty string if all segments were traversal).\n */\nexport function sanitizeRelativePath(input: string, warn: (msg: string) => void): string {\n const segments = input.replace(/\\\\/g, '/').split('/')\n const stack: string[] = []\n let stripped = false\n for (const seg of segments) {\n if (seg === '..') {\n stripped = true\n stack.pop()\n } else if (seg !== '.') {\n stack.push(seg)\n }\n }\n const result = stack.join('/')\n if (stripped) {\n warn(`Warning: path '${input}' contains '..' traversal — sanitized to '${result || '.'}'\\n`)\n }\n return result\n}\n"]}
|
|
@@ -104,9 +104,9 @@ export declare function sleep(seconds: number): Promise<void>;
|
|
|
104
104
|
*/
|
|
105
105
|
export declare function terminalSupportsHyperlinks(): boolean;
|
|
106
106
|
/**
|
|
107
|
-
* Check if
|
|
107
|
+
* Check if standard input and standard error are terminals that support prompting.
|
|
108
108
|
*
|
|
109
|
-
* @returns True if
|
|
109
|
+
* @returns True if standard input and standard error support prompting.
|
|
110
110
|
*/
|
|
111
111
|
export declare function terminalSupportsPrompting(): boolean;
|
|
112
112
|
/**
|
|
@@ -6,6 +6,7 @@ import { renderWarning } from './ui.js';
|
|
|
6
6
|
import { platformAndArch } from './os.js';
|
|
7
7
|
import { shouldDisplayColors, outputDebug } from './output.js';
|
|
8
8
|
import { isCloudEnvironment } from './context/local.js';
|
|
9
|
+
import { isInputDisabled } from './no-input.js';
|
|
9
10
|
import { execa } from 'execa';
|
|
10
11
|
import supportsHyperlinks from 'supports-hyperlinks';
|
|
11
12
|
import which from 'which';
|
|
@@ -26,6 +27,9 @@ const MAX_STDIN_SIZE = 10 * 1024 * 1024;
|
|
|
26
27
|
* @returns A promise that resolves true if the URL was opened successfully, false otherwise.
|
|
27
28
|
*/
|
|
28
29
|
export async function openURL(url) {
|
|
30
|
+
if (isInputDisabled()) {
|
|
31
|
+
throw new AbortError('Opening a browser is unavailable when user input is disabled.', 'Remove `--no-input` and run the command in an interactive terminal.');
|
|
32
|
+
}
|
|
29
33
|
if (isCloudEnvironment())
|
|
30
34
|
return false;
|
|
31
35
|
const externalOpen = await import('open');
|
|
@@ -277,15 +281,15 @@ export function terminalSupportsHyperlinks() {
|
|
|
277
281
|
return supportsHyperlinks.stdout;
|
|
278
282
|
}
|
|
279
283
|
/**
|
|
280
|
-
* Check if
|
|
284
|
+
* Check if standard input and standard error are terminals that support prompting.
|
|
281
285
|
*
|
|
282
|
-
* @returns True if
|
|
286
|
+
* @returns True if standard input and standard error support prompting.
|
|
283
287
|
*/
|
|
284
288
|
export function terminalSupportsPrompting() {
|
|
285
|
-
if (isTruthy(process.env.CI)) {
|
|
289
|
+
if (isInputDisabled() || isTruthy(process.env.CI)) {
|
|
286
290
|
return false;
|
|
287
291
|
}
|
|
288
|
-
return Boolean(process.stdin.isTTY && process.
|
|
292
|
+
return Boolean(process.stdin.isTTY && process.stderr.isTTY);
|
|
289
293
|
}
|
|
290
294
|
/**
|
|
291
295
|
* Check if the current environment is a CI environment.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system.js","sourceRoot":"","sources":["../../../src/public/node/system.ts"],"names":[],"mappings":"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","sourcesContent":["import {AbortSignal} from './abort.js'\nimport {AbortError, ExternalError} from './error.js'\nimport {cwd, dirname} from './path.js'\nimport {treeKill} from './tree-kill.js'\nimport {isTruthy} from './context/utilities.js'\nimport {renderWarning} from './ui.js'\nimport {platformAndArch} from './os.js'\nimport {shouldDisplayColors, outputDebug} from './output.js'\nimport {isCloudEnvironment} from './context/local.js'\nimport {execa, ExecaChildProcess} from 'execa'\nimport supportsHyperlinks from 'supports-hyperlinks'\nimport which from 'which'\nimport {delimiter} from 'pathe'\n\nimport {fstatSync, existsSync, readFileSync} from 'fs'\nimport {release} from 'os'\nimport {setTimeout} from 'timers/promises'\nimport type {Writable, Readable} from 'stream'\n\n/**\n * The maximum size of data that can be read from stdin in bytes.\n * This is to prevent memory exhaustion when reading from stdin.\n * 10MB.\n */\nconst MAX_STDIN_SIZE = 10 * 1024 * 1024\n\nexport interface ExecOptions {\n cwd?: string\n env?: Record<string, string | undefined>\n stdin?: Readable | 'inherit'\n stdout?: Writable | 'inherit'\n stderr?: Writable | 'inherit'\n stdio?: 'inherit'\n input?: string\n signal?: AbortSignal\n // Custom handler if process exits with a non-zero code\n externalErrorHandler?: (error: unknown) => Promise<void>\n // Ignored on Windows\n background?: boolean\n}\n\n/**\n * Options passed directly to execa.\n */\ninterface BuildExecOptions {\n /** Whether to throw on non-zero exit codes (default: true). */\n reject?: boolean\n}\n\n/**\n * Opens a URL in the user's default browser.\n *\n * @param url - URL to open.\n * @returns A promise that resolves true if the URL was opened successfully, false otherwise.\n */\nexport async function openURL(url: string): Promise<boolean> {\n if (isCloudEnvironment()) return false\n\n const externalOpen = await import('open')\n try {\n await externalOpen.default(url)\n return true\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n return false\n }\n}\n\n/**\n * Runs a command asynchronously, aggregates the stdout data, and returns it.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n * @returns A promise that resolves with the aggregatted stdout of the command.\n */\nexport async function captureOutput(command: string, args: string[], options?: ExecOptions): Promise<string> {\n const result = await buildExec(command, args, options)\n return result.stdout\n}\n\n/**\n * Result from running a command with captureOutputWithExitCode.\n */\nexport interface CaptureOutputResult {\n /** Standard output. */\n stdout: string\n /** Standard error. */\n stderr: string\n /** Exit code (0 = success). */\n exitCode: number\n}\n\n/**\n * Runs a command asynchronously and returns stdout, stderr, and exit code.\n * Unlike captureOutput, this function does NOT throw on non-zero exit codes.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n * @returns A promise that resolves with stdout, stderr, and exitCode.\n *\n * @example\n * ```typescript\n * const result = await captureOutputWithExitCode('ls', ['-la'])\n * if (result.exitCode !== 0) \\{\n * console.error('Command failed:', result.stderr)\n * \\}\n * ```\n */\nexport async function captureOutputWithExitCode(\n command: string,\n args: string[],\n options?: ExecOptions,\n): Promise<CaptureOutputResult> {\n const result = await buildExec(command, args, options, {reject: false})\n return {\n stdout: result.stdout,\n stderr: result.stderr,\n exitCode: result.exitCode ?? 0,\n }\n}\n\n/**\n * Parse a command string into an array of arguments, respecting quoted strings.\n * Handles both single and double quotes, preserving spaces within quoted sections.\n *\n * @param command - The command string to parse (e.g., 'ls -la \"my folder\"').\n * @returns An array of command parts with quotes removed.\n *\n * @example\n * parseCommand('shopify theme push --theme \"My Theme Name\"') // ['shopify', 'theme', 'push', '--theme', 'My Theme Name']\n */\nfunction parseCommand(command: string): string[] {\n const result: string[] = []\n let current = ''\n let inQuote: string | null = null\n\n for (const char of command) {\n if (inQuote) {\n if (char === inQuote) {\n // End of quoted section\n inQuote = null\n } else {\n current += char\n }\n } else if (char === '\"' || char === \"'\") {\n // Start of quoted section\n inQuote = char\n } else if (char === ' ' || char === '\\t') {\n // Whitespace outside quotes - end current token\n if (current) {\n result.push(current)\n current = ''\n }\n } else {\n current += char\n }\n }\n\n // Don't forget the last token\n if (current) {\n result.push(current)\n }\n\n return result\n}\n\n/**\n * Runs a command string asynchronously and returns stdout, stderr, and exit code.\n * Parses the command string into command and arguments (handles quoted strings).\n * Unlike captureOutput, this function does NOT throw on non-zero exit codes.\n *\n * @param command - Full command string to be executed (e.g., 'ls -la \"my folder\"').\n * @param options - Optional settings for how to run the command.\n * @returns A promise that resolves with stdout, stderr, and exitCode.\n *\n * @example\n * ```typescript\n * const result = await captureCommandWithExitCode('shopify theme push --theme \"My Theme\"')\n * if (result.exitCode !== 0) {\n * console.error('Command failed:', result.stderr)\n * }\n * ```\n */\nexport async function captureCommandWithExitCode(command: string, options?: ExecOptions): Promise<CaptureOutputResult> {\n const [cmd, ...args] = parseCommand(command)\n if (!cmd) {\n return {stdout: '', stderr: 'Empty command', exitCode: 1}\n }\n return captureOutputWithExitCode(cmd, args, options)\n}\n\n/**\n * Runs a command string asynchronously (parses command and arguments from the string).\n *\n * @param command - Full command string to be executed (e.g., 'ls -la \"my folder\"').\n * @param options - Optional settings for how to run the command.\n */\nexport async function execCommand(command: string, options?: ExecOptions): Promise<void> {\n const [cmd, ...args] = parseCommand(command)\n if (!cmd) {\n throw new AbortError('Empty command')\n }\n await exec(cmd, args, options)\n}\n\n/**\n * Runs a command asynchronously.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n */\nexport async function exec(command: string, args: string[], options?: ExecOptions): Promise<void> {\n if (options) {\n // Windows opens a new console window when running a command in the background, so we disable it.\n const runningOnWindows = platformAndArch().platform === 'windows'\n options.background = runningOnWindows ? false : options.background\n }\n\n const commandProcess = buildExec(command, args, options)\n\n if (options?.background) {\n commandProcess.unref()\n }\n\n if (options?.stderr && options.stderr !== 'inherit') {\n commandProcess.stderr?.pipe(options.stderr, {end: false})\n }\n if (options?.stdout && options.stdout !== 'inherit') {\n commandProcess.stdout?.pipe(options.stdout, {end: false})\n }\n let aborted = false\n options?.signal?.addEventListener('abort', () => {\n const pid = commandProcess.pid\n if (pid) {\n outputDebug(`Killing process ${pid}: ${command} ${args.join(' ')}`)\n aborted = true\n treeKill(pid, 'SIGTERM')\n }\n })\n try {\n await commandProcess\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (processError: any) {\n // Windows will throw an error whenever the process is killed, no matter the reason.\n // The aborted flag tell use that we killed it, so we can ignore the error.\n if (aborted) return\n if (options?.externalErrorHandler) {\n await options.externalErrorHandler(processError)\n } else {\n const abortError = new ExternalError(processError.message, command, args)\n abortError.stack = processError.stack\n throw abortError\n }\n }\n}\n\n/**\n * Runs a command asynchronously.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n * @param execaOptions - Options passed directly to execa.\n * @returns A promise for a result with stdout and stderr properties.\n */\nfunction buildExec(\n command: string,\n args: string[],\n options?: ExecOptions,\n execaOptions?: BuildExecOptions,\n): ExecaChildProcess {\n const env = options?.env ?? process.env\n if (shouldDisplayColors()) {\n env.FORCE_COLOR = '1'\n }\n const executionCwd = options?.cwd ?? cwd()\n checkCommandSafety(command, {cwd: executionCwd})\n const backgroundStdio = options?.input === undefined ? 'ignore' : (['pipe', 'ignore', 'ignore'] as const)\n const commandProcess = execa(command, args, {\n env,\n cwd: executionCwd,\n input: options?.input,\n stdio: options?.background ? backgroundStdio : options?.stdio,\n stdin: options?.stdin,\n stdout: options?.stdout === 'inherit' ? 'inherit' : undefined,\n stderr: options?.stderr === 'inherit' ? 'inherit' : undefined,\n // Setting this to false makes it possible to kill the main process\n // and all its sub-processes with Ctrl+C on Windows\n windowsHide: false,\n detached: options?.background,\n cleanup: !options?.background,\n ...execaOptions,\n })\n outputDebug(`Running system process${options?.background ? ' in background' : ''}:\n · Command: ${command} ${args.join(' ')}\n · Working directory: ${executionCwd}\n`)\n return commandProcess\n}\n\nfunction checkCommandSafety(command: string, _options: {cwd: string}): void {\n const pathIncludingLocal = `${_options.cwd}${delimiter}${process.env.PATH}`\n const commandPath = which.sync(command, {\n nothrow: true,\n path: pathIncludingLocal,\n })\n if (commandPath && dirname(commandPath) === _options.cwd) {\n const headline = ['Skipped run of unsecure binary', {command}, 'found in the current directory.']\n const body = 'Please remove that file or review your current PATH.'\n renderWarning({headline, body})\n throw new AbortError(headline, body)\n }\n}\n\n/**\n * Waits for a given number of seconds.\n *\n * @param seconds - Number of seconds to wait.\n * @returns A Promise resolving after the number of seconds.\n */\nexport async function sleep(seconds: number): Promise<void> {\n await setTimeout(1000 * seconds)\n}\n\n/**\n * Check if the terminal supports OSC 8 hyperlinks.\n *\n * @returns True if the terminal supports hyperlinks.\n */\nexport function terminalSupportsHyperlinks(): boolean {\n return supportsHyperlinks.stdout\n}\n\n/**\n * Check if the standard input and output streams support prompting.\n *\n * @returns True if the standard input and output streams support prompting.\n */\nexport function terminalSupportsPrompting(): boolean {\n if (isTruthy(process.env.CI)) {\n return false\n }\n return Boolean(process.stdin.isTTY && process.stdout.isTTY)\n}\n\n/**\n * Check if the current environment is a CI environment.\n *\n * @returns True if the current environment is a CI environment.\n */\nexport function isCI(): boolean {\n return isTruthy(process.env.CI)\n}\n\ninterface WslDetectionOverrides {\n platform?: NodeJS.Platform\n kernelRelease?: string\n procVersion?: string\n insideContainer?: boolean\n}\n\n/**\n * Check if the current environment is a WSL environment.\n *\n * @param overrides - Detection inputs, read from the system when not provided. Intended for tests.\n * @returns True if the current environment is a WSL environment.\n */\n// Mirrors https://github.com/sindresorhus/is-wsl: WSL reports \"microsoft\" in the kernel\n// release, but containers running inside WSL shouldn't count.\nexport async function isWsl(overrides: WslDetectionOverrides = {}): Promise<boolean> {\n const platform = overrides.platform ?? process.platform\n if (platform !== 'linux') return false\n const insideContainer = () => overrides.insideContainer ?? isInsideContainer()\n if ((overrides.kernelRelease ?? release()).toLowerCase().includes('microsoft')) {\n return !insideContainer()\n }\n try {\n const procVersion = overrides.procVersion ?? readFileSync('/proc/version', 'utf8')\n return procVersion.toLowerCase().includes('microsoft') ? !insideContainer() : false\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch {\n return false\n }\n}\n\n// Mirrors the is-inside-container and is-docker packages: Podman creates /run/.containerenv,\n// Docker creates /.dockerenv or mentions \"docker\" in the process cgroup.\n/**\n * Check if the current process is running inside a container.\n *\n * @returns True if the current process is running inside a container.\n */\nexport function isInsideContainer(): boolean {\n if (existsSync('/run/.containerenv') || existsSync('/.dockerenv')) return true\n try {\n return readFileSync('/proc/self/cgroup', 'utf8').includes('docker')\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch {\n return false\n }\n}\n\n/**\n * Check if stdin has piped data available.\n * This distinguishes between actual piped input (e.g., `echo \"query\" | cmd`)\n * and non-TTY environments without input (e.g., CI).\n *\n * @returns True if stdin is receiving piped data or file redirect, false otherwise.\n */\nexport function isStdinPiped(): boolean {\n try {\n const stats = fstatSync(0)\n return stats.isFIFO() || stats.isFile() || stats.isSocket()\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch {\n return false\n }\n}\n\n/**\n * Reads all data from stdin and returns it as a string.\n * This is useful for commands that accept input via piping.\n *\n * @example\n * // Usage: echo \"your query\" | shopify app execute\n * const query = await readStdin()\n *\n * @returns A promise that resolves with the stdin content, or undefined if stdin is a TTY.\n */\nexport async function readStdinString(): Promise<string | undefined> {\n if (!isStdinPiped()) {\n return undefined\n }\n\n let data = ''\n let totalSize = 0\n process.stdin.setEncoding('utf8')\n for await (const chunk of process.stdin) {\n const chunkString = String(chunk)\n totalSize += Buffer.byteLength(chunkString, 'utf8')\n if (totalSize > MAX_STDIN_SIZE) {\n throw new AbortError('Stdin input exceeded the maximum allowed size.')\n }\n data += chunkString\n }\n return data.trim()\n}\n"]}
|
|
1
|
+
{"version":3,"file":"system.js","sourceRoot":"","sources":["../../../src/public/node/system.ts"],"names":[],"mappings":"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","sourcesContent":["import {AbortSignal} from './abort.js'\nimport {AbortError, ExternalError} from './error.js'\nimport {cwd, dirname} from './path.js'\nimport {treeKill} from './tree-kill.js'\nimport {isTruthy} from './context/utilities.js'\nimport {renderWarning} from './ui.js'\nimport {platformAndArch} from './os.js'\nimport {shouldDisplayColors, outputDebug} from './output.js'\nimport {isCloudEnvironment} from './context/local.js'\nimport {isInputDisabled} from './no-input.js'\nimport {execa, ExecaChildProcess} from 'execa'\nimport supportsHyperlinks from 'supports-hyperlinks'\nimport which from 'which'\nimport {delimiter} from 'pathe'\n\nimport {fstatSync, existsSync, readFileSync} from 'fs'\nimport {release} from 'os'\nimport {setTimeout} from 'timers/promises'\nimport type {Writable, Readable} from 'stream'\n\n/**\n * The maximum size of data that can be read from stdin in bytes.\n * This is to prevent memory exhaustion when reading from stdin.\n * 10MB.\n */\nconst MAX_STDIN_SIZE = 10 * 1024 * 1024\n\nexport interface ExecOptions {\n cwd?: string\n env?: Record<string, string | undefined>\n stdin?: Readable | 'inherit'\n stdout?: Writable | 'inherit'\n stderr?: Writable | 'inherit'\n stdio?: 'inherit'\n input?: string\n signal?: AbortSignal\n // Custom handler if process exits with a non-zero code\n externalErrorHandler?: (error: unknown) => Promise<void>\n // Ignored on Windows\n background?: boolean\n}\n\n/**\n * Options passed directly to execa.\n */\ninterface BuildExecOptions {\n /** Whether to throw on non-zero exit codes (default: true). */\n reject?: boolean\n}\n\n/**\n * Opens a URL in the user's default browser.\n *\n * @param url - URL to open.\n * @returns A promise that resolves true if the URL was opened successfully, false otherwise.\n */\nexport async function openURL(url: string): Promise<boolean> {\n if (isInputDisabled()) {\n throw new AbortError(\n 'Opening a browser is unavailable when user input is disabled.',\n 'Remove `--no-input` and run the command in an interactive terminal.',\n )\n }\n if (isCloudEnvironment()) return false\n\n const externalOpen = await import('open')\n try {\n await externalOpen.default(url)\n return true\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n return false\n }\n}\n\n/**\n * Runs a command asynchronously, aggregates the stdout data, and returns it.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n * @returns A promise that resolves with the aggregatted stdout of the command.\n */\nexport async function captureOutput(command: string, args: string[], options?: ExecOptions): Promise<string> {\n const result = await buildExec(command, args, options)\n return result.stdout\n}\n\n/**\n * Result from running a command with captureOutputWithExitCode.\n */\nexport interface CaptureOutputResult {\n /** Standard output. */\n stdout: string\n /** Standard error. */\n stderr: string\n /** Exit code (0 = success). */\n exitCode: number\n}\n\n/**\n * Runs a command asynchronously and returns stdout, stderr, and exit code.\n * Unlike captureOutput, this function does NOT throw on non-zero exit codes.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n * @returns A promise that resolves with stdout, stderr, and exitCode.\n *\n * @example\n * ```typescript\n * const result = await captureOutputWithExitCode('ls', ['-la'])\n * if (result.exitCode !== 0) \\{\n * console.error('Command failed:', result.stderr)\n * \\}\n * ```\n */\nexport async function captureOutputWithExitCode(\n command: string,\n args: string[],\n options?: ExecOptions,\n): Promise<CaptureOutputResult> {\n const result = await buildExec(command, args, options, {reject: false})\n return {\n stdout: result.stdout,\n stderr: result.stderr,\n exitCode: result.exitCode ?? 0,\n }\n}\n\n/**\n * Parse a command string into an array of arguments, respecting quoted strings.\n * Handles both single and double quotes, preserving spaces within quoted sections.\n *\n * @param command - The command string to parse (e.g., 'ls -la \"my folder\"').\n * @returns An array of command parts with quotes removed.\n *\n * @example\n * parseCommand('shopify theme push --theme \"My Theme Name\"') // ['shopify', 'theme', 'push', '--theme', 'My Theme Name']\n */\nfunction parseCommand(command: string): string[] {\n const result: string[] = []\n let current = ''\n let inQuote: string | null = null\n\n for (const char of command) {\n if (inQuote) {\n if (char === inQuote) {\n // End of quoted section\n inQuote = null\n } else {\n current += char\n }\n } else if (char === '\"' || char === \"'\") {\n // Start of quoted section\n inQuote = char\n } else if (char === ' ' || char === '\\t') {\n // Whitespace outside quotes - end current token\n if (current) {\n result.push(current)\n current = ''\n }\n } else {\n current += char\n }\n }\n\n // Don't forget the last token\n if (current) {\n result.push(current)\n }\n\n return result\n}\n\n/**\n * Runs a command string asynchronously and returns stdout, stderr, and exit code.\n * Parses the command string into command and arguments (handles quoted strings).\n * Unlike captureOutput, this function does NOT throw on non-zero exit codes.\n *\n * @param command - Full command string to be executed (e.g., 'ls -la \"my folder\"').\n * @param options - Optional settings for how to run the command.\n * @returns A promise that resolves with stdout, stderr, and exitCode.\n *\n * @example\n * ```typescript\n * const result = await captureCommandWithExitCode('shopify theme push --theme \"My Theme\"')\n * if (result.exitCode !== 0) {\n * console.error('Command failed:', result.stderr)\n * }\n * ```\n */\nexport async function captureCommandWithExitCode(command: string, options?: ExecOptions): Promise<CaptureOutputResult> {\n const [cmd, ...args] = parseCommand(command)\n if (!cmd) {\n return {stdout: '', stderr: 'Empty command', exitCode: 1}\n }\n return captureOutputWithExitCode(cmd, args, options)\n}\n\n/**\n * Runs a command string asynchronously (parses command and arguments from the string).\n *\n * @param command - Full command string to be executed (e.g., 'ls -la \"my folder\"').\n * @param options - Optional settings for how to run the command.\n */\nexport async function execCommand(command: string, options?: ExecOptions): Promise<void> {\n const [cmd, ...args] = parseCommand(command)\n if (!cmd) {\n throw new AbortError('Empty command')\n }\n await exec(cmd, args, options)\n}\n\n/**\n * Runs a command asynchronously.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n */\nexport async function exec(command: string, args: string[], options?: ExecOptions): Promise<void> {\n if (options) {\n // Windows opens a new console window when running a command in the background, so we disable it.\n const runningOnWindows = platformAndArch().platform === 'windows'\n options.background = runningOnWindows ? false : options.background\n }\n\n const commandProcess = buildExec(command, args, options)\n\n if (options?.background) {\n commandProcess.unref()\n }\n\n if (options?.stderr && options.stderr !== 'inherit') {\n commandProcess.stderr?.pipe(options.stderr, {end: false})\n }\n if (options?.stdout && options.stdout !== 'inherit') {\n commandProcess.stdout?.pipe(options.stdout, {end: false})\n }\n let aborted = false\n options?.signal?.addEventListener('abort', () => {\n const pid = commandProcess.pid\n if (pid) {\n outputDebug(`Killing process ${pid}: ${command} ${args.join(' ')}`)\n aborted = true\n treeKill(pid, 'SIGTERM')\n }\n })\n try {\n await commandProcess\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (processError: any) {\n // Windows will throw an error whenever the process is killed, no matter the reason.\n // The aborted flag tell use that we killed it, so we can ignore the error.\n if (aborted) return\n if (options?.externalErrorHandler) {\n await options.externalErrorHandler(processError)\n } else {\n const abortError = new ExternalError(processError.message, command, args)\n abortError.stack = processError.stack\n throw abortError\n }\n }\n}\n\n/**\n * Runs a command asynchronously.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n * @param execaOptions - Options passed directly to execa.\n * @returns A promise for a result with stdout and stderr properties.\n */\nfunction buildExec(\n command: string,\n args: string[],\n options?: ExecOptions,\n execaOptions?: BuildExecOptions,\n): ExecaChildProcess {\n const env = options?.env ?? process.env\n if (shouldDisplayColors()) {\n env.FORCE_COLOR = '1'\n }\n const executionCwd = options?.cwd ?? cwd()\n checkCommandSafety(command, {cwd: executionCwd})\n const backgroundStdio = options?.input === undefined ? 'ignore' : (['pipe', 'ignore', 'ignore'] as const)\n const commandProcess = execa(command, args, {\n env,\n cwd: executionCwd,\n input: options?.input,\n stdio: options?.background ? backgroundStdio : options?.stdio,\n stdin: options?.stdin,\n stdout: options?.stdout === 'inherit' ? 'inherit' : undefined,\n stderr: options?.stderr === 'inherit' ? 'inherit' : undefined,\n // Setting this to false makes it possible to kill the main process\n // and all its sub-processes with Ctrl+C on Windows\n windowsHide: false,\n detached: options?.background,\n cleanup: !options?.background,\n ...execaOptions,\n })\n outputDebug(`Running system process${options?.background ? ' in background' : ''}:\n · Command: ${command} ${args.join(' ')}\n · Working directory: ${executionCwd}\n`)\n return commandProcess\n}\n\nfunction checkCommandSafety(command: string, _options: {cwd: string}): void {\n const pathIncludingLocal = `${_options.cwd}${delimiter}${process.env.PATH}`\n const commandPath = which.sync(command, {\n nothrow: true,\n path: pathIncludingLocal,\n })\n if (commandPath && dirname(commandPath) === _options.cwd) {\n const headline = ['Skipped run of unsecure binary', {command}, 'found in the current directory.']\n const body = 'Please remove that file or review your current PATH.'\n renderWarning({headline, body})\n throw new AbortError(headline, body)\n }\n}\n\n/**\n * Waits for a given number of seconds.\n *\n * @param seconds - Number of seconds to wait.\n * @returns A Promise resolving after the number of seconds.\n */\nexport async function sleep(seconds: number): Promise<void> {\n await setTimeout(1000 * seconds)\n}\n\n/**\n * Check if the terminal supports OSC 8 hyperlinks.\n *\n * @returns True if the terminal supports hyperlinks.\n */\nexport function terminalSupportsHyperlinks(): boolean {\n return supportsHyperlinks.stdout\n}\n\n/**\n * Check if standard input and standard error are terminals that support prompting.\n *\n * @returns True if standard input and standard error support prompting.\n */\nexport function terminalSupportsPrompting(): boolean {\n if (isInputDisabled() || isTruthy(process.env.CI)) {\n return false\n }\n return Boolean(process.stdin.isTTY && process.stderr.isTTY)\n}\n\n/**\n * Check if the current environment is a CI environment.\n *\n * @returns True if the current environment is a CI environment.\n */\nexport function isCI(): boolean {\n return isTruthy(process.env.CI)\n}\n\ninterface WslDetectionOverrides {\n platform?: NodeJS.Platform\n kernelRelease?: string\n procVersion?: string\n insideContainer?: boolean\n}\n\n/**\n * Check if the current environment is a WSL environment.\n *\n * @param overrides - Detection inputs, read from the system when not provided. Intended for tests.\n * @returns True if the current environment is a WSL environment.\n */\n// Mirrors https://github.com/sindresorhus/is-wsl: WSL reports \"microsoft\" in the kernel\n// release, but containers running inside WSL shouldn't count.\nexport async function isWsl(overrides: WslDetectionOverrides = {}): Promise<boolean> {\n const platform = overrides.platform ?? process.platform\n if (platform !== 'linux') return false\n const insideContainer = () => overrides.insideContainer ?? isInsideContainer()\n if ((overrides.kernelRelease ?? release()).toLowerCase().includes('microsoft')) {\n return !insideContainer()\n }\n try {\n const procVersion = overrides.procVersion ?? readFileSync('/proc/version', 'utf8')\n return procVersion.toLowerCase().includes('microsoft') ? !insideContainer() : false\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch {\n return false\n }\n}\n\n// Mirrors the is-inside-container and is-docker packages: Podman creates /run/.containerenv,\n// Docker creates /.dockerenv or mentions \"docker\" in the process cgroup.\n/**\n * Check if the current process is running inside a container.\n *\n * @returns True if the current process is running inside a container.\n */\nexport function isInsideContainer(): boolean {\n if (existsSync('/run/.containerenv') || existsSync('/.dockerenv')) return true\n try {\n return readFileSync('/proc/self/cgroup', 'utf8').includes('docker')\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch {\n return false\n }\n}\n\n/**\n * Check if stdin has piped data available.\n * This distinguishes between actual piped input (e.g., `echo \"query\" | cmd`)\n * and non-TTY environments without input (e.g., CI).\n *\n * @returns True if stdin is receiving piped data or file redirect, false otherwise.\n */\nexport function isStdinPiped(): boolean {\n try {\n const stats = fstatSync(0)\n return stats.isFIFO() || stats.isFile() || stats.isSocket()\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch {\n return false\n }\n}\n\n/**\n * Reads all data from stdin and returns it as a string.\n * This is useful for commands that accept input via piping.\n *\n * @example\n * // Usage: echo \"your query\" | shopify app execute\n * const query = await readStdin()\n *\n * @returns A promise that resolves with the stdin content, or undefined if stdin is a TTY.\n */\nexport async function readStdinString(): Promise<string | undefined> {\n if (!isStdinPiped()) {\n return undefined\n }\n\n let data = ''\n let totalSize = 0\n process.stdin.setEncoding('utf8')\n for await (const chunk of process.stdin) {\n const chunkString = String(chunk)\n totalSize += Buffer.byteLength(chunkString, 'utf8')\n if (totalSize > MAX_STDIN_SIZE) {\n throw new AbortError('Stdin input exceeded the maximum allowed size.')\n }\n data += chunkString\n }\n return data.trim()\n}\n"]}
|
|
@@ -8,6 +8,36 @@ interface OutputMock {
|
|
|
8
8
|
error: () => string;
|
|
9
9
|
clear: () => void;
|
|
10
10
|
}
|
|
11
|
+
interface StandardStreamsMock {
|
|
12
|
+
stdout: () => string;
|
|
13
|
+
stderr: () => string;
|
|
14
|
+
restore: () => void;
|
|
15
|
+
}
|
|
16
|
+
export interface CapturedStandardStreams {
|
|
17
|
+
stdout: () => string;
|
|
18
|
+
stderr: () => string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Runs a callback with process stdout/stderr captured and unit-test output suppression disabled,
|
|
22
|
+
* so tests can assert on what a command actually writes to the standard streams.
|
|
23
|
+
*
|
|
24
|
+
* The callback receives accessors instead of the function returning captured output so that
|
|
25
|
+
* assertions remain possible when the callback throws (for example commands that abort).
|
|
26
|
+
* Streams, console.warn and unit-test detection are restored afterwards.
|
|
27
|
+
* Not safe for concurrent tests.
|
|
28
|
+
*
|
|
29
|
+
* @param run - Callback receiving accessors for the captured stdout and stderr.
|
|
30
|
+
* @returns The value returned by the callback.
|
|
31
|
+
*/
|
|
32
|
+
export declare function withCapturedStandardStreams<T>(run: (streams: CapturedStandardStreams) => T | Promise<T>): Promise<T>;
|
|
33
|
+
/**
|
|
34
|
+
* Captures writes to stdout and stderr, including console warnings intercepted by Vitest.
|
|
35
|
+
* Call restore in a finally block. This replaces process globals and must not be used in concurrent tests.
|
|
36
|
+
* Prefer withCapturedStandardStreams, which also disables unit-test output suppression while it runs.
|
|
37
|
+
*
|
|
38
|
+
* @returns Captured output and a function to restore the original writers.
|
|
39
|
+
*/
|
|
40
|
+
export declare function mockAndCaptureStandardStreams(): StandardStreamsMock;
|
|
11
41
|
/**
|
|
12
42
|
* Returns a set of functions to get the outputs ocurred during a test run.
|
|
13
43
|
*
|
|
@@ -1,4 +1,87 @@
|
|
|
1
1
|
import { collectedLogs, clearCollectedLogs } from '../output.js';
|
|
2
|
+
import { resetMemoizedIsUnitTest } from '../context/local.js';
|
|
3
|
+
import { environmentVariables } from '../../../private/node/constants.js';
|
|
4
|
+
// eslint-disable-next-line n/prefer-global/console
|
|
5
|
+
import { Console } from 'node:console';
|
|
6
|
+
/**
|
|
7
|
+
* Runs a callback with process stdout/stderr captured and unit-test output suppression disabled,
|
|
8
|
+
* so tests can assert on what a command actually writes to the standard streams.
|
|
9
|
+
*
|
|
10
|
+
* The callback receives accessors instead of the function returning captured output so that
|
|
11
|
+
* assertions remain possible when the callback throws (for example commands that abort).
|
|
12
|
+
* Streams, console.warn and unit-test detection are restored afterwards.
|
|
13
|
+
* Not safe for concurrent tests.
|
|
14
|
+
*
|
|
15
|
+
* @param run - Callback receiving accessors for the captured stdout and stderr.
|
|
16
|
+
* @returns The value returned by the callback.
|
|
17
|
+
*/
|
|
18
|
+
export async function withCapturedStandardStreams(run) {
|
|
19
|
+
// Computed access on purpose: Vitest compile-replaces the literal process.env.SHOPIFY_UNIT_TEST expression.
|
|
20
|
+
const previousUnitTestVariable = process.env[environmentVariables.unitTest];
|
|
21
|
+
setUnitTestVariable('0');
|
|
22
|
+
resetMemoizedIsUnitTest();
|
|
23
|
+
const streams = mockAndCaptureStandardStreams();
|
|
24
|
+
try {
|
|
25
|
+
return await run({ stdout: streams.stdout, stderr: streams.stderr });
|
|
26
|
+
}
|
|
27
|
+
finally {
|
|
28
|
+
streams.restore();
|
|
29
|
+
setUnitTestVariable(previousUnitTestVariable);
|
|
30
|
+
resetMemoizedIsUnitTest();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function setUnitTestVariable(value) {
|
|
34
|
+
if (value === undefined) {
|
|
35
|
+
delete process.env[environmentVariables.unitTest];
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
process.env[environmentVariables.unitTest] = value;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Captures writes to stdout and stderr, including console warnings intercepted by Vitest.
|
|
43
|
+
* Call restore in a finally block. This replaces process globals and must not be used in concurrent tests.
|
|
44
|
+
* Prefer withCapturedStandardStreams, which also disables unit-test output suppression while it runs.
|
|
45
|
+
*
|
|
46
|
+
* @returns Captured output and a function to restore the original writers.
|
|
47
|
+
*/
|
|
48
|
+
export function mockAndCaptureStandardStreams() {
|
|
49
|
+
const stdout = captureStream(process.stdout);
|
|
50
|
+
const stderr = captureStream(process.stderr);
|
|
51
|
+
// Vitest intercepts console.warn before it reaches stderr; use Node's console to exercise the writer.
|
|
52
|
+
// eslint-disable-next-line no-console
|
|
53
|
+
const originalWarn = console.warn;
|
|
54
|
+
// eslint-disable-next-line no-console
|
|
55
|
+
console.warn = new Console(process.stdout, process.stderr).warn;
|
|
56
|
+
return {
|
|
57
|
+
stdout: stdout.output,
|
|
58
|
+
stderr: stderr.output,
|
|
59
|
+
restore: () => {
|
|
60
|
+
// eslint-disable-next-line no-console
|
|
61
|
+
console.warn = originalWarn;
|
|
62
|
+
stdout.restore();
|
|
63
|
+
stderr.restore();
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function captureStream(stream) {
|
|
68
|
+
const chunks = [];
|
|
69
|
+
const originalWrite = stream.write;
|
|
70
|
+
stream.write = (chunk, encodingOrCallback, callback) => {
|
|
71
|
+
const encoding = typeof encodingOrCallback === 'string' ? encodingOrCallback : 'utf8';
|
|
72
|
+
chunks.push(typeof chunk === 'string' ? Buffer.from(chunk, encoding) : Buffer.from(chunk));
|
|
73
|
+
const onWrite = typeof encodingOrCallback === 'function' ? encodingOrCallback : callback;
|
|
74
|
+
if (onWrite)
|
|
75
|
+
queueMicrotask(() => onWrite());
|
|
76
|
+
return true;
|
|
77
|
+
};
|
|
78
|
+
return {
|
|
79
|
+
output: () => Buffer.concat(chunks).toString('utf8'),
|
|
80
|
+
restore: () => {
|
|
81
|
+
stream.write = originalWrite;
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
2
85
|
/**
|
|
3
86
|
* Returns a set of functions to get the outputs ocurred during a test run.
|
|
4
87
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../../../src/public/node/testing/output.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAE,kBAAkB,EAAC,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../../../src/public/node/testing/output.ts"],"names":[],"mappings":"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","sourcesContent":["import {collectedLogs, clearCollectedLogs} from '../output.js'\nimport {resetMemoizedIsUnitTest} from '../context/local.js'\nimport {environmentVariables} from '../../../private/node/constants.js'\n// eslint-disable-next-line n/prefer-global/console\nimport {Console} from 'node:console'\n\ninterface OutputMock {\n output: () => string\n info: () => string\n debug: () => string\n success: () => string\n completed: () => string\n warn: () => string\n error: () => string\n clear: () => void\n}\n\ninterface StandardStreamsMock {\n stdout: () => string\n stderr: () => string\n restore: () => void\n}\n\nexport interface CapturedStandardStreams {\n stdout: () => string\n stderr: () => string\n}\n\n/**\n * Runs a callback with process stdout/stderr captured and unit-test output suppression disabled,\n * so tests can assert on what a command actually writes to the standard streams.\n *\n * The callback receives accessors instead of the function returning captured output so that\n * assertions remain possible when the callback throws (for example commands that abort).\n * Streams, console.warn and unit-test detection are restored afterwards.\n * Not safe for concurrent tests.\n *\n * @param run - Callback receiving accessors for the captured stdout and stderr.\n * @returns The value returned by the callback.\n */\nexport async function withCapturedStandardStreams<T>(\n run: (streams: CapturedStandardStreams) => T | Promise<T>,\n): Promise<T> {\n // Computed access on purpose: Vitest compile-replaces the literal process.env.SHOPIFY_UNIT_TEST expression.\n const previousUnitTestVariable = process.env[environmentVariables.unitTest]\n setUnitTestVariable('0')\n resetMemoizedIsUnitTest()\n const streams = mockAndCaptureStandardStreams()\n try {\n return await run({stdout: streams.stdout, stderr: streams.stderr})\n } finally {\n streams.restore()\n setUnitTestVariable(previousUnitTestVariable)\n resetMemoizedIsUnitTest()\n }\n}\n\nfunction setUnitTestVariable(value: string | undefined): void {\n if (value === undefined) {\n delete process.env[environmentVariables.unitTest]\n } else {\n process.env[environmentVariables.unitTest] = value\n }\n}\n\n/**\n * Captures writes to stdout and stderr, including console warnings intercepted by Vitest.\n * Call restore in a finally block. This replaces process globals and must not be used in concurrent tests.\n * Prefer withCapturedStandardStreams, which also disables unit-test output suppression while it runs.\n *\n * @returns Captured output and a function to restore the original writers.\n */\nexport function mockAndCaptureStandardStreams(): StandardStreamsMock {\n const stdout = captureStream(process.stdout)\n const stderr = captureStream(process.stderr)\n // Vitest intercepts console.warn before it reaches stderr; use Node's console to exercise the writer.\n // eslint-disable-next-line no-console\n const originalWarn = console.warn\n // eslint-disable-next-line no-console\n console.warn = new Console(process.stdout, process.stderr).warn\n\n return {\n stdout: stdout.output,\n stderr: stderr.output,\n restore: () => {\n // eslint-disable-next-line no-console\n console.warn = originalWarn\n stdout.restore()\n stderr.restore()\n },\n }\n}\n\nfunction captureStream(stream: NodeJS.WriteStream) {\n const chunks: Buffer[] = []\n const originalWrite = stream.write\n stream.write = (\n chunk: string | Uint8Array,\n encodingOrCallback?: BufferEncoding | ((error?: Error | null) => void),\n callback?: (error?: Error | null) => void,\n ) => {\n const encoding = typeof encodingOrCallback === 'string' ? encodingOrCallback : 'utf8'\n chunks.push(typeof chunk === 'string' ? Buffer.from(chunk, encoding) : Buffer.from(chunk))\n const onWrite = typeof encodingOrCallback === 'function' ? encodingOrCallback : callback\n if (onWrite) queueMicrotask(() => onWrite())\n return true\n }\n\n return {\n output: () => Buffer.concat(chunks).toString('utf8'),\n restore: () => {\n stream.write = originalWrite\n },\n }\n}\n\n/**\n * Returns a set of functions to get the outputs ocurred during a test run.\n *\n * @returns An mock object with all the output functions.\n */ export function mockAndCaptureOutput(): OutputMock {\n return {\n output: () => (collectedLogs.output ?? []).join('\\n'),\n info: () => (collectedLogs.info ?? []).join('\\n'),\n debug: () => (collectedLogs.debug ?? []).join('\\n'),\n success: () => (collectedLogs.success ?? []).join('\\n'),\n completed: () => (collectedLogs.completed ?? []).join('\\n'),\n warn: () => (collectedLogs.warn ?? []).join('\\n'),\n error: () => (collectedLogs.error ?? []).join('\\n'),\n clear: () => {\n clearCollectedLogs()\n // output.collectedLogs = {}\n },\n }\n}\n"]}
|
package/dist/public/node/ui.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ interface UIDebugOptions {
|
|
|
21
21
|
skipTTYCheck?: boolean;
|
|
22
22
|
}
|
|
23
23
|
export interface RenderConcurrentOptions extends PartialBy<ConcurrentOutputProps, 'abortSignal'> {
|
|
24
|
+
/** Ink options for terminal UI. Finite JSON output uses the command event channel on stderr instead. */
|
|
24
25
|
renderOptions?: RenderOptions;
|
|
25
26
|
}
|
|
26
27
|
/**
|
|
@@ -318,6 +319,8 @@ export declare function renderTasks<TContext>(tasks: Task<TContext>[], { renderO
|
|
|
318
319
|
export interface RenderSingleTaskOptions<T> {
|
|
319
320
|
title: TokenizedString;
|
|
320
321
|
task: (updateStatus: (status: TokenizedString) => void) => Promise<T>;
|
|
322
|
+
/** The number of additional attempts after a failure. Defaults to zero. */
|
|
323
|
+
retry?: number;
|
|
321
324
|
onAbort?: () => void;
|
|
322
325
|
renderOptions?: RenderOptions;
|
|
323
326
|
}
|
|
@@ -326,12 +329,13 @@ export interface RenderSingleTaskOptions<T> {
|
|
|
326
329
|
* @param options - Configuration object
|
|
327
330
|
* @param options.title - The initial title to display with the loading bar
|
|
328
331
|
* @param options.task - The async task to execute. Receives an updateStatus callback to change the displayed title.
|
|
332
|
+
* @param options.retry - The number of additional attempts after a failure. Defaults to zero.
|
|
329
333
|
* @param options.renderOptions - Optional render configuration
|
|
330
334
|
* @returns The result of the task
|
|
331
335
|
* @example
|
|
332
336
|
* Loading app ...
|
|
333
337
|
*/
|
|
334
|
-
export declare function renderSingleTask<T>({ title, task, onAbort, renderOptions, }: RenderSingleTaskOptions<T>): Promise<T>;
|
|
338
|
+
export declare function renderSingleTask<T>({ title, task, retry, onAbort, renderOptions, }: RenderSingleTaskOptions<T>): Promise<T>;
|
|
335
339
|
export interface RenderTextPromptOptions extends Omit<TextPromptProps, 'onSubmit'> {
|
|
336
340
|
renderOptions?: RenderOptions;
|
|
337
341
|
}
|
package/dist/public/node/ui.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/* eslint-disable tsdoc/syntax */
|
|
2
2
|
import { AbortError, AbortSilentError } from './error.js';
|
|
3
|
-
import {
|
|
3
|
+
import { commandEventOutputMode, emitCommandEvent } from './command-events.js';
|
|
4
|
+
import { randomUUID } from './crypto.js';
|
|
5
|
+
import { outputContent, outputDebug, outputToken, unstyled } from './output.js';
|
|
4
6
|
import { terminalSupportsPrompting } from './system.js';
|
|
5
7
|
import { AbortController } from './abort.js';
|
|
6
8
|
import { runWithTimer } from './metadata.js';
|
|
7
|
-
import { ConcurrentOutput } from '../../private/node/ui/components/ConcurrentOutput.js';
|
|
9
|
+
import { ConcurrentOutput, runConcurrentProcessesForJson, } from '../../private/node/ui/components/ConcurrentOutput.js';
|
|
8
10
|
import { handleCtrlC, render, renderOnce } from '../../private/node/ui.js';
|
|
9
11
|
import { alert } from '../../private/node/ui/alert.js';
|
|
10
12
|
import { FatalError } from '../../private/node/ui/components/FatalError.js';
|
|
@@ -13,6 +15,7 @@ import { tokenItemToString, } from '../../private/node/ui/components/token-item.
|
|
|
13
15
|
import { DangerousConfirmationPrompt, } from '../../private/node/ui/components/DangerousConfirmationPrompt.js';
|
|
14
16
|
import { SelectPrompt } from '../../private/node/ui/components/SelectPrompt.js';
|
|
15
17
|
import { Tasks } from '../../private/node/ui/components/Tasks.js';
|
|
18
|
+
import { runTasks } from '../../private/node/ui/tasks.js';
|
|
16
19
|
import { TextPrompt } from '../../private/node/ui/components/TextPrompt.js';
|
|
17
20
|
import { AutocompletePrompt } from '../../private/node/ui/components/AutocompletePrompt.js';
|
|
18
21
|
import { SingleTask } from '../../private/node/ui/components/SingleTask.js';
|
|
@@ -33,6 +36,15 @@ const defaultUIDebugOptions = {
|
|
|
33
36
|
*/
|
|
34
37
|
export async function renderConcurrent({ renderOptions, ...props }) {
|
|
35
38
|
const abortSignal = props.abortSignal ?? new AbortController().signal;
|
|
39
|
+
// Streaming callers retain their existing Ink lifecycle; finite JSON results must keep stdout clear.
|
|
40
|
+
if (commandEventOutputMode() === 'json' && !props.keepRunningAfterProcessesResolve) {
|
|
41
|
+
if (props.processes.length === 0)
|
|
42
|
+
return;
|
|
43
|
+
return renderSingleTask({
|
|
44
|
+
title: outputContent `Running concurrent processes`,
|
|
45
|
+
task: async () => runConcurrentProcessesForJson({ ...props, abortSignal }),
|
|
46
|
+
});
|
|
47
|
+
}
|
|
36
48
|
return render(React.createElement(ConcurrentOutput, { ...props, abortSignal: abortSignal }), renderOptions);
|
|
37
49
|
}
|
|
38
50
|
/**
|
|
@@ -231,6 +243,7 @@ export async function renderSelectPrompt({ renderOptions, isConfirmationPrompt,
|
|
|
231
243
|
await render(React.createElement(SelectPrompt, { ...props, onSubmit: (value) => {
|
|
232
244
|
selectedValue = value;
|
|
233
245
|
} }), {
|
|
246
|
+
stdout: process.stderr,
|
|
234
247
|
...renderOptions,
|
|
235
248
|
exitOnCtrlC: false,
|
|
236
249
|
});
|
|
@@ -342,6 +355,7 @@ export async function renderAutocompletePrompt({ renderOptions, ...props }, uiDe
|
|
|
342
355
|
await render(React.createElement(AutocompletePrompt, { ...newProps, onSubmit: (value) => {
|
|
343
356
|
selectedValue = value;
|
|
344
357
|
} }), {
|
|
358
|
+
stdout: process.stderr,
|
|
345
359
|
...renderOptions,
|
|
346
360
|
exitOnCtrlC: false,
|
|
347
361
|
});
|
|
@@ -369,6 +383,8 @@ export function renderTable({ renderOptions, ...props }) {
|
|
|
369
383
|
* Installing dependencies ...
|
|
370
384
|
*/
|
|
371
385
|
export async function renderTasks(tasks, { renderOptions, noProgressBar } = {}) {
|
|
386
|
+
if (commandEventOutputMode() === 'json')
|
|
387
|
+
return runTasks(tasks);
|
|
372
388
|
let taskResult;
|
|
373
389
|
await render(React.createElement(Tasks, { tasks: tasks, onComplete: (ctx) => {
|
|
374
390
|
taskResult = ctx;
|
|
@@ -384,16 +400,82 @@ export async function renderTasks(tasks, { renderOptions, noProgressBar } = {})
|
|
|
384
400
|
* @param options - Configuration object
|
|
385
401
|
* @param options.title - The initial title to display with the loading bar
|
|
386
402
|
* @param options.task - The async task to execute. Receives an updateStatus callback to change the displayed title.
|
|
403
|
+
* @param options.retry - The number of additional attempts after a failure. Defaults to zero.
|
|
387
404
|
* @param options.renderOptions - Optional render configuration
|
|
388
405
|
* @returns The result of the task
|
|
389
406
|
* @example
|
|
390
407
|
* Loading app ...
|
|
391
408
|
*/
|
|
392
|
-
export async function renderSingleTask({ title, task, onAbort, renderOptions, }) {
|
|
409
|
+
export async function renderSingleTask({ title, task, retry = 0, onAbort, renderOptions, }) {
|
|
410
|
+
// Keep updates correlated even when titles change or concurrent tasks share the same title.
|
|
411
|
+
const operation = randomUUID();
|
|
412
|
+
let currentStatus = title;
|
|
413
|
+
let aborted = false;
|
|
414
|
+
const abort = onAbort
|
|
415
|
+
? () => {
|
|
416
|
+
aborted = true;
|
|
417
|
+
onAbort();
|
|
418
|
+
}
|
|
419
|
+
: undefined;
|
|
420
|
+
const taskWithProgressEvents = async (updateStatus) => {
|
|
421
|
+
emitCommandEvent({ type: 'progress', operation, status: 'started', message: unstyled(currentStatus.value) }, { alreadyRendered: true });
|
|
422
|
+
const updateTaskStatus = (status) => {
|
|
423
|
+
currentStatus = status;
|
|
424
|
+
emitCommandEvent({ type: 'progress', operation, status: 'updated', message: unstyled(status.value) }, { alreadyRendered: true });
|
|
425
|
+
updateStatus(status);
|
|
426
|
+
};
|
|
427
|
+
for (let attempt = 0;; attempt++) {
|
|
428
|
+
let result;
|
|
429
|
+
try {
|
|
430
|
+
// eslint-disable-next-line no-await-in-loop
|
|
431
|
+
result = await task(updateTaskStatus);
|
|
432
|
+
}
|
|
433
|
+
catch (error) {
|
|
434
|
+
// A custom abort callback can reject the task; cancellation must not start another attempt.
|
|
435
|
+
if (aborted)
|
|
436
|
+
throw error;
|
|
437
|
+
const shouldRetry = attempt < retry;
|
|
438
|
+
emitCommandEvent({
|
|
439
|
+
type: 'progress',
|
|
440
|
+
operation,
|
|
441
|
+
status: shouldRetry ? 'retrying' : 'failed',
|
|
442
|
+
message: unstyled(currentStatus.value),
|
|
443
|
+
}, { alreadyRendered: true });
|
|
444
|
+
if (!shouldRetry)
|
|
445
|
+
throw error;
|
|
446
|
+
continue;
|
|
447
|
+
}
|
|
448
|
+
if (!aborted) {
|
|
449
|
+
emitCommandEvent({
|
|
450
|
+
type: 'progress',
|
|
451
|
+
operation,
|
|
452
|
+
status: 'completed',
|
|
453
|
+
message: unstyled(currentStatus.value),
|
|
454
|
+
current: 1,
|
|
455
|
+
total: 1,
|
|
456
|
+
}, { alreadyRendered: true });
|
|
457
|
+
}
|
|
458
|
+
return result;
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
if (commandEventOutputMode() === 'json') {
|
|
462
|
+
// Without Ink's raw input handling, Ctrl+C arrives as SIGINT. Leave the default
|
|
463
|
+
// signal behavior intact when the caller has no custom abort callback.
|
|
464
|
+
const onSigint = () => abort?.();
|
|
465
|
+
if (onAbort)
|
|
466
|
+
process.once('SIGINT', onSigint);
|
|
467
|
+
try {
|
|
468
|
+
return await taskWithProgressEvents(() => { });
|
|
469
|
+
}
|
|
470
|
+
finally {
|
|
471
|
+
if (onAbort)
|
|
472
|
+
process.removeListener('SIGINT', onSigint);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
393
475
|
let taskResult;
|
|
394
|
-
await render(React.createElement(SingleTask, { title: title, task:
|
|
476
|
+
await render(React.createElement(SingleTask, { title: title, task: taskWithProgressEvents, onComplete: (result) => {
|
|
395
477
|
taskResult = result;
|
|
396
|
-
}, onAbort:
|
|
478
|
+
}, onAbort: abort }), {
|
|
397
479
|
stdout: process.stderr,
|
|
398
480
|
...renderOptions,
|
|
399
481
|
exitOnCtrlC: false,
|
|
@@ -415,6 +497,7 @@ export async function renderTextPrompt({ renderOptions, ...props }, uiDebugOptio
|
|
|
415
497
|
await render(React.createElement(TextPrompt, { ...props, onSubmit: (value) => {
|
|
416
498
|
enteredText = value;
|
|
417
499
|
} }), {
|
|
500
|
+
stdout: process.stderr,
|
|
418
501
|
...renderOptions,
|
|
419
502
|
exitOnCtrlC: false,
|
|
420
503
|
});
|
|
@@ -451,6 +534,7 @@ export async function renderDangerousConfirmationPrompt({ renderOptions, ...prop
|
|
|
451
534
|
await render(React.createElement(DangerousConfirmationPrompt, { ...props, onSubmit: (value) => {
|
|
452
535
|
confirmed = value;
|
|
453
536
|
} }), {
|
|
537
|
+
stdout: process.stderr,
|
|
454
538
|
...renderOptions,
|
|
455
539
|
exitOnCtrlC: false,
|
|
456
540
|
});
|