@shopify/cli-kit 3.34.0 → 3.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/dist/git.js +2 -2
  2. package/dist/git.js.map +1 -1
  3. package/dist/http/fetch.js +1 -1
  4. package/dist/http/fetch.js.map +1 -1
  5. package/dist/index.d.ts +0 -3
  6. package/dist/index.js +0 -3
  7. package/dist/index.js.map +1 -1
  8. package/dist/npm.js +3 -3
  9. package/dist/npm.js.map +1 -1
  10. package/dist/output.js +3 -3
  11. package/dist/output.js.map +1 -1
  12. package/dist/private/node/api/graphql.js +1 -1
  13. package/dist/private/node/api/graphql.js.map +1 -1
  14. package/dist/private/node/api/headers.d.ts +2 -2
  15. package/dist/private/node/api/headers.js +3 -3
  16. package/dist/private/node/api/headers.js.map +1 -1
  17. package/dist/private/node/api/rest.d.ts +5 -3
  18. package/dist/private/node/api/rest.js +8 -7
  19. package/dist/private/node/api/rest.js.map +1 -1
  20. package/dist/private/node/constants.d.ts +42 -0
  21. package/dist/private/node/constants.js +58 -0
  22. package/dist/private/node/constants.js.map +1 -0
  23. package/dist/private/node/environment/service.js +2 -2
  24. package/dist/private/node/environment/service.js.map +1 -1
  25. package/dist/private/node/session/post-auth.js +8 -8
  26. package/dist/private/node/session/post-auth.js.map +1 -1
  27. package/dist/private/node/session/store.js +6 -6
  28. package/dist/private/node/session/store.js.map +1 -1
  29. package/dist/private/node/session/validate.js +2 -2
  30. package/dist/private/node/session/validate.js.map +1 -1
  31. package/dist/private/node/session.js +2 -2
  32. package/dist/private/node/session.js.map +1 -1
  33. package/dist/private/node/ui/components/SelectPrompt.d.ts +2 -1
  34. package/dist/private/node/ui/components/SelectPrompt.js +2 -1
  35. package/dist/private/node/ui/components/SelectPrompt.js.map +1 -1
  36. package/dist/private/node/ui/components/Table/Column.d.ts +5 -0
  37. package/dist/private/node/ui/components/Table/Column.js +2 -0
  38. package/dist/private/node/ui/components/Table/Column.js.map +1 -0
  39. package/dist/private/node/ui/components/Table/Row.d.ts +12 -0
  40. package/dist/private/node/ui/components/Table/Row.js +24 -0
  41. package/dist/private/node/ui/components/Table/Row.js.map +1 -0
  42. package/dist/private/node/ui/components/Table/ScalarDict.d.ts +5 -0
  43. package/dist/private/node/ui/components/Table/ScalarDict.js +2 -0
  44. package/dist/private/node/ui/components/Table/ScalarDict.js.map +1 -0
  45. package/dist/private/node/ui/components/Table/Table.d.ts +12 -0
  46. package/dist/private/node/ui/components/Table/Table.js +30 -0
  47. package/dist/private/node/ui/components/Table/Table.js.map +1 -0
  48. package/dist/private/node/ui/components/Table/Table.test.d.ts +1 -0
  49. package/dist/private/node/ui/components/Table/Table.test.js +41 -0
  50. package/dist/private/node/ui/components/Table/Table.test.js.map +1 -0
  51. package/dist/public/common/string.d.ts +11 -0
  52. package/dist/public/common/string.js +21 -0
  53. package/dist/public/common/string.js.map +1 -1
  54. package/dist/public/common/version.d.ts +1 -0
  55. package/dist/public/common/version.js +2 -0
  56. package/dist/public/common/version.js.map +1 -0
  57. package/dist/public/node/analytics.js +2 -2
  58. package/dist/public/node/analytics.js.map +1 -1
  59. package/dist/public/node/api/admin.d.ts +4 -1
  60. package/dist/public/node/api/admin.js +4 -3
  61. package/dist/public/node/api/admin.js.map +1 -1
  62. package/dist/public/node/cli.js +4 -4
  63. package/dist/public/node/cli.js.map +1 -1
  64. package/dist/public/node/dot-env.js +2 -2
  65. package/dist/public/node/dot-env.js.map +1 -1
  66. package/dist/public/node/environment/local.js +17 -17
  67. package/dist/public/node/environment/local.js.map +1 -1
  68. package/dist/public/node/environment/spin.js +5 -5
  69. package/dist/public/node/environment/spin.js.map +1 -1
  70. package/dist/public/node/error-handler.js +6 -5
  71. package/dist/public/node/error-handler.js.map +1 -1
  72. package/dist/public/node/fs.d.ts +222 -3
  73. package/dist/public/node/fs.js +338 -2
  74. package/dist/public/node/fs.js.map +1 -1
  75. package/dist/public/node/git.d.ts +90 -0
  76. package/dist/public/node/git.js +174 -0
  77. package/dist/public/node/git.js.map +1 -0
  78. package/dist/public/node/liquid.js +6 -6
  79. package/dist/public/node/liquid.js.map +1 -1
  80. package/dist/public/node/node-package-manager.d.ts +0 -10
  81. package/dist/public/node/node-package-manager.js +2 -19
  82. package/dist/public/node/node-package-manager.js.map +1 -1
  83. package/dist/public/node/presets.js +2 -2
  84. package/dist/public/node/presets.js.map +1 -1
  85. package/dist/public/node/ruby.js +8 -8
  86. package/dist/public/node/ruby.js.map +1 -1
  87. package/dist/public/node/session.js +2 -2
  88. package/dist/public/node/session.js.map +1 -1
  89. package/dist/public/node/ui.d.ts +13 -0
  90. package/dist/public/node/ui.js +14 -0
  91. package/dist/public/node/ui.js.map +1 -1
  92. package/dist/public/node/vscode.js +5 -5
  93. package/dist/public/node/vscode.js.map +1 -1
  94. package/dist/secure-store.js +4 -4
  95. package/dist/secure-store.js.map +1 -1
  96. package/dist/store.d.ts +10 -10
  97. package/dist/store.js +21 -22
  98. package/dist/store.js.map +1 -1
  99. package/dist/testing/store.js +3 -3
  100. package/dist/testing/store.js.map +1 -1
  101. package/dist/tsconfig.tsbuildinfo +1 -1
  102. package/dist/ui.js +3 -3
  103. package/dist/ui.js.map +1 -1
  104. package/package.json +2 -2
  105. package/dist/constants.d.ts +0 -48
  106. package/dist/constants.js +0 -67
  107. package/dist/constants.js.map +0 -1
  108. package/dist/file.d.ts +0 -98
  109. package/dist/file.js +0 -216
  110. package/dist/file.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../../src/public/node/error-handler.ts"],"names":[],"mappings":"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","sourcesContent":["import {reportAnalyticsEvent} from './analytics.js'\nimport {getEnvironmentData} from '../../private/node/analytics.js'\nimport {\n AbortSilent,\n CancelExecution,\n mapper as errorMapper,\n shouldReport as shouldReportError,\n handler,\n cleanSingleStackTracePath,\n} from '../../error.js'\nimport {debug, info} from '../../output.js'\nimport * as path from '../../path.js'\nimport * as metadata from '../../metadata.js'\nimport {fanoutHooks} from '../../plugins.js'\nimport constants, {bugsnagApiKey} from '../../constants.js'\nimport {settings, Interfaces} from '@oclif/core'\nimport StackTracey from 'stacktracey'\nimport Bugsnag, {Event} from '@bugsnag/js'\nimport {realpath} from 'fs/promises'\n\nexport function errorHandler(\n error: (CancelExecution | AbortSilent) & {exitCode?: number | undefined},\n config?: Interfaces.Config,\n): void\nexport function errorHandler(error: Error & {exitCode?: number | undefined}, config?: Interfaces.Config): Promise<void>\nexport function errorHandler(error: Error & {exitCode?: number | undefined}, config?: Interfaces.Config): unknown {\n if (error instanceof CancelExecution) {\n if (error.message && error.message !== '') {\n info(`✨ ${error.message}`)\n }\n } else if (error instanceof AbortSilent) {\n process.exit(1)\n } else {\n return errorMapper(error)\n .then((error) => {\n return handler(error)\n })\n .then((mappedError) => reportError(mappedError, config))\n .then(() => {\n process.exit(1)\n })\n }\n}\n\nconst reportError = async (error: unknown, config?: Interfaces.Config): Promise<void> => {\n if (config !== undefined) {\n // Log an analytics event when there's an error\n await reportAnalyticsEvent({config, errorMessage: error instanceof Error ? error.message : undefined})\n }\n await sendErrorToBugsnag(error)\n}\n\n/**\n * Sends an error to Bugsnag. This is configured automatically for uncaught errors from CLI commands, but can also be used to manually record an error.\n *\n * @returns the reported error (this may have been tweaked for better reporting), and a bool to indicate if the error was actually submitted or not\n */\nexport async function sendErrorToBugsnag(\n error: unknown,\n): Promise<{reported: false; error: unknown} | {error: Error; reported: true}> {\n if (settings.debug || !shouldReportError(error)) return {reported: false, error}\n\n let reportableError: Error\n let stacktrace: string | undefined\n let report = false\n\n if (error instanceof Error) {\n report = true\n reportableError = new Error(error.message)\n stacktrace = error.stack\n\n /**\n * Some errors that reach this point have an empty string. For example:\n * https://app.bugsnag.com/shopify/cli/errors/62cd5d31fd5040000814086c?filters[event.since]=30d&filters[error.status]=new&filters[release.seen_in]=3.1.0\n *\n * Because at this point we have neither the error message nor a stack trace reporting them\n * to Bugsnag is pointless and adds noise.\n */\n } else if (typeof error === 'string' && error.trim().length !== 0) {\n report = true\n reportableError = new Error(error)\n stacktrace = reportableError.stack\n } else {\n report = false\n reportableError = new Error('Unknown error')\n }\n\n const formattedStacktrace = new StackTracey(stacktrace ?? '')\n .clean()\n .items.map((item) => {\n const filePath = cleanSingleStackTracePath(item.file)\n return ` at ${item.callee} (${filePath}:${item.line}:${item.column})`\n })\n .join('\\n')\n reportableError.stack = `Error: ${reportableError.message}\\n${formattedStacktrace}`\n\n if (report) {\n await initializeBugsnag()\n await new Promise((resolve, reject) => {\n Bugsnag.notify(reportableError, undefined, (error, event) => {\n if (error) {\n reject(error)\n } else {\n resolve(reportableError)\n }\n })\n })\n }\n return {error: reportableError, reported: report}\n}\n\n/**\n * If the given file path is within a node_modules folder, remove prefix up\n * to and including the node_modules folder.\n *\n * This gives us very consistent paths for errors generated by the CLI.\n */\nexport function cleanStackFrameFilePath({\n currentFilePath,\n projectRoot,\n pluginLocations,\n}: {\n currentFilePath: string\n projectRoot: string\n pluginLocations: {name: string; pluginPath: string}[]\n}): string {\n const fullLocation = path.isAbsolute(currentFilePath) ? currentFilePath : path.join(projectRoot, currentFilePath)\n\n const matchingPluginPath = pluginLocations.filter(({pluginPath}) => fullLocation.indexOf(pluginPath) === 0)[0]\n\n if (matchingPluginPath !== undefined) {\n // the plugin name (e.g. @shopify/cli-kit), plus the relative path of the error line from within the plugin's code (e.g. dist/something.js )\n return path.join(matchingPluginPath.name, path.relative(matchingPluginPath.pluginPath, fullLocation))\n }\n\n // strip prefix up to node_modules folder, so we can normalize error reporting\n return currentFilePath.replace(/.*node_modules\\//, '')\n}\n\n/**\n * Register a Bugsnag error listener to clean up stack traces for errors within plugin code.\n *\n */\nexport async function registerCleanBugsnagErrorsFromWithinPlugins(config: Interfaces.Config): Promise<void> {\n // Bugsnag have their own plug-ins that use this private field\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const bugsnagConfigProjectRoot: string = (Bugsnag as any)?._client?._config?.projectRoot ?? process.cwd()\n const projectRoot = path.normalize(bugsnagConfigProjectRoot)\n const pluginLocations = await Promise.all(\n config.plugins.map(async (plugin) => {\n const followSymlinks = await realpath(plugin.root)\n return {name: plugin.name, pluginPath: path.normalize(followSymlinks)}\n }),\n )\n await initializeBugsnag()\n Bugsnag.addOnError(async (event) => {\n event.errors.forEach((error) => {\n error.stacktrace.forEach((stackFrame) => {\n stackFrame.file = cleanStackFrameFilePath({currentFilePath: stackFrame.file, projectRoot, pluginLocations})\n })\n })\n try {\n await addBugsnagMetadata(event, config)\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (metadataError) {\n debug(`There was an error adding metadata to the Bugsnag report; Ignoring and carrying on ${metadataError}`)\n }\n })\n}\n\nexport async function addBugsnagMetadata(event: Event, config: Interfaces.Config): Promise<void> {\n const publicData = metadata.getAllPublic()\n const {commandStartOptions} = metadata.getAllSensitive()\n const {startCommand} = commandStartOptions ?? {}\n\n const {'@shopify/app': appPublic, ...otherPluginsPublic} = await fanoutHooks(config, 'public_command_metadata', {})\n\n const environment = await getEnvironmentData(config)\n\n const allMetadata = {\n command: startCommand,\n ...appPublic,\n ...publicData,\n ...environment,\n pluginData: otherPluginsPublic,\n }\n\n const appData = {} as {[key: string]: unknown}\n const commandData = {} as {[key: string]: unknown}\n const environmentData = {} as {[key: string]: unknown}\n const miscData = {} as {[key: string]: unknown}\n const appKeys = ['api_key', 'partner_id', 'project_type']\n const commandKeys = ['command']\n const environmentKeys = ['cli_version', 'node_version', 'ruby_version', 'uname']\n\n Object.entries(allMetadata).forEach(([key, value]) => {\n if (key.startsWith('app_') || appKeys.includes(key)) {\n appData[key] = value\n } else if (key.startsWith('cmd_') || commandKeys.includes(key)) {\n commandData[key] = value\n } else if (key.startsWith('env_') || environmentKeys) {\n environmentData[key] = value\n } else {\n miscData[key] = value\n }\n })\n\n // app, command, environment, misc\n const bugsnagMetadata = {\n 'Shopify App': appData,\n Command: commandData,\n Environment: environmentData,\n Misc: miscData,\n }\n Object.entries(bugsnagMetadata).forEach(([section, values]) => {\n event.addMetadata(section, values)\n })\n}\n\nasync function initializeBugsnag() {\n if (Bugsnag.isStarted()) {\n return\n }\n Bugsnag.start({\n appType: 'node',\n apiKey: bugsnagApiKey,\n logger: null,\n appVersion: await constants.versions.cliKit(),\n autoTrackSessions: false,\n autoDetectErrors: false,\n })\n}\n"]}
1
+ {"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../../src/public/node/error-handler.ts"],"names":[],"mappings":"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","sourcesContent":["import {reportAnalyticsEvent} from './analytics.js'\nimport {getEnvironmentData} from '../../private/node/analytics.js'\nimport {\n AbortSilent,\n CancelExecution,\n mapper as errorMapper,\n shouldReport as shouldReportError,\n handler,\n cleanSingleStackTracePath,\n} from '../../error.js'\nimport {debug, info} from '../../output.js'\nimport * as path from '../../path.js'\nimport * as metadata from '../../metadata.js'\nimport {fanoutHooks} from '../../plugins.js'\nimport {bugsnagApiKey} from '../../private/node/constants.js'\nimport {CLI_KIT_VERSION} from '../common/version.js'\nimport {settings, Interfaces} from '@oclif/core'\nimport StackTracey from 'stacktracey'\nimport Bugsnag, {Event} from '@bugsnag/js'\nimport {realpath} from 'fs/promises'\n\nexport function errorHandler(\n error: (CancelExecution | AbortSilent) & {exitCode?: number | undefined},\n config?: Interfaces.Config,\n): void\nexport function errorHandler(error: Error & {exitCode?: number | undefined}, config?: Interfaces.Config): Promise<void>\nexport function errorHandler(error: Error & {exitCode?: number | undefined}, config?: Interfaces.Config): unknown {\n if (error instanceof CancelExecution) {\n if (error.message && error.message !== '') {\n info(`✨ ${error.message}`)\n }\n } else if (error instanceof AbortSilent) {\n process.exit(1)\n } else {\n return errorMapper(error)\n .then((error) => {\n return handler(error)\n })\n .then((mappedError) => reportError(mappedError, config))\n .then(() => {\n process.exit(1)\n })\n }\n}\n\nconst reportError = async (error: unknown, config?: Interfaces.Config): Promise<void> => {\n if (config !== undefined) {\n // Log an analytics event when there's an error\n await reportAnalyticsEvent({config, errorMessage: error instanceof Error ? error.message : undefined})\n }\n await sendErrorToBugsnag(error)\n}\n\n/**\n * Sends an error to Bugsnag. This is configured automatically for uncaught errors from CLI commands, but can also be used to manually record an error.\n *\n * @returns the reported error (this may have been tweaked for better reporting), and a bool to indicate if the error was actually submitted or not\n */\nexport async function sendErrorToBugsnag(\n error: unknown,\n): Promise<{reported: false; error: unknown} | {error: Error; reported: true}> {\n if (settings.debug || !shouldReportError(error)) return {reported: false, error}\n\n let reportableError: Error\n let stacktrace: string | undefined\n let report = false\n\n if (error instanceof Error) {\n report = true\n reportableError = new Error(error.message)\n stacktrace = error.stack\n\n /**\n * Some errors that reach this point have an empty string. For example:\n * https://app.bugsnag.com/shopify/cli/errors/62cd5d31fd5040000814086c?filters[event.since]=30d&filters[error.status]=new&filters[release.seen_in]=3.1.0\n *\n * Because at this point we have neither the error message nor a stack trace reporting them\n * to Bugsnag is pointless and adds noise.\n */\n } else if (typeof error === 'string' && error.trim().length !== 0) {\n report = true\n reportableError = new Error(error)\n stacktrace = reportableError.stack\n } else {\n report = false\n reportableError = new Error('Unknown error')\n }\n\n const formattedStacktrace = new StackTracey(stacktrace ?? '')\n .clean()\n .items.map((item) => {\n const filePath = cleanSingleStackTracePath(item.file)\n return ` at ${item.callee} (${filePath}:${item.line}:${item.column})`\n })\n .join('\\n')\n reportableError.stack = `Error: ${reportableError.message}\\n${formattedStacktrace}`\n\n if (report) {\n initializeBugsnag()\n await new Promise((resolve, reject) => {\n Bugsnag.notify(reportableError, undefined, (error, event) => {\n if (error) {\n reject(error)\n } else {\n resolve(reportableError)\n }\n })\n })\n }\n return {error: reportableError, reported: report}\n}\n\n/**\n * If the given file path is within a node_modules folder, remove prefix up\n * to and including the node_modules folder.\n *\n * This gives us very consistent paths for errors generated by the CLI.\n */\nexport function cleanStackFrameFilePath({\n currentFilePath,\n projectRoot,\n pluginLocations,\n}: {\n currentFilePath: string\n projectRoot: string\n pluginLocations: {name: string; pluginPath: string}[]\n}): string {\n const fullLocation = path.isAbsolute(currentFilePath) ? currentFilePath : path.join(projectRoot, currentFilePath)\n\n const matchingPluginPath = pluginLocations.filter(({pluginPath}) => fullLocation.indexOf(pluginPath) === 0)[0]\n\n if (matchingPluginPath !== undefined) {\n // the plugin name (e.g. @shopify/cli-kit), plus the relative path of the error line from within the plugin's code (e.g. dist/something.js )\n return path.join(matchingPluginPath.name, path.relative(matchingPluginPath.pluginPath, fullLocation))\n }\n\n // strip prefix up to node_modules folder, so we can normalize error reporting\n return currentFilePath.replace(/.*node_modules\\//, '')\n}\n\n/**\n * Register a Bugsnag error listener to clean up stack traces for errors within plugin code.\n *\n */\nexport async function registerCleanBugsnagErrorsFromWithinPlugins(config: Interfaces.Config): Promise<void> {\n // Bugsnag have their own plug-ins that use this private field\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const bugsnagConfigProjectRoot: string = (Bugsnag as any)?._client?._config?.projectRoot ?? process.cwd()\n const projectRoot = path.normalize(bugsnagConfigProjectRoot)\n const pluginLocations = await Promise.all(\n config.plugins.map(async (plugin) => {\n const followSymlinks = await realpath(plugin.root)\n return {name: plugin.name, pluginPath: path.normalize(followSymlinks)}\n }),\n )\n initializeBugsnag()\n Bugsnag.addOnError(async (event) => {\n event.errors.forEach((error) => {\n error.stacktrace.forEach((stackFrame) => {\n stackFrame.file = cleanStackFrameFilePath({currentFilePath: stackFrame.file, projectRoot, pluginLocations})\n })\n })\n try {\n await addBugsnagMetadata(event, config)\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (metadataError) {\n debug(`There was an error adding metadata to the Bugsnag report; Ignoring and carrying on ${metadataError}`)\n }\n })\n}\n\nexport async function addBugsnagMetadata(event: Event, config: Interfaces.Config): Promise<void> {\n const publicData = metadata.getAllPublic()\n const {commandStartOptions} = metadata.getAllSensitive()\n const {startCommand} = commandStartOptions ?? {}\n\n const {'@shopify/app': appPublic, ...otherPluginsPublic} = await fanoutHooks(config, 'public_command_metadata', {})\n\n const environment = await getEnvironmentData(config)\n\n const allMetadata = {\n command: startCommand,\n ...appPublic,\n ...publicData,\n ...environment,\n pluginData: otherPluginsPublic,\n }\n\n const appData = {} as {[key: string]: unknown}\n const commandData = {} as {[key: string]: unknown}\n const environmentData = {} as {[key: string]: unknown}\n const miscData = {} as {[key: string]: unknown}\n const appKeys = ['api_key', 'partner_id', 'project_type']\n const commandKeys = ['command']\n const environmentKeys = ['cli_version', 'node_version', 'ruby_version', 'uname']\n\n Object.entries(allMetadata).forEach(([key, value]) => {\n if (key.startsWith('app_') || appKeys.includes(key)) {\n appData[key] = value\n } else if (key.startsWith('cmd_') || commandKeys.includes(key)) {\n commandData[key] = value\n } else if (key.startsWith('env_') || environmentKeys) {\n environmentData[key] = value\n } else {\n miscData[key] = value\n }\n })\n\n // app, command, environment, misc\n const bugsnagMetadata = {\n 'Shopify App': appData,\n Command: commandData,\n Environment: environmentData,\n Misc: miscData,\n }\n Object.entries(bugsnagMetadata).forEach(([section, values]) => {\n event.addMetadata(section, values)\n })\n}\n\nfunction initializeBugsnag() {\n if (Bugsnag.isStarted()) {\n return\n }\n Bugsnag.start({\n appType: 'node',\n apiKey: bugsnagApiKey,\n logger: null,\n appVersion: CLI_KIT_VERSION,\n autoTrackSessions: false,\n autoDetectErrors: false,\n })\n}\n"]}
@@ -1,16 +1,235 @@
1
- import type { RandomNameFamily } from '../common/string.js';
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ import { RandomNameFamily } from '../common/string.js';
4
+ import { ReadStream } from 'fs';
5
+ /**
6
+ * Strip the first `strip` parts of the path.
7
+ *
8
+ * @param path - Path to strip.
9
+ * @param strip - Number of parts to strip.
10
+ * @returns The stripped path.
11
+ */
12
+ export declare function stripUpPath(path: string, strip: number): string;
13
+ /**
14
+ * Creates a temporary directory and ties its lifecycle to the lifecycle of the callback.
15
+ *
16
+ * @param callback - The callback that receives the temporary directory.
17
+ */
18
+ export declare function inTemporaryDirectory<T>(callback: (tmpDir: string) => T | Promise<T>): Promise<T>;
19
+ /**
20
+ * It reads a file and returns its content as a string using the
21
+ * utf-8 encoding.
22
+ *
23
+ * @param path - Path to the file to read.
24
+ * @returns A promise that resolves with the content of the file.
25
+ */
26
+ export declare type ReadOptions = undefined | {
27
+ flag?: string | undefined;
28
+ } | {
29
+ encoding: BufferEncoding | string;
30
+ flag?: string | undefined;
31
+ };
32
+ export declare function readFile(path: string, options?: ReadOptions): Promise<string>;
33
+ export declare function readFile(path: string, options?: ReadOptions): Promise<Buffer>;
34
+ /**
35
+ * Synchronously reads a file and returns its content as a string.
36
+ *
37
+ * @param path - Path to the file to read.
38
+ * @param options - Options to read the file with (defaults to utf-8 encoding).
39
+ * @returns The content of the file.
40
+ */
41
+ export declare function readSync(path: string, options?: object): string;
42
+ /**
43
+ * Given a path, it determines the actual path. This is useful when working
44
+ * with paths that represent symlinks.
45
+ *
46
+ * @param path - Path whose real path will be returned.
47
+ */
48
+ export declare function fileRealPath(path: string): Promise<string>;
49
+ /**
50
+ * Copies a file.
51
+ *
52
+ * @param from - Path to the directory or file to be copied.
53
+ * @param to - Destination path.
54
+ */
55
+ export declare function copyFile(from: string, to: string): Promise<void>;
56
+ /**
57
+ * Creates a file at the given path.
58
+ *
59
+ * @param path - Path to the file to be created.
60
+ */
61
+ export declare function touchFile(path: string): Promise<void>;
62
+ /**
63
+ * Synchronously creates a file at the given path.
64
+ *
65
+ * @param path - Path to the file to be created.
66
+ */
67
+ export declare function touchFileSync(path: string): void;
68
+ /**
69
+ * Appnds content to file at path.
70
+ *
71
+ * @param path - Path to the file to be appended.
72
+ * @param content - Content to be appended.
73
+ */
74
+ export declare function appendFile(path: string, content: string): Promise<void>;
75
+ /**
76
+ * Synchronously appends content to file at path.
77
+ *
78
+ * @param path - Path to the file to be appended.
79
+ * @param data - Content to be appended.
80
+ */
81
+ export declare function appendFileSync(path: string, data: string): void;
82
+ /**
83
+ * Writes content to file at path.
84
+ *
85
+ * @param path - Path to the file to be written.
86
+ * @param data - Content to be written.
87
+ */
88
+ export declare function writeFile(path: string, data: string): Promise<void>;
89
+ /**
90
+ * Synchronously writes content to file at path.
91
+ *
92
+ * @param path - Path to the file to be written.
93
+ * @param data - Content to be written.
94
+ */
95
+ export declare function writeFileSync(path: string, data: string): void;
96
+ /**
97
+ * Creates a directory at the given path.
98
+ *
99
+ * @param path - Path to the directory to be created.
100
+ */
101
+ export declare function mkdir(path: string): Promise<void>;
102
+ /**
103
+ * Synchronously creates a directory at the given path.
104
+ *
105
+ * @param path - Path to the directory to be created.
106
+ */
107
+ export declare function mkdirSync(path: string): void;
108
+ /**
109
+ * Removes a file at the given path.
110
+ *
111
+ * @param path - Path to the file to be removed.
112
+ */
113
+ export declare function removeFile(path: string): Promise<void>;
114
+ /**
115
+ * Synchronously removes a file at the given path.
116
+ *
117
+ * @param path - Path to the file to be removed.
118
+ */
119
+ export declare function removeFileSync(path: string): void;
120
+ interface RmDirOptions {
121
+ force?: boolean;
122
+ }
123
+ /**
124
+ * Removes a directory at the given path.
125
+ *
126
+ * @param path - Path to the directory to be removed.
127
+ * @param options - Options to remove the directory with.
128
+ */
129
+ export declare function rmdir(path: string, options?: RmDirOptions): Promise<void>;
130
+ /**
131
+ * Create a temporary directory.
132
+ *
133
+ * @returns Path to the temporary directory.
134
+ */
135
+ export declare function mkTmpDir(): Promise<string>;
136
+ /**
137
+ * Check whether a path is a directory.
138
+ *
139
+ * @param path - Path to check.
140
+ * @returns True if the path is a directory, false otherwise.
141
+ */
142
+ export declare function isDirectory(path: string): Promise<boolean>;
143
+ /**
144
+ * Get the size of a file.
145
+ *
146
+ * @param path - Path to the file.
147
+ * @returns The size of the file in bytes.
148
+ */
149
+ export declare function fileSize(path: string): Promise<number>;
150
+ /**
151
+ * Synchronously get the size of a file.
152
+ *
153
+ * @param path - Path to the file.
154
+ * @returns The size of the file in bytes.
155
+ */
156
+ export declare function fileSizeSync(path: string): number;
157
+ /**
158
+ * Create a read stream for a file.
159
+ *
160
+ * @param path - Path to the file.
161
+ * @returns A read stream for the file.
162
+ */
163
+ export declare function createFileReadStream(path: string): ReadStream;
164
+ /**
165
+ * Returns the Date object for the last modification of a file.
166
+ *
167
+ * @param path - Path to the directory or file.
168
+ * @returns A unix timestamp.
169
+ */
170
+ export declare function fileLastUpdated(path: string): Promise<Date>;
171
+ /**
172
+ * Returns the unix timestamp of the last modification of a file.
173
+ *
174
+ * @param path - Path to the directory or file.
175
+ * @returns A unix timestamp.
176
+ */
177
+ export declare function fileLastUpdatedTimestamp(path: string): Promise<number | undefined>;
178
+ interface MoveFileOptions {
179
+ overwrite?: boolean;
180
+ }
181
+ /**
182
+ * Moves a file.
183
+ *
184
+ * @param src - File to be moved.
185
+ * @param dest - Path to be moved to.
186
+ * @param options - Moving options.
187
+ */
188
+ export declare function moveFile(src: string, dest: string, options?: MoveFileOptions): Promise<void>;
189
+ /**
190
+ * Changes the permissions of a directory or file.
191
+ *
192
+ * @param path - Path to the file or directory whose permissions will be modified.
193
+ * @param mode - Permissions to set to the file or directory.
194
+ */
195
+ export declare function chmod(path: string, mode: number | string): Promise<void>;
196
+ /**
197
+ * Checks if a file has executable permissions.
198
+ *
199
+ * @param path - Path to the file whose permissions will be checked.
200
+ */
201
+ export declare function fileHasExecutablePermissions(path: string): Promise<boolean>;
202
+ /**
203
+ * Returns true if a file or directory exists.
204
+ *
205
+ * @param path - Path to the directory or file.
206
+ * @returns True if it exists.
207
+ */
208
+ export declare function fileExists(path: string): Promise<boolean>;
209
+ interface FileOptions {
210
+ path: string;
211
+ }
212
+ /**
213
+ * Format a string using prettier. Return the formatted content.
214
+ *
215
+ * @param content - Content to be formatted.
216
+ * @param options - Options to format the content with.
217
+ * @returns The formatted content.
218
+ */
219
+ export declare function fileContentPrettyFormat(content: string, options: FileOptions): Promise<string>;
2
220
  interface GenerateRandomDirectoryOptions {
3
- /** Suffix to include in the randomly generated directory name */
221
+ /** Suffix to include in the randomly generated directory name. */
4
222
  suffix: string;
5
223
  /** Absolute path to the directory where the random directory will be created. */
6
224
  directory: string;
7
- /** Type of word to use for random name */
225
+ /** Type of word to use for random name. */
8
226
  family?: RandomNameFamily;
9
227
  }
10
228
  /**
11
229
  * It generates a random directory directory name for a sub-directory.
12
230
  * It ensures that the returned directory name doesn't exist.
13
231
  *
232
+ * @param options - Options to generate the random directory name.
14
233
  * @returns It returns the name of the directory.
15
234
  */
16
235
  export declare function generateRandomNameForSubdirectory(options: GenerateRandomDirectoryOptions): Promise<string>;
@@ -1,10 +1,346 @@
1
- import { exists as fileExists } from '../../file.js';
2
- import { join as joinPath } from '../../path.js';
1
+ import { content as outputContent, token, debug } from '../../output.js';
3
2
  import { getRandomName } from '../common/string.js';
3
+ import { join as joinPath } from '../../path.js';
4
+ import { copy as fsCopy, ensureFile as fsEnsureFile, ensureFileSync as fsEnsureFileSync, remove as fsRemove, removeSync as fsRemoveSync, move as fsMove,
5
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
6
+ // @ts-ignore
7
+ } from 'fs-extra/esm';
8
+ import { temporaryDirectoryTask } from 'tempy';
9
+ import { sep, join, extname } from 'pathe';
10
+ import { mkdirSync as fsMkdirSync, readFileSync as fsReadFileSync, writeFileSync as fsWriteFileSync, appendFileSync as fsAppendFileSync, statSync as fsStatSync, createReadStream as fsCreateReadStream, constants as fsConstants, } from 'fs';
11
+ import { mkdir as fsMkdir, writeFile as fsWriteFile, readFile as fsReadFile, realpath as fsRealPath, appendFile as fsAppendFile, mkdtemp as fsMkdtemp, stat as fsStat, lstat as fsLstat, chmod as fsChmod, access as fsAccess, } from 'fs/promises';
12
+ const DEFAULT_PRETTIER_CONFIG = {
13
+ arrowParens: 'always',
14
+ singleQuote: true,
15
+ bracketSpacing: false,
16
+ trailingComma: 'all',
17
+ };
18
+ /**
19
+ * Strip the first `strip` parts of the path.
20
+ *
21
+ * @param path - Path to strip.
22
+ * @param strip - Number of parts to strip.
23
+ * @returns The stripped path.
24
+ */
25
+ export function stripUpPath(path, strip) {
26
+ const parts = path.split(sep);
27
+ return join(...parts.slice(strip));
28
+ }
29
+ /**
30
+ * Creates a temporary directory and ties its lifecycle to the lifecycle of the callback.
31
+ *
32
+ * @param callback - The callback that receives the temporary directory.
33
+ */
34
+ export async function inTemporaryDirectory(callback) {
35
+ return temporaryDirectoryTask(callback);
36
+ }
37
+ /**
38
+ * It reads a file and returns its content as a string.
39
+ * Uses utf-8 encoding by default.
40
+ *
41
+ * @param path - Path to the file to read.
42
+ * @param options - Options to read the file with (defaults to utf-8 encoding).
43
+ * @returns A promise that resolves with the content of the file.
44
+ */
45
+ export async function readFile(path, options = { encoding: 'utf8' }) {
46
+ debug(outputContent `Reading the content of file at ${token.path(path)}...`);
47
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
48
+ // @ts-ignore
49
+ return fsReadFile(path, options);
50
+ }
51
+ /**
52
+ * Synchronously reads a file and returns its content as a string.
53
+ *
54
+ * @param path - Path to the file to read.
55
+ * @param options - Options to read the file with (defaults to utf-8 encoding).
56
+ * @returns The content of the file.
57
+ */
58
+ export function readSync(path, options = { encoding: 'utf-8' }) {
59
+ debug(outputContent `Sync-reading the content of file at ${token.path(path)}...`);
60
+ const content = fsReadFileSync(path, options);
61
+ return content.toString();
62
+ }
63
+ /**
64
+ * Given a path, it determines the actual path. This is useful when working
65
+ * with paths that represent symlinks.
66
+ *
67
+ * @param path - Path whose real path will be returned.
68
+ */
69
+ export async function fileRealPath(path) {
70
+ return fsRealPath(path);
71
+ }
72
+ /**
73
+ * Copies a file.
74
+ *
75
+ * @param from - Path to the directory or file to be copied.
76
+ * @param to - Destination path.
77
+ */
78
+ export async function copyFile(from, to) {
79
+ debug(outputContent `Copying file from ${token.path(from)} to ${token.path(to)}...`);
80
+ await fsCopy(from, to);
81
+ }
82
+ /**
83
+ * Creates a file at the given path.
84
+ *
85
+ * @param path - Path to the file to be created.
86
+ */
87
+ export async function touchFile(path) {
88
+ debug(outputContent `Creating an empty file at ${token.path(path)}...`);
89
+ await fsEnsureFile(path);
90
+ }
91
+ /**
92
+ * Synchronously creates a file at the given path.
93
+ *
94
+ * @param path - Path to the file to be created.
95
+ */
96
+ export function touchFileSync(path) {
97
+ debug(outputContent `Creating an empty file at ${token.path(path)}...`);
98
+ fsEnsureFileSync(path);
99
+ }
100
+ /**
101
+ * Appnds content to file at path.
102
+ *
103
+ * @param path - Path to the file to be appended.
104
+ * @param content - Content to be appended.
105
+ */
106
+ export async function appendFile(path, content) {
107
+ debug(outputContent `Appending the following content to ${token.path(path)}:
108
+ ${content
109
+ .split('\n')
110
+ .map((line) => ` ${line}`)
111
+ .join('\n')}
112
+ `);
113
+ await fsAppendFile(path, content);
114
+ }
115
+ /**
116
+ * Synchronously appends content to file at path.
117
+ *
118
+ * @param path - Path to the file to be appended.
119
+ * @param data - Content to be appended.
120
+ */
121
+ export function appendFileSync(path, data) {
122
+ fsAppendFileSync(path, data);
123
+ }
124
+ /**
125
+ * Writes content to file at path.
126
+ *
127
+ * @param path - Path to the file to be written.
128
+ * @param data - Content to be written.
129
+ */
130
+ export async function writeFile(path, data) {
131
+ debug(outputContent `Writing some content to file at ${token.path(path)}...`);
132
+ await fsWriteFile(path, data, { encoding: 'utf8' });
133
+ }
134
+ /**
135
+ * Synchronously writes content to file at path.
136
+ *
137
+ * @param path - Path to the file to be written.
138
+ * @param data - Content to be written.
139
+ */
140
+ export function writeFileSync(path, data) {
141
+ debug(outputContent `File-writing some content to file at ${token.path(path)}...`);
142
+ fsWriteFileSync(path, data);
143
+ }
144
+ /**
145
+ * Creates a directory at the given path.
146
+ *
147
+ * @param path - Path to the directory to be created.
148
+ */
149
+ export async function mkdir(path) {
150
+ debug(outputContent `Creating directory at ${token.path(path)}...`);
151
+ await fsMkdir(path, { recursive: true });
152
+ }
153
+ /**
154
+ * Synchronously creates a directory at the given path.
155
+ *
156
+ * @param path - Path to the directory to be created.
157
+ */
158
+ export function mkdirSync(path) {
159
+ debug(outputContent `Sync-creating directory at ${token.path(path)}...`);
160
+ fsMkdirSync(path, { recursive: true });
161
+ }
162
+ /**
163
+ * Removes a file at the given path.
164
+ *
165
+ * @param path - Path to the file to be removed.
166
+ */
167
+ export async function removeFile(path) {
168
+ debug(outputContent `Removing file at ${token.path(path)}...`);
169
+ await fsRemove(path);
170
+ }
171
+ /**
172
+ * Synchronously removes a file at the given path.
173
+ *
174
+ * @param path - Path to the file to be removed.
175
+ */
176
+ export function removeFileSync(path) {
177
+ debug(outputContent `Sync-removing file at ${token.path(path)}...`);
178
+ fsRemoveSync(path);
179
+ }
180
+ /**
181
+ * Removes a directory at the given path.
182
+ *
183
+ * @param path - Path to the directory to be removed.
184
+ * @param options - Options to remove the directory with.
185
+ */
186
+ export async function rmdir(path, options = {}) {
187
+ const { default: del } = await import('del');
188
+ debug(outputContent `Removing directory at ${token.path(path)}...`);
189
+ await del(path, { force: options.force });
190
+ }
191
+ /**
192
+ * Create a temporary directory.
193
+ *
194
+ * @returns Path to the temporary directory.
195
+ */
196
+ export async function mkTmpDir() {
197
+ debug(outputContent `Creating a temporary directory...`);
198
+ const directory = await fsMkdtemp('tmp-');
199
+ return directory;
200
+ }
201
+ /**
202
+ * Check whether a path is a directory.
203
+ *
204
+ * @param path - Path to check.
205
+ * @returns True if the path is a directory, false otherwise.
206
+ */
207
+ export async function isDirectory(path) {
208
+ debug(outputContent `Checking if ${token.path(path)} is a directory...`);
209
+ return (await fsLstat(path)).isDirectory();
210
+ }
211
+ /**
212
+ * Get the size of a file.
213
+ *
214
+ * @param path - Path to the file.
215
+ * @returns The size of the file in bytes.
216
+ */
217
+ export async function fileSize(path) {
218
+ debug(outputContent `Getting the size of file file at ${token.path(path)}...`);
219
+ return (await fsStat(path)).size;
220
+ }
221
+ /**
222
+ * Synchronously get the size of a file.
223
+ *
224
+ * @param path - Path to the file.
225
+ * @returns The size of the file in bytes.
226
+ */
227
+ export function fileSizeSync(path) {
228
+ debug(outputContent `Sync-getting the size of file file at ${token.path(path)}...`);
229
+ return fsStatSync(path).size;
230
+ }
231
+ /**
232
+ * Create a read stream for a file.
233
+ *
234
+ * @param path - Path to the file.
235
+ * @returns A read stream for the file.
236
+ */
237
+ export function createFileReadStream(path) {
238
+ return fsCreateReadStream(path);
239
+ }
240
+ /**
241
+ * Returns the Date object for the last modification of a file.
242
+ *
243
+ * @param path - Path to the directory or file.
244
+ * @returns A unix timestamp.
245
+ */
246
+ export async function fileLastUpdated(path) {
247
+ debug(outputContent `Getting last updated timestamp for file at ${token.path(path)}...`);
248
+ return (await fsStat(path)).ctime;
249
+ }
250
+ /**
251
+ * Returns the unix timestamp of the last modification of a file.
252
+ *
253
+ * @param path - Path to the directory or file.
254
+ * @returns A unix timestamp.
255
+ */
256
+ export async function fileLastUpdatedTimestamp(path) {
257
+ try {
258
+ const lastUpdatedDateTime = await fileLastUpdated(path);
259
+ return lastUpdatedDateTime.getTime();
260
+ // eslint-disable-next-line no-catch-all/no-catch-all
261
+ }
262
+ catch {
263
+ return undefined;
264
+ }
265
+ }
266
+ /**
267
+ * Moves a file.
268
+ *
269
+ * @param src - File to be moved.
270
+ * @param dest - Path to be moved to.
271
+ * @param options - Moving options.
272
+ */
273
+ export async function moveFile(src, dest, options = {}) {
274
+ await fsMove(src, dest, options);
275
+ }
276
+ /**
277
+ * Changes the permissions of a directory or file.
278
+ *
279
+ * @param path - Path to the file or directory whose permissions will be modified.
280
+ * @param mode - Permissions to set to the file or directory.
281
+ */
282
+ export async function chmod(path, mode) {
283
+ await fsChmod(path, mode);
284
+ }
285
+ /**
286
+ * Checks if a file has executable permissions.
287
+ *
288
+ * @param path - Path to the file whose permissions will be checked.
289
+ */
290
+ export async function fileHasExecutablePermissions(path) {
291
+ try {
292
+ await fsAccess(path, fsConstants.X_OK);
293
+ return true;
294
+ // eslint-disable-next-line no-catch-all/no-catch-all
295
+ }
296
+ catch {
297
+ return false;
298
+ }
299
+ }
300
+ /**
301
+ * Returns true if a file or directory exists.
302
+ *
303
+ * @param path - Path to the directory or file.
304
+ * @returns True if it exists.
305
+ */
306
+ export async function fileExists(path) {
307
+ try {
308
+ await fsAccess(path);
309
+ return true;
310
+ // eslint-disable-next-line no-catch-all/no-catch-all
311
+ }
312
+ catch {
313
+ return false;
314
+ }
315
+ }
316
+ /**
317
+ * Format a string using prettier. Return the formatted content.
318
+ *
319
+ * @param content - Content to be formatted.
320
+ * @param options - Options to format the content with.
321
+ * @returns The formatted content.
322
+ */
323
+ export async function fileContentPrettyFormat(content, options) {
324
+ const { default: prettier } = await import('prettier');
325
+ const ext = extname(options.path);
326
+ const prettierConfig = {
327
+ ...DEFAULT_PRETTIER_CONFIG,
328
+ parser: 'babel',
329
+ };
330
+ switch (ext) {
331
+ case '.html':
332
+ case '.css':
333
+ prettierConfig.parser = ext.slice(1);
334
+ break;
335
+ }
336
+ const formattedContent = await prettier.format(content, prettierConfig);
337
+ return formattedContent;
338
+ }
4
339
  /**
5
340
  * It generates a random directory directory name for a sub-directory.
6
341
  * It ensures that the returned directory name doesn't exist.
7
342
  *
343
+ * @param options - Options to generate the random directory name.
8
344
  * @returns It returns the name of the directory.
9
345
  */
10
346
  export async function generateRandomNameForSubdirectory(options) {