@shopify/cli-kit 3.69.0 → 3.69.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/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 +12 -4
- package/dist/public/node/api/admin.js.map +1 -1
- package/dist/public/node/error-handler.js +2 -2
- package/dist/public/node/error-handler.js.map +1 -1
- package/dist/public/node/error.d.ts +3 -3
- package/dist/public/node/error.js +29 -3
- package/dist/public/node/error.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const CLI_KIT_VERSION = "3.69.
|
|
1
|
+
export declare const CLI_KIT_VERSION = "3.69.1";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const CLI_KIT_VERSION = '3.69.
|
|
1
|
+
export const CLI_KIT_VERSION = '3.69.1';
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/public/common/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAA","sourcesContent":["export const CLI_KIT_VERSION = '3.69.
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/public/common/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAA","sourcesContent":["export const CLI_KIT_VERSION = '3.69.1'\n"]}
|
|
@@ -4,6 +4,7 @@ import { BugError, AbortError } from '../error.js';
|
|
|
4
4
|
import { restRequestBody, restRequestHeaders, restRequestUrl } from '../../../private/node/api/rest.js';
|
|
5
5
|
import { fetch } from '../http.js';
|
|
6
6
|
import { PublicApiVersions } from '../../../cli/api/graphql/admin/generated/public_api_versions.js';
|
|
7
|
+
import { normalizeStoreFqdn } from '../context/fqdn.js';
|
|
7
8
|
import { ClientError } from 'graphql-request';
|
|
8
9
|
/**
|
|
9
10
|
* Executes a GraphQL query against the Admin API.
|
|
@@ -16,7 +17,8 @@ import { ClientError } from 'graphql-request';
|
|
|
16
17
|
export async function adminRequest(query, session, variables) {
|
|
17
18
|
const api = 'Admin';
|
|
18
19
|
const version = await fetchLatestSupportedApiVersion(session);
|
|
19
|
-
const
|
|
20
|
+
const store = await normalizeStoreFqdn(session.storeFqdn);
|
|
21
|
+
const url = adminUrl(store, version);
|
|
20
22
|
return graphqlRequest({ query, api, url, token: session.token, variables });
|
|
21
23
|
}
|
|
22
24
|
/**
|
|
@@ -34,8 +36,9 @@ export async function adminRequestDoc(query, session, variables, version, respon
|
|
|
34
36
|
if (!version) {
|
|
35
37
|
apiVersion = await fetchLatestSupportedApiVersion(session);
|
|
36
38
|
}
|
|
39
|
+
const store = await normalizeStoreFqdn(session.storeFqdn);
|
|
37
40
|
const opts = {
|
|
38
|
-
url: adminUrl(
|
|
41
|
+
url: adminUrl(store, apiVersion),
|
|
39
42
|
api: 'Admin',
|
|
40
43
|
token: session.token,
|
|
41
44
|
};
|
|
@@ -82,7 +85,12 @@ async function fetchApiVersions(session) {
|
|
|
82
85
|
const storeName = session.storeFqdn.replace('.myshopify.com', '');
|
|
83
86
|
throw new AbortError(outputContent `Looks like you don't have access this dev store: (${outputToken.link(storeName, `https://${session.storeFqdn}`)})`, outputContent `If you're not the owner, create a dev store staff account for yourself`);
|
|
84
87
|
}
|
|
85
|
-
|
|
88
|
+
else if (error instanceof ClientError) {
|
|
89
|
+
throw new BugError(`Unknown client error connecting to your store ${session.storeFqdn}: ${error.message} ${error.response.status} ${error.response.data}`);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
throw new BugError(`Unknown error connecting to your store ${session.storeFqdn}: ${error instanceof Error ? error.message : String(error)}`);
|
|
93
|
+
}
|
|
86
94
|
}
|
|
87
95
|
}
|
|
88
96
|
/**
|
|
@@ -93,7 +101,7 @@ async function fetchApiVersions(session) {
|
|
|
93
101
|
* @returns - Admin API URL.
|
|
94
102
|
*/
|
|
95
103
|
export function adminUrl(store, version) {
|
|
96
|
-
const realVersion = version
|
|
104
|
+
const realVersion = version ?? 'unstable';
|
|
97
105
|
return `https://${store}/admin/api/${realVersion}/graphql.json`;
|
|
98
106
|
}
|
|
99
107
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin.js","sourceRoot":"","sources":["../../../../src/public/node/api/admin.ts"],"names":[],"mappings":"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","sourcesContent":["import {graphqlRequest, graphqlRequestDoc, GraphQLResponseOptions, GraphQLVariables} from './graphql.js'\nimport {AdminSession} from '../session.js'\nimport {outputContent, outputToken} from '../../../public/node/output.js'\nimport {BugError, AbortError} from '../error.js'\nimport {restRequestBody, restRequestHeaders, restRequestUrl} from '../../../private/node/api/rest.js'\nimport {fetch} from '../http.js'\nimport {PublicApiVersions} from '../../../cli/api/graphql/admin/generated/public_api_versions.js'\nimport {ClientError, Variables} from 'graphql-request'\nimport {TypedDocumentNode} from '@graphql-typed-document-node/core'\n\n/**\n * Executes a GraphQL query against the Admin API.\n *\n * @param query - GraphQL query to execute.\n * @param session - Shopify admin session including token and Store FQDN.\n * @param variables - GraphQL variables to pass to the query.\n * @returns The response of the query of generic type <T>.\n */\nexport async function adminRequest<T>(query: string, session: AdminSession, variables?: GraphQLVariables): Promise<T> {\n const api = 'Admin'\n const version = await fetchLatestSupportedApiVersion(session)\n const url = adminUrl(session.storeFqdn, version)\n return graphqlRequest({query, api, url, token: session.token, variables})\n}\n\n/**\n * Executes a GraphQL query against the Admin API. Uses typed documents.\n *\n * @param query - GraphQL query to execute.\n * @param session - Shopify admin session including token and Store FQDN.\n * @param variables - GraphQL variables to pass to the query.\n * @param version - API version.\n * @param responseOptions - Control how API responses will be handled.\n * @returns The response of the query of generic type <TResult>.\n */\nexport async function adminRequestDoc<TResult, TVariables extends Variables>(\n query: TypedDocumentNode<TResult, TVariables>,\n session: AdminSession,\n variables?: TVariables,\n version?: string,\n responseOptions?: GraphQLResponseOptions<TResult>,\n): Promise<TResult> {\n let apiVersion = version\n if (!version) {\n apiVersion = await fetchLatestSupportedApiVersion(session)\n }\n const opts = {\n url: adminUrl(session.storeFqdn, apiVersion),\n api: 'Admin',\n token: session.token,\n }\n const result = graphqlRequestDoc<TResult, TVariables>({...opts, query, variables, responseOptions})\n return result\n}\n\n/**\n * GraphQL query to retrieve the latest supported API version.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @returns - The latest supported API version.\n */\nasync function fetchLatestSupportedApiVersion(session: AdminSession): Promise<string> {\n const apiVersions = await supportedApiVersions(session)\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return apiVersions.reverse()[0]!\n}\n\n/**\n * GraphQL query to retrieve all supported API versions.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @returns - An array of supported API versions.\n */\nexport async function supportedApiVersions(session: AdminSession): Promise<string[]> {\n const apiVersions = await fetchApiVersions(session)\n return apiVersions\n .filter((item) => item.supported)\n .map((item) => item.handle)\n .sort()\n}\n\n/**\n * GraphQL query to retrieve all API versions.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @returns - An array of supported and unsupported API versions.\n */\nasync function fetchApiVersions(session: AdminSession): Promise<ApiVersion[]> {\n try {\n const response = await adminRequestDoc(PublicApiVersions, session, {}, 'unstable', {handleErrors: false})\n return response.publicApiVersions\n } catch (error) {\n if (error instanceof ClientError && error.response.status === 403) {\n const storeName = session.storeFqdn.replace('.myshopify.com', '')\n throw new AbortError(\n outputContent`Looks like you don't have access this dev store: (${outputToken.link(\n storeName,\n `https://${session.storeFqdn}`,\n )})`,\n outputContent`If you're not the owner, create a dev store staff account for yourself`,\n )\n }\n throw new BugError(`Unknown error connecting to your store`)\n }\n}\n\n/**\n * Returns the Admin API URL for the given store and version.\n *\n * @param store - Store FQDN.\n * @param version - API version.\n * @returns - Admin API URL.\n */\nexport function adminUrl(store: string, version: string | undefined): string {\n const realVersion = version || 'unstable'\n return `https://${store}/admin/api/${realVersion}/graphql.json`\n}\n\ninterface ApiVersion {\n handle: string\n supported: boolean\n}\n\n/**\n * Executes a REST request against the Admin API.\n *\n * @param method - Request's HTTP method.\n * @param path - Path of the REST resource.\n * @param session - Shopify Admin session including token and Store FQDN.\n * @param requestBody - Request body of including REST resource specific parameters.\n * @param searchParams - Search params, appended to the URL.\n * @param apiVersion - Admin API version.\n * @returns - The {@link RestResponse}.\n */\nexport async function restRequest<T>(\n method: string,\n path: string,\n session: AdminSession,\n requestBody?: T,\n searchParams: {[name: string]: string} = {},\n apiVersion = 'unstable',\n): Promise<RestResponse> {\n const url = restRequestUrl(session, apiVersion, path, searchParams)\n const body = restRequestBody<T>(requestBody)\n\n const headers = restRequestHeaders(session)\n const response = await fetch(url, {\n headers,\n method,\n body,\n })\n\n const json = await response.json().catch(() => ({}))\n\n return {\n json,\n status: response.status,\n headers: response.headers.raw(),\n }\n}\n\n/**\n * Respose of a REST request.\n */\nexport interface RestResponse {\n /**\n * REST JSON respose.\n */\n // Using `any` to avoid introducing extra DTO layers.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n json: any\n\n /**\n * HTTP response status.\n */\n status: number\n\n /**\n * HTTP response headers.\n */\n headers: {[key: string]: string[]}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"admin.js","sourceRoot":"","sources":["../../../../src/public/node/api/admin.ts"],"names":[],"mappings":"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","sourcesContent":["import {graphqlRequest, graphqlRequestDoc, GraphQLResponseOptions, GraphQLVariables} from './graphql.js'\nimport {AdminSession} from '../session.js'\nimport {outputContent, outputToken} from '../../../public/node/output.js'\nimport {BugError, AbortError} from '../error.js'\nimport {restRequestBody, restRequestHeaders, restRequestUrl} from '../../../private/node/api/rest.js'\nimport {fetch} from '../http.js'\nimport {PublicApiVersions} from '../../../cli/api/graphql/admin/generated/public_api_versions.js'\nimport {normalizeStoreFqdn} from '../context/fqdn.js'\nimport {ClientError, Variables} from 'graphql-request'\nimport {TypedDocumentNode} from '@graphql-typed-document-node/core'\n\n/**\n * Executes a GraphQL query against the Admin API.\n *\n * @param query - GraphQL query to execute.\n * @param session - Shopify admin session including token and Store FQDN.\n * @param variables - GraphQL variables to pass to the query.\n * @returns The response of the query of generic type <T>.\n */\nexport async function adminRequest<T>(query: string, session: AdminSession, variables?: GraphQLVariables): Promise<T> {\n const api = 'Admin'\n const version = await fetchLatestSupportedApiVersion(session)\n const store = await normalizeStoreFqdn(session.storeFqdn)\n const url = adminUrl(store, version)\n return graphqlRequest({query, api, url, token: session.token, variables})\n}\n\n/**\n * Executes a GraphQL query against the Admin API. Uses typed documents.\n *\n * @param query - GraphQL query to execute.\n * @param session - Shopify admin session including token and Store FQDN.\n * @param variables - GraphQL variables to pass to the query.\n * @param version - API version.\n * @param responseOptions - Control how API responses will be handled.\n * @returns The response of the query of generic type <TResult>.\n */\nexport async function adminRequestDoc<TResult, TVariables extends Variables>(\n query: TypedDocumentNode<TResult, TVariables>,\n session: AdminSession,\n variables?: TVariables,\n version?: string,\n responseOptions?: GraphQLResponseOptions<TResult>,\n): Promise<TResult> {\n let apiVersion = version\n if (!version) {\n apiVersion = await fetchLatestSupportedApiVersion(session)\n }\n const store = await normalizeStoreFqdn(session.storeFqdn)\n const opts = {\n url: adminUrl(store, apiVersion),\n api: 'Admin',\n token: session.token,\n }\n const result = graphqlRequestDoc<TResult, TVariables>({...opts, query, variables, responseOptions})\n return result\n}\n\n/**\n * GraphQL query to retrieve the latest supported API version.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @returns - The latest supported API version.\n */\nasync function fetchLatestSupportedApiVersion(session: AdminSession): Promise<string> {\n const apiVersions = await supportedApiVersions(session)\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return apiVersions.reverse()[0]!\n}\n\n/**\n * GraphQL query to retrieve all supported API versions.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @returns - An array of supported API versions.\n */\nexport async function supportedApiVersions(session: AdminSession): Promise<string[]> {\n const apiVersions = await fetchApiVersions(session)\n return apiVersions\n .filter((item) => item.supported)\n .map((item) => item.handle)\n .sort()\n}\n\n/**\n * GraphQL query to retrieve all API versions.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @returns - An array of supported and unsupported API versions.\n */\nasync function fetchApiVersions(session: AdminSession): Promise<ApiVersion[]> {\n try {\n const response = await adminRequestDoc(PublicApiVersions, session, {}, 'unstable', {handleErrors: false})\n return response.publicApiVersions\n } catch (error) {\n if (error instanceof ClientError && error.response.status === 403) {\n const storeName = session.storeFqdn.replace('.myshopify.com', '')\n throw new AbortError(\n outputContent`Looks like you don't have access this dev store: (${outputToken.link(\n storeName,\n `https://${session.storeFqdn}`,\n )})`,\n outputContent`If you're not the owner, create a dev store staff account for yourself`,\n )\n } else if (error instanceof ClientError) {\n throw new BugError(\n `Unknown client error connecting to your store ${session.storeFqdn}: ${error.message} ${error.response.status} ${error.response.data}`,\n )\n } else {\n throw new BugError(\n `Unknown error connecting to your store ${session.storeFqdn}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n )\n }\n }\n}\n\n/**\n * Returns the Admin API URL for the given store and version.\n *\n * @param store - Store FQDN.\n * @param version - API version.\n * @returns - Admin API URL.\n */\nexport function adminUrl(store: string, version: string | undefined): string {\n const realVersion = version ?? 'unstable'\n return `https://${store}/admin/api/${realVersion}/graphql.json`\n}\n\ninterface ApiVersion {\n handle: string\n supported: boolean\n}\n\n/**\n * Executes a REST request against the Admin API.\n *\n * @param method - Request's HTTP method.\n * @param path - Path of the REST resource.\n * @param session - Shopify Admin session including token and Store FQDN.\n * @param requestBody - Request body of including REST resource specific parameters.\n * @param searchParams - Search params, appended to the URL.\n * @param apiVersion - Admin API version.\n * @returns - The {@link RestResponse}.\n */\nexport async function restRequest<T>(\n method: string,\n path: string,\n session: AdminSession,\n requestBody?: T,\n searchParams: {[name: string]: string} = {},\n apiVersion = 'unstable',\n): Promise<RestResponse> {\n const url = restRequestUrl(session, apiVersion, path, searchParams)\n const body = restRequestBody<T>(requestBody)\n\n const headers = restRequestHeaders(session)\n const response = await fetch(url, {\n headers,\n method,\n body,\n })\n\n const json = await response.json().catch(() => ({}))\n\n return {\n json,\n status: response.status,\n headers: response.headers.raw(),\n }\n}\n\n/**\n * Respose of a REST request.\n */\nexport interface RestResponse {\n /**\n * REST JSON respose.\n */\n // Using `any` to avoid introducing extra DTO layers.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n json: any\n\n /**\n * HTTP response status.\n */\n status: number\n\n /**\n * HTTP response headers.\n */\n headers: {[key: string]: string[]}\n}\n"]}
|
|
@@ -2,7 +2,7 @@ import { reportAnalyticsEvent } from './analytics.js';
|
|
|
2
2
|
import * as path from './path.js';
|
|
3
3
|
import { fanoutHooks } from './plugins.js';
|
|
4
4
|
import * as metadata from './metadata.js';
|
|
5
|
-
import { AbortSilentError, CancelExecution, errorMapper,
|
|
5
|
+
import { AbortSilentError, CancelExecution, errorMapper, shouldReportErrorAsUnexpected, handler, cleanSingleStackTracePath, } from './error.js';
|
|
6
6
|
import { getEnvironmentData } from '../../private/node/analytics.js';
|
|
7
7
|
import { outputDebug, outputInfo } from '../../public/node/output.js';
|
|
8
8
|
import { bugsnagApiKey, reportingRateLimit } from '../../private/node/constants.js';
|
|
@@ -36,7 +36,7 @@ export async function errorHandler(error, config) {
|
|
|
36
36
|
const reportError = async (error, config) => {
|
|
37
37
|
// categorise the error first
|
|
38
38
|
let exitMode = 'expected_error';
|
|
39
|
-
if (
|
|
39
|
+
if (shouldReportErrorAsUnexpected(error))
|
|
40
40
|
exitMode = 'unexpected_error';
|
|
41
41
|
if (config !== undefined) {
|
|
42
42
|
// Log an analytics event when there's an error
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../../src/public/node/error-handler.ts"],"names":[],"mappings":"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","sourcesContent":["import {CommandExitMode, reportAnalyticsEvent} from './analytics.js'\nimport * as path from './path.js'\nimport {fanoutHooks} from './plugins.js'\nimport * as metadata from './metadata.js'\nimport {\n AbortSilentError,\n CancelExecution,\n errorMapper,\n shouldReportError,\n handler,\n cleanSingleStackTracePath,\n} from './error.js'\nimport {getEnvironmentData} from '../../private/node/analytics.js'\nimport {outputDebug, outputInfo} from '../../public/node/output.js'\nimport {bugsnagApiKey, reportingRateLimit} from '../../private/node/constants.js'\nimport {printEventsJson} from '../../private/node/demo-recorder.js'\nimport {CLI_KIT_VERSION} from '../common/version.js'\nimport {runWithRateLimit} from '../../private/node/conf-store.js'\nimport {settings, Interfaces} from '@oclif/core'\nimport StackTracey from 'stacktracey'\nimport Bugsnag, {Event} from '@bugsnag/js'\nimport {realpath} from 'fs/promises'\n\nexport async function errorHandler(\n error: Error & {exitCode?: number | undefined},\n config?: Interfaces.Config,\n): Promise<void> {\n if (error instanceof CancelExecution) {\n if (error.message && error.message !== '') {\n outputInfo(`✨ ${error.message}`)\n }\n } else if (error instanceof AbortSilentError) {\n printEventsJson()\n } else {\n return errorMapper(error)\n .then((error) => {\n return handler(error)\n })\n .then((mappedError) => {\n printEventsJson()\n return reportError(mappedError, config)\n })\n }\n}\n\nconst reportError = async (error: unknown, config?: Interfaces.Config): Promise<void> => {\n // categorise the error first\n let exitMode: CommandExitMode = 'expected_error'\n if (shouldReportError(error)) exitMode = 'unexpected_error'\n\n if (config !== undefined) {\n // Log an analytics event when there's an error\n await reportAnalyticsEvent({config, errorMessage: error instanceof Error ? error.message : undefined, exitMode})\n }\n await sendErrorToBugsnag(error, exitMode)\n}\n\n/**\n * Sends an error to Bugsnag. This is configured automatically for uncaught errors from CLI commands, but can also be used to manually record an error.\n *\n * @returns the reported error (this may have been tweaked for better reporting), and a bool to indicate if the error was actually submitted or not\n */\nexport async function sendErrorToBugsnag(\n error: unknown,\n exitMode: Omit<CommandExitMode, 'ok'>,\n): Promise<{reported: false; error: unknown; unhandled: unknown} | {error: Error; reported: true; unhandled: boolean}> {\n if (settings.debug) {\n outputDebug(`Skipping Bugsnag report`)\n return {reported: false, error, unhandled: undefined}\n }\n\n // If the error was unexpected, we flag it as \"unhandled\" in Bugsnag. This is a helpful distinction.\n const unhandled = exitMode === 'unexpected_error'\n\n let reportableError: Error\n let stacktrace: string | undefined\n let report = false\n\n if (error instanceof Error) {\n report = true\n reportableError = new Error(error.message)\n stacktrace = error.stack\n\n /**\n * Some errors that reach this point have an empty string. For example:\n * https://app.bugsnag.com/shopify/cli/errors/62cd5d31fd5040000814086c?filters[event.since]=30d&filters[error.status]=new&filters[release.seen_in]=3.1.0\n *\n * Because at this point we have neither the error message nor a stack trace reporting them\n * to Bugsnag is pointless and adds noise.\n */\n } else if (typeof error === 'string' && error.trim().length !== 0) {\n report = true\n reportableError = new Error(error)\n stacktrace = reportableError.stack\n } else {\n report = false\n reportableError = new Error('Unknown error')\n }\n\n const formattedStacktrace = new StackTracey(stacktrace ?? '')\n .clean()\n .items.map((item) => {\n const filePath = cleanSingleStackTracePath(item.file)\n return ` at ${item.callee} (${filePath}:${item.line}:${item.column})`\n })\n .join('\\n')\n reportableError.stack = `Error: ${reportableError.message}\\n${formattedStacktrace}`\n\n let withinRateLimit = false\n await runWithRateLimit({\n key: 'send-error-to-bugsnag',\n ...reportingRateLimit,\n task: async () => {\n withinRateLimit = true\n },\n })\n if (!withinRateLimit) {\n outputDebug(`Skipping Bugsnag report due to rate limiting`)\n report = false\n }\n\n if (report) {\n initializeBugsnag()\n await new Promise((resolve, reject) => {\n outputDebug(`Reporting ${unhandled ? 'unhandled' : 'handled'} error to Bugsnag: ${reportableError.message}`)\n const eventHandler = (event: Event) => {\n event.severity = 'error'\n event.unhandled = unhandled\n }\n const errorHandler = (error: unknown) => {\n if (error) {\n reject(error)\n } else {\n resolve(reportableError)\n }\n }\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n Bugsnag.notify(reportableError, eventHandler, errorHandler)\n })\n }\n return {error: reportableError, reported: report, unhandled}\n}\n\n/**\n * If the given file path is within a node_modules folder, remove prefix up\n * to and including the node_modules folder.\n *\n * This gives us very consistent paths for errors generated by the CLI.\n */\nexport function cleanStackFrameFilePath({\n currentFilePath,\n projectRoot,\n pluginLocations,\n}: {\n currentFilePath: string\n projectRoot: string\n pluginLocations: {name: string; pluginPath: string}[]\n}): string {\n const fullLocation = path.isAbsolutePath(currentFilePath)\n ? currentFilePath\n : path.joinPath(projectRoot, currentFilePath)\n\n const matchingPluginPath = pluginLocations.filter(({pluginPath}) => fullLocation.startsWith(pluginPath))[0]\n\n if (matchingPluginPath !== undefined) {\n // the plugin name (e.g. @shopify/cli-kit), plus the relative path of the error line from within the plugin's code (e.g. dist/something.js )\n return path.joinPath(matchingPluginPath.name, path.relativePath(matchingPluginPath.pluginPath, fullLocation))\n }\n\n // strip prefix up to node_modules folder, so we can normalize error reporting\n return currentFilePath.replace(/.*node_modules\\//, '')\n}\n\n/**\n * Register a Bugsnag error listener to clean up stack traces for errors within plugin code.\n *\n */\nexport async function registerCleanBugsnagErrorsFromWithinPlugins(config: Interfaces.Config): Promise<void> {\n // Bugsnag have their own plug-ins that use this private field\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const bugsnagConfigProjectRoot: string = (Bugsnag as any)?._client?._config?.projectRoot ?? path.cwd()\n const projectRoot = path.normalizePath(bugsnagConfigProjectRoot)\n const pluginLocations = await Promise.all(\n [...config.plugins].map(async ([_, plugin]) => {\n const followSymlinks = await realpath(plugin.root)\n return {name: plugin.name, pluginPath: path.normalizePath(followSymlinks)}\n }),\n )\n initializeBugsnag()\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n Bugsnag.addOnError(async (event) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n event.errors.forEach((error: any) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n error.stacktrace.forEach((stackFrame: any) => {\n stackFrame.file = cleanStackFrameFilePath({currentFilePath: stackFrame.file, projectRoot, pluginLocations})\n })\n })\n try {\n await addBugsnagMetadata(event, config)\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (metadataError) {\n outputDebug(`There was an error adding metadata to the Bugsnag report; Ignoring and carrying on ${metadataError}`)\n }\n })\n}\n\n// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any\nexport async function addBugsnagMetadata(event: any, config: Interfaces.Config): Promise<void> {\n const publicData = metadata.getAllPublicMetadata()\n const {commandStartOptions} = metadata.getAllSensitiveMetadata()\n const {startCommand} = commandStartOptions ?? {}\n\n const {'@shopify/app': appPublic, ...otherPluginsPublic} = await fanoutHooks(config, 'public_command_metadata', {})\n\n const environment = await getEnvironmentData(config)\n\n const allMetadata = {\n command: startCommand,\n ...appPublic,\n ...publicData,\n ...environment,\n pluginData: otherPluginsPublic,\n }\n\n const appData = {} as {[key: string]: unknown}\n const commandData = {} as {[key: string]: unknown}\n const environmentData = {} as {[key: string]: unknown}\n const miscData = {} as {[key: string]: unknown}\n const appKeys = ['api_key', 'partner_id', 'project_type']\n const commandKeys = ['command']\n const environmentKeys = ['cli_version', 'node_version', '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 // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n if (Bugsnag.isStarted()) {\n return\n }\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n Bugsnag.start({\n appType: 'node',\n apiKey: bugsnagApiKey,\n logger: null,\n appVersion: CLI_KIT_VERSION,\n autoTrackSessions: false,\n autoDetectErrors: false,\n enabledReleaseStages: ['production'],\n })\n}\n"]}
|
|
1
|
+
{"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../../src/public/node/error-handler.ts"],"names":[],"mappings":"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","sourcesContent":["import {CommandExitMode, reportAnalyticsEvent} from './analytics.js'\nimport * as path from './path.js'\nimport {fanoutHooks} from './plugins.js'\nimport * as metadata from './metadata.js'\nimport {\n AbortSilentError,\n CancelExecution,\n errorMapper,\n shouldReportErrorAsUnexpected,\n handler,\n cleanSingleStackTracePath,\n} from './error.js'\nimport {getEnvironmentData} from '../../private/node/analytics.js'\nimport {outputDebug, outputInfo} from '../../public/node/output.js'\nimport {bugsnagApiKey, reportingRateLimit} from '../../private/node/constants.js'\nimport {printEventsJson} from '../../private/node/demo-recorder.js'\nimport {CLI_KIT_VERSION} from '../common/version.js'\nimport {runWithRateLimit} from '../../private/node/conf-store.js'\nimport {settings, Interfaces} from '@oclif/core'\nimport StackTracey from 'stacktracey'\nimport Bugsnag, {Event} from '@bugsnag/js'\nimport {realpath} from 'fs/promises'\n\nexport async function errorHandler(\n error: Error & {exitCode?: number | undefined},\n config?: Interfaces.Config,\n): Promise<void> {\n if (error instanceof CancelExecution) {\n if (error.message && error.message !== '') {\n outputInfo(`✨ ${error.message}`)\n }\n } else if (error instanceof AbortSilentError) {\n printEventsJson()\n } else {\n return errorMapper(error)\n .then((error) => {\n return handler(error)\n })\n .then((mappedError) => {\n printEventsJson()\n return reportError(mappedError, config)\n })\n }\n}\n\nconst reportError = async (error: unknown, config?: Interfaces.Config): Promise<void> => {\n // categorise the error first\n let exitMode: CommandExitMode = 'expected_error'\n if (shouldReportErrorAsUnexpected(error)) exitMode = 'unexpected_error'\n\n if (config !== undefined) {\n // Log an analytics event when there's an error\n await reportAnalyticsEvent({config, errorMessage: error instanceof Error ? error.message : undefined, exitMode})\n }\n await sendErrorToBugsnag(error, exitMode)\n}\n\n/**\n * Sends an error to Bugsnag. This is configured automatically for uncaught errors from CLI commands, but can also be used to manually record an error.\n *\n * @returns the reported error (this may have been tweaked for better reporting), and a bool to indicate if the error was actually submitted or not\n */\nexport async function sendErrorToBugsnag(\n error: unknown,\n exitMode: Omit<CommandExitMode, 'ok'>,\n): Promise<{reported: false; error: unknown; unhandled: unknown} | {error: Error; reported: true; unhandled: boolean}> {\n if (settings.debug) {\n outputDebug(`Skipping Bugsnag report`)\n return {reported: false, error, unhandled: undefined}\n }\n\n // If the error was unexpected, we flag it as \"unhandled\" in Bugsnag. This is a helpful distinction.\n const unhandled = exitMode === 'unexpected_error'\n\n let reportableError: Error\n let stacktrace: string | undefined\n let report = false\n\n if (error instanceof Error) {\n report = true\n reportableError = new Error(error.message)\n stacktrace = error.stack\n\n /**\n * Some errors that reach this point have an empty string. For example:\n * https://app.bugsnag.com/shopify/cli/errors/62cd5d31fd5040000814086c?filters[event.since]=30d&filters[error.status]=new&filters[release.seen_in]=3.1.0\n *\n * Because at this point we have neither the error message nor a stack trace reporting them\n * to Bugsnag is pointless and adds noise.\n */\n } else if (typeof error === 'string' && error.trim().length !== 0) {\n report = true\n reportableError = new Error(error)\n stacktrace = reportableError.stack\n } else {\n report = false\n reportableError = new Error('Unknown error')\n }\n\n const formattedStacktrace = new StackTracey(stacktrace ?? '')\n .clean()\n .items.map((item) => {\n const filePath = cleanSingleStackTracePath(item.file)\n return ` at ${item.callee} (${filePath}:${item.line}:${item.column})`\n })\n .join('\\n')\n reportableError.stack = `Error: ${reportableError.message}\\n${formattedStacktrace}`\n\n let withinRateLimit = false\n await runWithRateLimit({\n key: 'send-error-to-bugsnag',\n ...reportingRateLimit,\n task: async () => {\n withinRateLimit = true\n },\n })\n if (!withinRateLimit) {\n outputDebug(`Skipping Bugsnag report due to rate limiting`)\n report = false\n }\n\n if (report) {\n initializeBugsnag()\n await new Promise((resolve, reject) => {\n outputDebug(`Reporting ${unhandled ? 'unhandled' : 'handled'} error to Bugsnag: ${reportableError.message}`)\n const eventHandler = (event: Event) => {\n event.severity = 'error'\n event.unhandled = unhandled\n }\n const errorHandler = (error: unknown) => {\n if (error) {\n reject(error)\n } else {\n resolve(reportableError)\n }\n }\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n Bugsnag.notify(reportableError, eventHandler, errorHandler)\n })\n }\n return {error: reportableError, reported: report, unhandled}\n}\n\n/**\n * If the given file path is within a node_modules folder, remove prefix up\n * to and including the node_modules folder.\n *\n * This gives us very consistent paths for errors generated by the CLI.\n */\nexport function cleanStackFrameFilePath({\n currentFilePath,\n projectRoot,\n pluginLocations,\n}: {\n currentFilePath: string\n projectRoot: string\n pluginLocations: {name: string; pluginPath: string}[]\n}): string {\n const fullLocation = path.isAbsolutePath(currentFilePath)\n ? currentFilePath\n : path.joinPath(projectRoot, currentFilePath)\n\n const matchingPluginPath = pluginLocations.filter(({pluginPath}) => fullLocation.startsWith(pluginPath))[0]\n\n if (matchingPluginPath !== undefined) {\n // the plugin name (e.g. @shopify/cli-kit), plus the relative path of the error line from within the plugin's code (e.g. dist/something.js )\n return path.joinPath(matchingPluginPath.name, path.relativePath(matchingPluginPath.pluginPath, fullLocation))\n }\n\n // strip prefix up to node_modules folder, so we can normalize error reporting\n return currentFilePath.replace(/.*node_modules\\//, '')\n}\n\n/**\n * Register a Bugsnag error listener to clean up stack traces for errors within plugin code.\n *\n */\nexport async function registerCleanBugsnagErrorsFromWithinPlugins(config: Interfaces.Config): Promise<void> {\n // Bugsnag have their own plug-ins that use this private field\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const bugsnagConfigProjectRoot: string = (Bugsnag as any)?._client?._config?.projectRoot ?? path.cwd()\n const projectRoot = path.normalizePath(bugsnagConfigProjectRoot)\n const pluginLocations = await Promise.all(\n [...config.plugins].map(async ([_, plugin]) => {\n const followSymlinks = await realpath(plugin.root)\n return {name: plugin.name, pluginPath: path.normalizePath(followSymlinks)}\n }),\n )\n initializeBugsnag()\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n Bugsnag.addOnError(async (event) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n event.errors.forEach((error: any) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n error.stacktrace.forEach((stackFrame: any) => {\n stackFrame.file = cleanStackFrameFilePath({currentFilePath: stackFrame.file, projectRoot, pluginLocations})\n })\n })\n try {\n await addBugsnagMetadata(event, config)\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (metadataError) {\n outputDebug(`There was an error adding metadata to the Bugsnag report; Ignoring and carrying on ${metadataError}`)\n }\n })\n}\n\n// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any\nexport async function addBugsnagMetadata(event: any, config: Interfaces.Config): Promise<void> {\n const publicData = metadata.getAllPublicMetadata()\n const {commandStartOptions} = metadata.getAllSensitiveMetadata()\n const {startCommand} = commandStartOptions ?? {}\n\n const {'@shopify/app': appPublic, ...otherPluginsPublic} = await fanoutHooks(config, 'public_command_metadata', {})\n\n const environment = await getEnvironmentData(config)\n\n const allMetadata = {\n command: startCommand,\n ...appPublic,\n ...publicData,\n ...environment,\n pluginData: otherPluginsPublic,\n }\n\n const appData = {} as {[key: string]: unknown}\n const commandData = {} as {[key: string]: unknown}\n const environmentData = {} as {[key: string]: unknown}\n const miscData = {} as {[key: string]: unknown}\n const appKeys = ['api_key', 'partner_id', 'project_type']\n const commandKeys = ['command']\n const environmentKeys = ['cli_version', 'node_version', '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 // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n if (Bugsnag.isStarted()) {\n return\n }\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n Bugsnag.start({\n appType: 'node',\n apiKey: bugsnagApiKey,\n logger: null,\n appVersion: CLI_KIT_VERSION,\n autoTrackSessions: false,\n autoDetectErrors: false,\n enabledReleaseStages: ['production'],\n })\n}\n"]}
|
|
@@ -75,12 +75,12 @@ export declare function handler(error: unknown): Promise<unknown>;
|
|
|
75
75
|
*/
|
|
76
76
|
export declare function errorMapper(error: unknown): Promise<unknown>;
|
|
77
77
|
/**
|
|
78
|
-
* A function that checks if an error should be reported as
|
|
78
|
+
* A function that checks if an error should be reported as unexpected.
|
|
79
79
|
*
|
|
80
80
|
* @param error - Error to be checked.
|
|
81
|
-
* @returns A boolean indicating if the error should be reported.
|
|
81
|
+
* @returns A boolean indicating if the error should be reported as unexpected.
|
|
82
82
|
*/
|
|
83
|
-
export declare function
|
|
83
|
+
export declare function shouldReportErrorAsUnexpected(error: unknown): boolean;
|
|
84
84
|
/**
|
|
85
85
|
* Stack traces usually have file:// - we strip that and also remove the Windows drive designation.
|
|
86
86
|
*
|
|
@@ -146,13 +146,18 @@ function isFatal(error) {
|
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
148
|
/**
|
|
149
|
-
* A function that checks if an error should be reported as
|
|
149
|
+
* A function that checks if an error should be reported as unexpected.
|
|
150
150
|
*
|
|
151
151
|
* @param error - Error to be checked.
|
|
152
|
-
* @returns A boolean indicating if the error should be reported.
|
|
152
|
+
* @returns A boolean indicating if the error should be reported as unexpected.
|
|
153
153
|
*/
|
|
154
|
-
export function
|
|
154
|
+
export function shouldReportErrorAsUnexpected(error) {
|
|
155
155
|
if (!isFatal(error)) {
|
|
156
|
+
// this means its not one of the CLI wrapped errors
|
|
157
|
+
if (error instanceof Error) {
|
|
158
|
+
const message = error.message;
|
|
159
|
+
return !errorMessageImpliesEnvironmentIssue(message);
|
|
160
|
+
}
|
|
156
161
|
return true;
|
|
157
162
|
}
|
|
158
163
|
if (error.type === FatalErrorType.Bug) {
|
|
@@ -171,4 +176,25 @@ export function cleanSingleStackTracePath(filePath) {
|
|
|
171
176
|
.replace('file:/', '/')
|
|
172
177
|
.replace(/^\/?[A-Z]:/, '');
|
|
173
178
|
}
|
|
179
|
+
/**
|
|
180
|
+
* There are certain errors that we know are not due to a CLI bug, but are environmental/user error.
|
|
181
|
+
*
|
|
182
|
+
* @param message - The error message to check.
|
|
183
|
+
* @returns A boolean indicating if the error message implies an environment issue.
|
|
184
|
+
*/
|
|
185
|
+
function errorMessageImpliesEnvironmentIssue(message) {
|
|
186
|
+
const environmentIssueMessages = [
|
|
187
|
+
'EPERM: operation not permitted, scandir',
|
|
188
|
+
'EACCES: permission denied',
|
|
189
|
+
'EPERM: operation not permitted, symlink',
|
|
190
|
+
'This version of npm supports the following node versions',
|
|
191
|
+
'EBUSY: resource busy or locked, rmdir',
|
|
192
|
+
'getaddrinfo ENOTFOUND',
|
|
193
|
+
'Client network socket disconnected before secure TLS connection was established',
|
|
194
|
+
'spawn EPERM',
|
|
195
|
+
'socket hang up',
|
|
196
|
+
];
|
|
197
|
+
const anyMatches = environmentIssueMessages.some((issueMessage) => message.includes(issueMessage));
|
|
198
|
+
return anyMatches;
|
|
199
|
+
}
|
|
174
200
|
//# sourceMappingURL=error.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.js","sourceRoot":"","sources":["../../../src/public/node/error.ts"],"names":[],"mappings":"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","sourcesContent":["import {AlertCustomSection, renderFatalError} from './ui.js'\nimport {OutputMessage, stringifyMessage, TokenizedString} from '../../public/node/output.js'\nimport {normalizePath} from '../../public/node/path.js'\nimport {InlineToken, TokenItem, tokenItemToString} from '../../private/node/ui/components/TokenizedText.js'\nimport {Errors} from '@oclif/core'\n\nexport {ExtendableError} from 'ts-error'\n\nexport enum FatalErrorType {\n Abort,\n AbortSilent,\n Bug,\n}\n\nexport class CancelExecution extends Error {}\n\n/**\n * A fatal error represents an error shouldn't be rescued and that causes the execution to terminate.\n * There shouldn't be code that catches fatal errors.\n */\nexport abstract class FatalError extends Error {\n tryMessage: TokenItem | null\n type: FatalErrorType\n nextSteps?: TokenItem<InlineToken>[]\n formattedMessage?: TokenItem\n customSections?: AlertCustomSection[]\n skipOclifErrorHandling: boolean\n /**\n * Creates a new FatalError error.\n *\n * @param message - The error message.\n * @param type - The type of fatal error.\n * @param tryMessage - The message that recommends next steps to the user.\n * You can pass a string a {@link TokenizedString} or a {@link TokenItem}\n * if you need to style the message inside the error Banner component.\n * @param nextSteps - Message to show as \"next steps\" with suggestions to solve the issue.\n * @param customSections - Custom sections to show in the error banner. To be used if nextSteps is not enough.\n */\n constructor(\n message: TokenItem | OutputMessage,\n type: FatalErrorType,\n tryMessage: TokenItem | OutputMessage | null = null,\n nextSteps?: TokenItem<InlineToken>[],\n customSections?: AlertCustomSection[],\n ) {\n const messageIsOutputMessage = typeof message === 'string' || 'value' in message\n super(messageIsOutputMessage ? stringifyMessage(message) : tokenItemToString(message))\n\n if (tryMessage) {\n if (tryMessage instanceof TokenizedString) {\n this.tryMessage = stringifyMessage(tryMessage)\n } else {\n this.tryMessage = tryMessage\n }\n } else {\n this.tryMessage = null\n }\n\n this.type = type\n this.nextSteps = nextSteps\n this.customSections = customSections\n this.skipOclifErrorHandling = true\n\n if (!messageIsOutputMessage) {\n this.formattedMessage = message\n }\n }\n}\n\n/**\n * An abort error is a fatal error that shouldn't be reported as a bug.\n * Those usually represent unexpected scenarios that we can't handle and that usually require some action from the developer.\n */\nexport class AbortError extends FatalError {\n nextSteps?: TokenItem<InlineToken>[]\n customSections?: AlertCustomSection[]\n\n constructor(\n message: TokenItem | OutputMessage,\n tryMessage: TokenItem | OutputMessage | null = null,\n nextSteps?: TokenItem<InlineToken>[],\n customSections?: AlertCustomSection[],\n ) {\n super(message, FatalErrorType.Abort, tryMessage, nextSteps, customSections)\n }\n}\n\n/**\n * An external error is similar to Abort but has extra command and args attributes.\n * This is useful to represent errors coming from external commands, usually executed by execa.\n */\nexport class ExternalError extends FatalError {\n command: string\n args: string[]\n\n constructor(\n message: OutputMessage,\n command: string,\n args: string[],\n tryMessage: TokenItem | OutputMessage | null = null,\n ) {\n super(message, FatalErrorType.Abort, tryMessage)\n this.command = command\n this.args = args\n }\n}\n\nexport class AbortSilentError extends FatalError {\n constructor() {\n super('', FatalErrorType.AbortSilent)\n }\n}\n\n/**\n * A bug error is an error that represents a bug and therefore should be reported.\n */\nexport class BugError extends FatalError {\n constructor(message: TokenItem | OutputMessage, tryMessage: TokenItem | OutputMessage | null = null) {\n super(message, FatalErrorType.Bug, tryMessage)\n }\n}\n\n/**\n * A function that handles errors that blow up in the CLI.\n *\n * @param error - Error to be handled.\n * @returns A promise that resolves with the error passed.\n */\nexport async function handler(error: unknown): Promise<unknown> {\n let fatal: FatalError\n if (isFatal(error)) {\n fatal = error\n } else if (typeof error === 'string') {\n fatal = new BugError(error)\n } else if (error instanceof Error) {\n fatal = new BugError(error.message)\n fatal.stack = error.stack\n } else {\n // errors can come in all shapes and sizes...\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const maybeError = error as any\n fatal = new BugError(maybeError?.message ?? 'Unknown error')\n if (maybeError?.stack) {\n fatal.stack = maybeError?.stack\n }\n }\n\n renderFatalError(fatal)\n return Promise.resolve(error)\n}\n\n/**\n * A function that maps an error to an Abort with the stack trace when coming from the CLI.\n *\n * @param error - Error to be mapped.\n * @returns A promise that resolves with the new error object.\n */\nexport function errorMapper(error: unknown): Promise<unknown> {\n if (error instanceof Errors.CLIError) {\n const mappedError = new AbortError(error.message)\n mappedError.stack = error.stack\n return Promise.resolve(mappedError)\n } else {\n return Promise.resolve(error)\n }\n}\n\n/**\n * A function that checks if an error is a fatal one.\n *\n * @param error - Error to be checked.\n * @returns A boolean indicating if the error is a fatal one.\n */\nfunction isFatal(error: unknown): error is FatalError {\n try {\n return Object.prototype.hasOwnProperty.call(error, 'type')\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch {\n return false\n }\n}\n\n/**\n * A function that checks if an error should be reported as unhandled.\n *\n * @param error - Error to be checked.\n * @returns A boolean indicating if the error should be reported.\n */\nexport function shouldReportError(error: unknown): boolean {\n if (!isFatal(error)) {\n return true\n }\n if (error.type === FatalErrorType.Bug) {\n return true\n }\n return false\n}\n\n/**\n * Stack traces usually have file:// - we strip that and also remove the Windows drive designation.\n *\n * @param filePath - Path to be cleaned.\n * @returns The cleaned path.\n */\nexport function cleanSingleStackTracePath(filePath: string): string {\n return normalizePath(filePath)\n .replace('file:/', '/')\n .replace(/^\\/?[A-Z]:/, '')\n}\n"]}
|
|
1
|
+
{"version":3,"file":"error.js","sourceRoot":"","sources":["../../../src/public/node/error.ts"],"names":[],"mappings":"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","sourcesContent":["import {AlertCustomSection, renderFatalError} from './ui.js'\nimport {OutputMessage, stringifyMessage, TokenizedString} from '../../public/node/output.js'\nimport {normalizePath} from '../../public/node/path.js'\nimport {InlineToken, TokenItem, tokenItemToString} from '../../private/node/ui/components/TokenizedText.js'\nimport {Errors} from '@oclif/core'\n\nexport {ExtendableError} from 'ts-error'\n\nexport enum FatalErrorType {\n Abort,\n AbortSilent,\n Bug,\n}\n\nexport class CancelExecution extends Error {}\n\n/**\n * A fatal error represents an error shouldn't be rescued and that causes the execution to terminate.\n * There shouldn't be code that catches fatal errors.\n */\nexport abstract class FatalError extends Error {\n tryMessage: TokenItem | null\n type: FatalErrorType\n nextSteps?: TokenItem<InlineToken>[]\n formattedMessage?: TokenItem\n customSections?: AlertCustomSection[]\n skipOclifErrorHandling: boolean\n /**\n * Creates a new FatalError error.\n *\n * @param message - The error message.\n * @param type - The type of fatal error.\n * @param tryMessage - The message that recommends next steps to the user.\n * You can pass a string a {@link TokenizedString} or a {@link TokenItem}\n * if you need to style the message inside the error Banner component.\n * @param nextSteps - Message to show as \"next steps\" with suggestions to solve the issue.\n * @param customSections - Custom sections to show in the error banner. To be used if nextSteps is not enough.\n */\n constructor(\n message: TokenItem | OutputMessage,\n type: FatalErrorType,\n tryMessage: TokenItem | OutputMessage | null = null,\n nextSteps?: TokenItem<InlineToken>[],\n customSections?: AlertCustomSection[],\n ) {\n const messageIsOutputMessage = typeof message === 'string' || 'value' in message\n super(messageIsOutputMessage ? stringifyMessage(message) : tokenItemToString(message))\n\n if (tryMessage) {\n if (tryMessage instanceof TokenizedString) {\n this.tryMessage = stringifyMessage(tryMessage)\n } else {\n this.tryMessage = tryMessage\n }\n } else {\n this.tryMessage = null\n }\n\n this.type = type\n this.nextSteps = nextSteps\n this.customSections = customSections\n this.skipOclifErrorHandling = true\n\n if (!messageIsOutputMessage) {\n this.formattedMessage = message\n }\n }\n}\n\n/**\n * An abort error is a fatal error that shouldn't be reported as a bug.\n * Those usually represent unexpected scenarios that we can't handle and that usually require some action from the developer.\n */\nexport class AbortError extends FatalError {\n nextSteps?: TokenItem<InlineToken>[]\n customSections?: AlertCustomSection[]\n\n constructor(\n message: TokenItem | OutputMessage,\n tryMessage: TokenItem | OutputMessage | null = null,\n nextSteps?: TokenItem<InlineToken>[],\n customSections?: AlertCustomSection[],\n ) {\n super(message, FatalErrorType.Abort, tryMessage, nextSteps, customSections)\n }\n}\n\n/**\n * An external error is similar to Abort but has extra command and args attributes.\n * This is useful to represent errors coming from external commands, usually executed by execa.\n */\nexport class ExternalError extends FatalError {\n command: string\n args: string[]\n\n constructor(\n message: OutputMessage,\n command: string,\n args: string[],\n tryMessage: TokenItem | OutputMessage | null = null,\n ) {\n super(message, FatalErrorType.Abort, tryMessage)\n this.command = command\n this.args = args\n }\n}\n\nexport class AbortSilentError extends FatalError {\n constructor() {\n super('', FatalErrorType.AbortSilent)\n }\n}\n\n/**\n * A bug error is an error that represents a bug and therefore should be reported.\n */\nexport class BugError extends FatalError {\n constructor(message: TokenItem | OutputMessage, tryMessage: TokenItem | OutputMessage | null = null) {\n super(message, FatalErrorType.Bug, tryMessage)\n }\n}\n\n/**\n * A function that handles errors that blow up in the CLI.\n *\n * @param error - Error to be handled.\n * @returns A promise that resolves with the error passed.\n */\nexport async function handler(error: unknown): Promise<unknown> {\n let fatal: FatalError\n if (isFatal(error)) {\n fatal = error\n } else if (typeof error === 'string') {\n fatal = new BugError(error)\n } else if (error instanceof Error) {\n fatal = new BugError(error.message)\n fatal.stack = error.stack\n } else {\n // errors can come in all shapes and sizes...\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const maybeError = error as any\n fatal = new BugError(maybeError?.message ?? 'Unknown error')\n if (maybeError?.stack) {\n fatal.stack = maybeError?.stack\n }\n }\n\n renderFatalError(fatal)\n return Promise.resolve(error)\n}\n\n/**\n * A function that maps an error to an Abort with the stack trace when coming from the CLI.\n *\n * @param error - Error to be mapped.\n * @returns A promise that resolves with the new error object.\n */\nexport function errorMapper(error: unknown): Promise<unknown> {\n if (error instanceof Errors.CLIError) {\n const mappedError = new AbortError(error.message)\n mappedError.stack = error.stack\n return Promise.resolve(mappedError)\n } else {\n return Promise.resolve(error)\n }\n}\n\n/**\n * A function that checks if an error is a fatal one.\n *\n * @param error - Error to be checked.\n * @returns A boolean indicating if the error is a fatal one.\n */\nfunction isFatal(error: unknown): error is FatalError {\n try {\n return Object.prototype.hasOwnProperty.call(error, 'type')\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch {\n return false\n }\n}\n\n/**\n * A function that checks if an error should be reported as unexpected.\n *\n * @param error - Error to be checked.\n * @returns A boolean indicating if the error should be reported as unexpected.\n */\nexport function shouldReportErrorAsUnexpected(error: unknown): boolean {\n if (!isFatal(error)) {\n // this means its not one of the CLI wrapped errors\n if (error instanceof Error) {\n const message = error.message\n return !errorMessageImpliesEnvironmentIssue(message)\n }\n return true\n }\n if (error.type === FatalErrorType.Bug) {\n return true\n }\n return false\n}\n\n/**\n * Stack traces usually have file:// - we strip that and also remove the Windows drive designation.\n *\n * @param filePath - Path to be cleaned.\n * @returns The cleaned path.\n */\nexport function cleanSingleStackTracePath(filePath: string): string {\n return normalizePath(filePath)\n .replace('file:/', '/')\n .replace(/^\\/?[A-Z]:/, '')\n}\n\n/**\n * There are certain errors that we know are not due to a CLI bug, but are environmental/user error.\n *\n * @param message - The error message to check.\n * @returns A boolean indicating if the error message implies an environment issue.\n */\nfunction errorMessageImpliesEnvironmentIssue(message: string): boolean {\n const environmentIssueMessages = [\n 'EPERM: operation not permitted, scandir',\n 'EACCES: permission denied',\n 'EPERM: operation not permitted, symlink',\n 'This version of npm supports the following node versions',\n 'EBUSY: resource busy or locked, rmdir',\n 'getaddrinfo ENOTFOUND',\n 'Client network socket disconnected before secure TLS connection was established',\n 'spawn EPERM',\n 'socket hang up',\n ]\n const anyMatches = environmentIssueMessages.some((issueMessage) => message.includes(issueMessage))\n return anyMatches\n}\n"]}
|