@shopify/cli-kit 3.76.1 → 3.77.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.
- package/dist/private/node/api.d.ts +27 -4
- package/dist/private/node/api.js +64 -8
- package/dist/private/node/api.js.map +1 -1
- package/dist/private/node/constants.d.ts +2 -0
- package/dist/private/node/constants.js +2 -0
- package/dist/private/node/constants.js.map +1 -1
- package/dist/private/node/session/device-authorization.js +3 -3
- package/dist/private/node/session/device-authorization.js.map +1 -1
- package/dist/private/node/session/schema.d.ts +40 -40
- package/dist/private/node/sleep-with-backoff.d.ts +16 -0
- package/dist/private/node/sleep-with-backoff.js +64 -0
- package/dist/private/node/sleep-with-backoff.js.map +1 -0
- package/dist/public/common/version.d.ts +1 -1
- package/dist/public/common/version.js +1 -1
- package/dist/public/common/version.js.map +1 -1
- package/dist/public/node/api/admin.js +2 -2
- package/dist/public/node/api/admin.js.map +1 -1
- package/dist/public/node/api/graphql.js +6 -1
- package/dist/public/node/api/graphql.js.map +1 -1
- package/dist/public/node/context/fqdn.js +1 -1
- package/dist/public/node/context/fqdn.js.map +1 -1
- package/dist/public/node/environment.d.ts +20 -0
- package/dist/public/node/environment.js +29 -0
- package/dist/public/node/environment.js.map +1 -1
- package/dist/public/node/github.d.ts +1 -0
- package/dist/public/node/github.js +31 -2
- package/dist/public/node/github.js.map +1 -1
- package/dist/public/node/hooks/prerun.js +1 -2
- package/dist/public/node/hooks/prerun.js.map +1 -1
- package/dist/public/node/http.d.ts +48 -3
- package/dist/public/node/http.js +134 -24
- package/dist/public/node/http.js.map +1 -1
- package/dist/public/node/monorail.js +1 -1
- package/dist/public/node/monorail.js.map +1 -1
- package/dist/public/node/notifications-system.js +26 -11
- package/dist/public/node/notifications-system.js.map +1 -1
- package/dist/public/node/system.d.ts +6 -0
- package/dist/public/node/system.js +9 -2
- package/dist/public/node/system.js.map +1 -1
- package/dist/public/node/testing/test-with-temp-dir.d.ts +9 -0
- package/dist/public/node/testing/test-with-temp-dir.js +14 -0
- package/dist/public/node/testing/test-with-temp-dir.js.map +1 -0
- package/dist/public/node/themes/types.d.ts +3 -2
- package/dist/public/node/themes/types.js.map +1 -1
- package/dist/public/node/vendor/dev_server/dev-server-2016.d.ts +9 -0
- package/dist/public/node/vendor/dev_server/dev-server-2016.js +38 -0
- package/dist/public/node/vendor/dev_server/dev-server-2016.js.map +1 -0
- package/dist/public/node/vendor/dev_server/dev-server-2024.d.ts +9 -0
- package/dist/public/node/vendor/dev_server/dev-server-2024.js +68 -0
- package/dist/public/node/vendor/dev_server/dev-server-2024.js.map +1 -0
- package/dist/public/node/vendor/dev_server/dev-server-spin.d.ts +5 -0
- package/dist/public/node/vendor/dev_server/dev-server-spin.js +28 -0
- package/dist/public/node/vendor/dev_server/dev-server-spin.js.map +1 -0
- package/dist/public/node/vendor/dev_server/dev-server.d.ts +15 -0
- package/dist/public/node/vendor/dev_server/dev-server.js +59 -0
- package/dist/public/node/vendor/dev_server/dev-server.js.map +1 -0
- package/dist/public/node/vendor/dev_server/env.d.ts +2 -0
- package/dist/public/node/vendor/dev_server/env.js +7 -0
- package/dist/public/node/vendor/dev_server/env.js.map +1 -0
- package/dist/public/node/vendor/dev_server/index.d.ts +2 -0
- package/dist/public/node/vendor/dev_server/index.js +3 -0
- package/dist/public/node/vendor/dev_server/index.js.map +1 -0
- package/dist/public/node/vendor/dev_server/network/host.d.ts +2 -0
- package/dist/public/node/vendor/dev_server/network/host.js +45 -0
- package/dist/public/node/vendor/dev_server/network/host.js.map +1 -0
- package/dist/public/node/vendor/dev_server/network/index.d.ts +9 -0
- package/dist/public/node/vendor/dev_server/network/index.js +36 -0
- package/dist/public/node/vendor/dev_server/network/index.js.map +1 -0
- package/dist/public/node/vendor/dev_server/types.d.ts +11 -0
- package/dist/public/node/vendor/dev_server/types.js +2 -0
- package/dist/public/node/vendor/dev_server/types.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -1
- package/dist/public/node/vendor/dev_server/DevServer.d.ts +0 -19
- package/dist/public/node/vendor/dev_server/DevServer.js +0 -170
- package/dist/public/node/vendor/dev_server/DevServer.js.map +0 -1
|
@@ -56,3 +56,23 @@ export declare function jsonOutputEnabled(environment?: NodeJS.ProcessEnv): bool
|
|
|
56
56
|
* @returns True if the SHOPIFY_CLI_NEVER_USE_PARTNERS_API environment variable is set.
|
|
57
57
|
*/
|
|
58
58
|
export declare function blockPartnersAccess(): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* If true, the CLI should not use the network level retry.
|
|
61
|
+
*
|
|
62
|
+
* If there is an error when calling a network API that looks like a DNS or connectivity issue, the CLI will by default
|
|
63
|
+
* automatically retry the request.
|
|
64
|
+
*
|
|
65
|
+
* @param environment - Process environment variables.
|
|
66
|
+
* @returns True if the SHOPIFY_CLI_SKIP_NETWORK_LEVEL_RETRY environment variable is set.
|
|
67
|
+
*/
|
|
68
|
+
export declare function skipNetworkLevelRetry(environment?: NodeJS.ProcessEnv): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Returns the default maximum request time for network calls in milliseconds.
|
|
71
|
+
*
|
|
72
|
+
* After this long, API requests may be cancelled by an AbortSignal. The limit can be overridden by setting the
|
|
73
|
+
* SHOPIFY_CLI_MAX_REQUEST_TIME_FOR_NETWORK_CALLS environment variable.
|
|
74
|
+
*
|
|
75
|
+
* @param environment - Process environment variables.
|
|
76
|
+
* @returns The maximum request time in milliseconds.
|
|
77
|
+
*/
|
|
78
|
+
export declare function maxRequestTimeForNetworkCallsMs(environment?: NodeJS.ProcessEnv): number;
|
|
@@ -84,4 +84,33 @@ export function jsonOutputEnabled(environment = getEnvironmentVariables()) {
|
|
|
84
84
|
export function blockPartnersAccess() {
|
|
85
85
|
return isTruthy(getEnvironmentVariables()[environmentVariables.neverUsePartnersApi]);
|
|
86
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* If true, the CLI should not use the network level retry.
|
|
89
|
+
*
|
|
90
|
+
* If there is an error when calling a network API that looks like a DNS or connectivity issue, the CLI will by default
|
|
91
|
+
* automatically retry the request.
|
|
92
|
+
*
|
|
93
|
+
* @param environment - Process environment variables.
|
|
94
|
+
* @returns True if the SHOPIFY_CLI_SKIP_NETWORK_LEVEL_RETRY environment variable is set.
|
|
95
|
+
*/
|
|
96
|
+
export function skipNetworkLevelRetry(environment = getEnvironmentVariables()) {
|
|
97
|
+
return isTruthy(environment[environmentVariables.skipNetworkLevelRetry]);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Returns the default maximum request time for network calls in milliseconds.
|
|
101
|
+
*
|
|
102
|
+
* After this long, API requests may be cancelled by an AbortSignal. The limit can be overridden by setting the
|
|
103
|
+
* SHOPIFY_CLI_MAX_REQUEST_TIME_FOR_NETWORK_CALLS environment variable.
|
|
104
|
+
*
|
|
105
|
+
* @param environment - Process environment variables.
|
|
106
|
+
* @returns The maximum request time in milliseconds.
|
|
107
|
+
*/
|
|
108
|
+
export function maxRequestTimeForNetworkCallsMs(environment = getEnvironmentVariables()) {
|
|
109
|
+
const maxRequestTime = environment[environmentVariables.maxRequestTimeForNetworkCalls];
|
|
110
|
+
if (maxRequestTime && !isNaN(Number(maxRequestTime))) {
|
|
111
|
+
return Number(maxRequestTime);
|
|
112
|
+
}
|
|
113
|
+
// 15 seconds is the default
|
|
114
|
+
return 15 * 1000;
|
|
115
|
+
}
|
|
87
116
|
//# sourceMappingURL=environment.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environment.js","sourceRoot":"","sources":["../../../src/public/node/environment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,aAAa,CAAA;AACzC,OAAO,EAAC,QAAQ,EAAC,MAAM,wBAAwB,CAAA;AAC/C,OAAO,EAAC,YAAY,EAAC,MAAM,WAAW,CAAA;AACtC,OAAO,EAAC,oBAAoB,EAAE,0BAA0B,EAAC,MAAM,iCAAiC,CAAA;AAEhG;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO,OAAO,CAAC,GAAG,CAAA;AACpB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,uBAAuB,EAAE,CAAC,oBAAoB,CAAC,aAAa,CAAC,CAAA;AACtE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,gBAAgB,EAAE,KAAK,SAAS,CAAA;AACzC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,uBAAuB,EAAE,CAAC,oBAAoB,CAAC,YAAY,CAAC,CAAA;AACrE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,WAAW,GAAG,uBAAuB,EAAE,CAAC,0BAA0B,CAAC,WAAW,CAAC,CAAA;IACrF,IAAI,WAAW,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;QAC/C,OAAO,MAAM,CAAC,WAAW,CAAC,CAAA;IAC5B,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,2BAA2B;IACzC,MAAM,aAAa,GAAG,uBAAuB,EAAE,CAAC,oBAAoB,CAAC,aAAa,CAAC,CAAA;IACnF,MAAM,YAAY,GAAG,uBAAuB,EAAE,CAAC,oBAAoB,CAAC,YAAY,CAAC,CAAA;IACjF,IAAI,CAAC,aAAa,IAAI,CAAC,YAAY;QAAE,OAAO,SAAS,CAAA;IACrD,OAAO;QACL,WAAW,EAAE,aAAa;QAC1B,YAAY;QACZ,MAAM,EAAE,aAAa,CAAC,aAAa,CAAC;KACrC,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,WAAW,GAAG,uBAAuB,EAAE;IACvE,OAAO,YAAY,EAAE,IAAI,QAAQ,CAAC,WAAW,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAA;AAC3E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO,QAAQ,CAAC,uBAAuB,EAAE,CAAC,oBAAoB,CAAC,mBAAmB,CAAC,CAAC,CAAA;AACtF,CAAC","sourcesContent":["import {nonRandomUUID} from './crypto.js'\nimport {isTruthy} from './context/utilities.js'\nimport {sniffForJson} from './path.js'\nimport {environmentVariables, systemEnvironmentVariables} from '../../private/node/constants.js'\n\n/**\n * It returns the environment variables of the environment\n * where the Node process is running.\n *\n * This function exists to prevent the access of the process\n * global variable which is discouraged via the no-process-env\n * ESLint rule.\n *\n * @returns Current process environment variables.\n */\nexport function getEnvironmentVariables(): NodeJS.ProcessEnv {\n return process.env\n}\n\n/**\n * Returns the value of the SHOPIFY_CLI_PARTNERS_TOKEN environment variable.\n *\n * @returns Current process environment variables.\n */\nexport function getPartnersToken(): string | undefined {\n return getEnvironmentVariables()[environmentVariables.partnersToken]\n}\n\n/**\n * Check if the current proccess is running using the partners token.\n *\n * @returns True if the current proccess is running using the partners token.\n */\nexport function usePartnersToken(): boolean {\n return getPartnersToken() !== undefined\n}\n\n/**\n * Returns the value of the organization id from the environment variables.\n *\n * @returns True if the current proccess is running using the partners token.\n */\nexport function getOrganization(): string | undefined {\n return getEnvironmentVariables()[environmentVariables.organization]\n}\n\n/**\n * Return the backend port value.\n *\n * @returns The port as a number. Undefined otherwise.\n */\nexport function getBackendPort(): number | undefined {\n const backendPort = getEnvironmentVariables()[systemEnvironmentVariables.backendPort]\n if (backendPort && !isNaN(Number(backendPort))) {\n return Number(backendPort)\n }\n return undefined\n}\n\n/**\n * Returns the information of the identity & refresh tokens, provided by environment variables.\n *\n * @returns The identity token information in case it exists.\n */\nexport function getIdentityTokenInformation(): {accessToken: string; refreshToken: string; userId: string} | undefined {\n const identityToken = getEnvironmentVariables()[environmentVariables.identityToken]\n const refreshToken = getEnvironmentVariables()[environmentVariables.refreshToken]\n if (!identityToken || !refreshToken) return undefined\n return {\n accessToken: identityToken,\n refreshToken,\n userId: nonRandomUUID(identityToken),\n }\n}\n\n/**\n * Checks if the JSON output is enabled via flag (--json or -j) or environment variable (SHOPIFY_FLAG_JSON).\n *\n * @param environment - Process environment variables.\n * @returns True if the JSON output is enabled, false otherwise.\n */\nexport function jsonOutputEnabled(environment = getEnvironmentVariables()): boolean {\n return sniffForJson() || isTruthy(environment[environmentVariables.json])\n}\n\n/**\n * If true, the CLI should not use the Partners API.\n *\n * @returns True if the SHOPIFY_CLI_NEVER_USE_PARTNERS_API environment variable is set.\n */\nexport function blockPartnersAccess(): boolean {\n return isTruthy(getEnvironmentVariables()[environmentVariables.neverUsePartnersApi])\n}\n"]}
|
|
1
|
+
{"version":3,"file":"environment.js","sourceRoot":"","sources":["../../../src/public/node/environment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,aAAa,CAAA;AACzC,OAAO,EAAC,QAAQ,EAAC,MAAM,wBAAwB,CAAA;AAC/C,OAAO,EAAC,YAAY,EAAC,MAAM,WAAW,CAAA;AACtC,OAAO,EAAC,oBAAoB,EAAE,0BAA0B,EAAC,MAAM,iCAAiC,CAAA;AAEhG;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO,OAAO,CAAC,GAAG,CAAA;AACpB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,uBAAuB,EAAE,CAAC,oBAAoB,CAAC,aAAa,CAAC,CAAA;AACtE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,gBAAgB,EAAE,KAAK,SAAS,CAAA;AACzC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,uBAAuB,EAAE,CAAC,oBAAoB,CAAC,YAAY,CAAC,CAAA;AACrE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,WAAW,GAAG,uBAAuB,EAAE,CAAC,0BAA0B,CAAC,WAAW,CAAC,CAAA;IACrF,IAAI,WAAW,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;QAC/C,OAAO,MAAM,CAAC,WAAW,CAAC,CAAA;IAC5B,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,2BAA2B;IACzC,MAAM,aAAa,GAAG,uBAAuB,EAAE,CAAC,oBAAoB,CAAC,aAAa,CAAC,CAAA;IACnF,MAAM,YAAY,GAAG,uBAAuB,EAAE,CAAC,oBAAoB,CAAC,YAAY,CAAC,CAAA;IACjF,IAAI,CAAC,aAAa,IAAI,CAAC,YAAY;QAAE,OAAO,SAAS,CAAA;IACrD,OAAO;QACL,WAAW,EAAE,aAAa;QAC1B,YAAY;QACZ,MAAM,EAAE,aAAa,CAAC,aAAa,CAAC;KACrC,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,WAAW,GAAG,uBAAuB,EAAE;IACvE,OAAO,YAAY,EAAE,IAAI,QAAQ,CAAC,WAAW,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAA;AAC3E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO,QAAQ,CAAC,uBAAuB,EAAE,CAAC,oBAAoB,CAAC,mBAAmB,CAAC,CAAC,CAAA;AACtF,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CAAC,WAAW,GAAG,uBAAuB,EAAE;IAC3E,OAAO,QAAQ,CAAC,WAAW,CAAC,oBAAoB,CAAC,qBAAqB,CAAC,CAAC,CAAA;AAC1E,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,+BAA+B,CAAC,WAAW,GAAG,uBAAuB,EAAE;IACrF,MAAM,cAAc,GAAG,WAAW,CAAC,oBAAoB,CAAC,6BAA6B,CAAC,CAAA;IACtF,IAAI,cAAc,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC;QACrD,OAAO,MAAM,CAAC,cAAc,CAAC,CAAA;IAC/B,CAAC;IACD,4BAA4B;IAC5B,OAAO,EAAE,GAAG,IAAI,CAAA;AAClB,CAAC","sourcesContent":["import {nonRandomUUID} from './crypto.js'\nimport {isTruthy} from './context/utilities.js'\nimport {sniffForJson} from './path.js'\nimport {environmentVariables, systemEnvironmentVariables} from '../../private/node/constants.js'\n\n/**\n * It returns the environment variables of the environment\n * where the Node process is running.\n *\n * This function exists to prevent the access of the process\n * global variable which is discouraged via the no-process-env\n * ESLint rule.\n *\n * @returns Current process environment variables.\n */\nexport function getEnvironmentVariables(): NodeJS.ProcessEnv {\n return process.env\n}\n\n/**\n * Returns the value of the SHOPIFY_CLI_PARTNERS_TOKEN environment variable.\n *\n * @returns Current process environment variables.\n */\nexport function getPartnersToken(): string | undefined {\n return getEnvironmentVariables()[environmentVariables.partnersToken]\n}\n\n/**\n * Check if the current proccess is running using the partners token.\n *\n * @returns True if the current proccess is running using the partners token.\n */\nexport function usePartnersToken(): boolean {\n return getPartnersToken() !== undefined\n}\n\n/**\n * Returns the value of the organization id from the environment variables.\n *\n * @returns True if the current proccess is running using the partners token.\n */\nexport function getOrganization(): string | undefined {\n return getEnvironmentVariables()[environmentVariables.organization]\n}\n\n/**\n * Return the backend port value.\n *\n * @returns The port as a number. Undefined otherwise.\n */\nexport function getBackendPort(): number | undefined {\n const backendPort = getEnvironmentVariables()[systemEnvironmentVariables.backendPort]\n if (backendPort && !isNaN(Number(backendPort))) {\n return Number(backendPort)\n }\n return undefined\n}\n\n/**\n * Returns the information of the identity & refresh tokens, provided by environment variables.\n *\n * @returns The identity token information in case it exists.\n */\nexport function getIdentityTokenInformation(): {accessToken: string; refreshToken: string; userId: string} | undefined {\n const identityToken = getEnvironmentVariables()[environmentVariables.identityToken]\n const refreshToken = getEnvironmentVariables()[environmentVariables.refreshToken]\n if (!identityToken || !refreshToken) return undefined\n return {\n accessToken: identityToken,\n refreshToken,\n userId: nonRandomUUID(identityToken),\n }\n}\n\n/**\n * Checks if the JSON output is enabled via flag (--json or -j) or environment variable (SHOPIFY_FLAG_JSON).\n *\n * @param environment - Process environment variables.\n * @returns True if the JSON output is enabled, false otherwise.\n */\nexport function jsonOutputEnabled(environment = getEnvironmentVariables()): boolean {\n return sniffForJson() || isTruthy(environment[environmentVariables.json])\n}\n\n/**\n * If true, the CLI should not use the Partners API.\n *\n * @returns True if the SHOPIFY_CLI_NEVER_USE_PARTNERS_API environment variable is set.\n */\nexport function blockPartnersAccess(): boolean {\n return isTruthy(getEnvironmentVariables()[environmentVariables.neverUsePartnersApi])\n}\n\n/**\n * If true, the CLI should not use the network level retry.\n *\n * If there is an error when calling a network API that looks like a DNS or connectivity issue, the CLI will by default\n * automatically retry the request.\n *\n * @param environment - Process environment variables.\n * @returns True if the SHOPIFY_CLI_SKIP_NETWORK_LEVEL_RETRY environment variable is set.\n */\nexport function skipNetworkLevelRetry(environment = getEnvironmentVariables()): boolean {\n return isTruthy(environment[environmentVariables.skipNetworkLevelRetry])\n}\n\n/**\n * Returns the default maximum request time for network calls in milliseconds.\n *\n * After this long, API requests may be cancelled by an AbortSignal. The limit can be overridden by setting the\n * SHOPIFY_CLI_MAX_REQUEST_TIME_FOR_NETWORK_CALLS environment variable.\n *\n * @param environment - Process environment variables.\n * @returns The maximum request time in milliseconds.\n */\nexport function maxRequestTimeForNetworkCallsMs(environment = getEnvironmentVariables()): number {\n const maxRequestTime = environment[environmentVariables.maxRequestTimeForNetworkCalls]\n if (maxRequestTime && !isNaN(Number(maxRequestTime))) {\n return Number(maxRequestTime)\n }\n // 15 seconds is the default\n return 15 * 1000\n}\n"]}
|
|
@@ -47,4 +47,5 @@ export interface GithubRepositoryReference {
|
|
|
47
47
|
* @param reference - A GitHub repository URL (e.g. https://github.com/Shopify/cli/blob/main/package.json)
|
|
48
48
|
*/
|
|
49
49
|
export declare function parseGitHubRepositoryReference(reference: string): GithubRepositoryReference;
|
|
50
|
+
export declare function downloadGitHubRelease(repo: string, version: string, assetName: string, targetPath: string): Promise<void>;
|
|
50
51
|
export {};
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
2
2
|
import { err, ok } from './result.js';
|
|
3
3
|
import { fetch } from './http.js';
|
|
4
|
-
import {
|
|
4
|
+
import { writeFile, mkdir, inTemporaryDirectory, moveFile, chmod } from './fs.js';
|
|
5
|
+
import { dirname, joinPath } from './path.js';
|
|
6
|
+
import { runWithTimer } from './metadata.js';
|
|
7
|
+
import { AbortError } from './error.js';
|
|
8
|
+
import { outputContent, outputDebug, outputToken } from '../../public/node/output.js';
|
|
5
9
|
class GitHubClientError extends Error {
|
|
6
10
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7
11
|
constructor(url, statusCode, bodyJson) {
|
|
@@ -41,7 +45,7 @@ export function parseGitHubRepositoryURL(url) {
|
|
|
41
45
|
];
|
|
42
46
|
return err(new Error(`Parsing the url ${url} failed. Supported formats are ${exampleFormats.join(', ')}.`));
|
|
43
47
|
}
|
|
44
|
-
const site = match[1]
|
|
48
|
+
const site = match[1] ?? match[2] ?? match[3] ?? 'github.com';
|
|
45
49
|
const normalizedSite = site === 'github' ? 'github.com' : site;
|
|
46
50
|
const user = match[4];
|
|
47
51
|
const name = match[5].replace(/\.git$/, '');
|
|
@@ -70,4 +74,29 @@ export function parseGitHubRepositoryReference(reference) {
|
|
|
70
74
|
filePath,
|
|
71
75
|
};
|
|
72
76
|
}
|
|
77
|
+
export async function downloadGitHubRelease(repo, version, assetName, targetPath) {
|
|
78
|
+
const url = `https://github.com/${repo}/releases/download/${version}/${assetName}`;
|
|
79
|
+
return runWithTimer('cmd_all_timing_network_ms')(async () => {
|
|
80
|
+
outputDebug(outputContent `Downloading ${outputToken.link(assetName, url)}`);
|
|
81
|
+
await inTemporaryDirectory(async (tmpDir) => {
|
|
82
|
+
const tempPath = joinPath(tmpDir, assetName);
|
|
83
|
+
let response;
|
|
84
|
+
try {
|
|
85
|
+
response = await fetch(url);
|
|
86
|
+
if (!response.ok) {
|
|
87
|
+
throw new AbortError(`Failed to download ${assetName}: ${response.statusText}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
throw new AbortError(`Failed to download ${assetName}: ${error instanceof Error ? error.message : 'unknown error'}`);
|
|
92
|
+
}
|
|
93
|
+
const buffer = await response.arrayBuffer();
|
|
94
|
+
await writeFile(tempPath, Buffer.from(buffer));
|
|
95
|
+
await chmod(tempPath, 0o755);
|
|
96
|
+
await mkdir(dirname(targetPath));
|
|
97
|
+
await moveFile(tempPath, targetPath);
|
|
98
|
+
});
|
|
99
|
+
outputDebug(outputContent `${outputToken.successIcon()} Successfully downloaded ${outputToken.path(targetPath)}`);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
73
102
|
//# sourceMappingURL=github.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../../src/public/node/github.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,OAAO,EAAC,GAAG,EAAE,EAAE,EAAS,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAC,KAAK,
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../../src/public/node/github.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-non-null-assertion */\nimport {err, ok, Result} from './result.js'\nimport {fetch, Response} from './http.js'\nimport {writeFile, mkdir, inTemporaryDirectory, moveFile, chmod} from './fs.js'\nimport {dirname, joinPath} from './path.js'\nimport {runWithTimer} from './metadata.js'\nimport {AbortError} from './error.js'\nimport {outputContent, outputDebug, outputToken} from '../../public/node/output.js'\n\nclass GitHubClientError extends Error {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n constructor(url: string, statusCode: number, bodyJson: any) {\n super(\n `The request to GitHub API URL ${url} failed with status code ${statusCode} and the following error message: ${bodyJson.message}`,\n )\n }\n}\n\nexport interface GithubRelease {\n id: number\n url: string\n tag_name: string\n name: string\n body: string\n draft: boolean\n prerelease: boolean\n created_at: string\n published_at: string\n tarball_url: string\n}\n\ninterface GetLatestGitHubReleaseOptions {\n filter: (release: GithubRelease) => boolean\n}\n\n/**\n * Given a GitHub repository it obtains the latest release.\n * @param owner - Repository owner (e.g., shopify)\n * @param repo - Repository name (e.g., cli)\n * @param options - Options\n */\nexport async function getLatestGitHubRelease(\n owner: string,\n repo: string,\n options: GetLatestGitHubReleaseOptions = {filter: () => true},\n): Promise<GithubRelease> {\n outputDebug(outputContent`Getting the latest release of GitHub repository ${owner}/${repo}...`)\n const url = `https://api.github.com/repos/${owner}/${repo}/releases`\n const fetchResult = await fetch(url)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const jsonBody: any = await fetchResult.json()\n\n if (fetchResult.status !== 200) {\n throw new GitHubClientError(url, fetchResult.status, jsonBody)\n }\n\n return jsonBody.find(options.filter)\n}\n\ninterface ParseRepositoryURLOutput {\n full: string\n site: string\n user: string\n name: string\n ref: string\n subDirectory: string\n ssh: string\n http: string\n}\n\n/**\n * Given a GitHub repository URL, it parses it and returns its coomponents.\n * @param url - The GitHub repository URL\n */\nexport function parseGitHubRepositoryURL(url: string): Result<ParseRepositoryURLOutput, Error> {\n const match =\n /^(?:(?:https:\\/\\/)?([^:/]+\\.[^:/]+)\\/|git@([^:/]+)[:/]|([^/]+):)?([^/\\s]+)\\/([^/\\s#]+)(?:((?:\\/[^/\\s#]+)+))?(?:\\/)?(?:#(.+))?/.exec(\n url,\n )\n\n if (!match) {\n const exampleFormats = [\n 'github:user/repo',\n 'user/repo/subdirectory',\n 'git@github.com:user/repo',\n 'user/repo#dev',\n 'https://github.com/user/repo',\n ]\n\n return err(new Error(`Parsing the url ${url} failed. Supported formats are ${exampleFormats.join(', ')}.`))\n }\n\n const site = match[1] ?? match[2] ?? match[3] ?? 'github.com'\n const normalizedSite = site === 'github' ? 'github.com' : site\n const user = match[4]!\n const name = match[5]!.replace(/\\.git$/, '')\n // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain\n const subDirectory = match[6]?.slice(1)!\n const ref = match[7]!\n const branch = ref ? `#${ref}` : ''\n const ssh = `git@${normalizedSite}:${user}/${name}`\n const http = `https://${normalizedSite}/${user}/${name}`\n const full = ['https:/', normalizedSite, user, name, subDirectory].join('/').concat(branch)\n\n return ok({full, site: normalizedSite, user, name, ref, subDirectory, ssh, http})\n}\n\nexport interface GithubRepositoryReference {\n baseURL: string\n branch?: string\n filePath?: string\n}\n\n/**\n * Given a GitHub repository URL it parses it and extracts the branch, file path,\n * and base URL components\n * @param reference - A GitHub repository URL (e.g. https://github.com/Shopify/cli/blob/main/package.json)\n */\nexport function parseGitHubRepositoryReference(reference: string): GithubRepositoryReference {\n const url = new URL(reference)\n const branch = url.hash ? url.hash.slice(1) : undefined\n const [_, user, repo, ...repoPath] = url.pathname.split('/')\n const filePath = repoPath.length > 0 ? repoPath.join('/') : undefined\n\n return {\n baseURL: `${url.origin}/${user}/${repo}`,\n branch,\n filePath,\n }\n}\n\nexport async function downloadGitHubRelease(\n repo: string,\n version: string,\n assetName: string,\n targetPath: string,\n): Promise<void> {\n const url = `https://github.com/${repo}/releases/download/${version}/${assetName}`\n\n return runWithTimer('cmd_all_timing_network_ms')(async () => {\n outputDebug(outputContent`Downloading ${outputToken.link(assetName, url)}`)\n await inTemporaryDirectory(async (tmpDir) => {\n const tempPath = joinPath(tmpDir, assetName)\n let response: Response\n try {\n response = await fetch(url)\n if (!response.ok) {\n throw new AbortError(`Failed to download ${assetName}: ${response.statusText}`)\n }\n } catch (error) {\n throw new AbortError(\n `Failed to download ${assetName}: ${error instanceof Error ? error.message : 'unknown error'}`,\n )\n }\n\n const buffer = await response.arrayBuffer()\n await writeFile(tempPath, Buffer.from(buffer))\n\n await chmod(tempPath, 0o755)\n await mkdir(dirname(targetPath))\n await moveFile(tempPath, targetPath)\n })\n outputDebug(outputContent`${outputToken.successIcon()} Successfully downloaded ${outputToken.path(targetPath)}`)\n })\n}\n"]}
|
|
@@ -16,8 +16,7 @@ export const hook = async (options) => {
|
|
|
16
16
|
await warnOnAvailableUpgrade();
|
|
17
17
|
outputDebug(`Running command ${commandContent.command}`);
|
|
18
18
|
await startAnalytics({ commandContent, args, commandClass: options.Command });
|
|
19
|
-
|
|
20
|
-
fetchNotificationsInBackground(options.Command.id);
|
|
19
|
+
fetchNotificationsInBackground(options.Command.id);
|
|
21
20
|
};
|
|
22
21
|
export function parseCommandContent(cmdInfo) {
|
|
23
22
|
let commandContent = parseCreateCommand(cmdInfo.pluginAlias);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prerun.js","sourceRoot":"","sources":["../../../../src/public/node/hooks/prerun.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,yBAAyB,CAAA;AACvD,OAAO,EAAC,kBAAkB,EAAE,wBAAwB,EAAC,MAAM,4BAA4B,CAAA;AACvF,OAAO,EAAC,cAAc,EAAC,MAAM,oCAAoC,CAAA;AACjE,OAAO,EAAC,WAAW,EAAE,UAAU,EAAC,MAAM,gCAAgC,CAAA;AACtE,OAAO,EAAC,0BAA0B,EAAC,MAAM,iCAAiC,CAAA;AAE1E,OAAO,EAAC,oBAAoB,EAAC,MAAM,qCAAqC,CAAA;AACxE,OAAO,EAAC,8BAA8B,EAAC,MAAM,4BAA4B,CAAA;AAQzE,sFAAsF;AACtF,MAAM,CAAC,MAAM,IAAI,GAAgB,KAAK,EAAE,OAAO,EAAE,EAAE;IACjD,MAAM,cAAc,GAAG,mBAAmB,CAAC;QACzC,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE;QACtB,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,OAAO;QAChC,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK;KAC3C,CAAC,CAAA;IACF,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAA;IACzB,MAAM,sBAAsB,EAAE,CAAA;IAC9B,WAAW,CAAC,mBAAmB,cAAc,CAAC,OAAO,EAAE,CAAC,CAAA;IACxD,MAAM,cAAc,CAAC,EAAC,cAAc,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,CAAC,OAAoC,EAAC,CAAC,CAAA;IACxG,
|
|
1
|
+
{"version":3,"file":"prerun.js","sourceRoot":"","sources":["../../../../src/public/node/hooks/prerun.ts"],"names":[],"mappings":"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","sourcesContent":["import {CLI_KIT_VERSION} from '../../common/version.js'\nimport {checkForNewVersion, checkForCachedNewVersion} from '../node-package-manager.js'\nimport {startAnalytics} from '../../../private/node/analytics.js'\nimport {outputDebug, outputWarn} from '../../../public/node/output.js'\nimport {getOutputUpdateCLIReminder} from '../../../public/node/upgrade.js'\nimport Command from '../../../public/node/base-command.js'\nimport {runAtMinimumInterval} from '../../../private/node/conf-store.js'\nimport {fetchNotificationsInBackground} from '../notifications-system.js'\nimport {Hook} from '@oclif/core'\n\nexport declare interface CommandContent {\n command: string\n topic?: string\n alias?: string\n}\n// This hook is called before each command run. More info: https://oclif.io/docs/hooks\nexport const hook: Hook.Prerun = async (options) => {\n const commandContent = parseCommandContent({\n id: options.Command.id,\n aliases: options.Command.aliases,\n pluginAlias: options.Command.plugin?.alias,\n })\n const args = options.argv\n await warnOnAvailableUpgrade()\n outputDebug(`Running command ${commandContent.command}`)\n await startAnalytics({commandContent, args, commandClass: options.Command as unknown as typeof Command})\n fetchNotificationsInBackground(options.Command.id)\n}\n\nexport function parseCommandContent(cmdInfo: {id: string; aliases: string[]; pluginAlias?: string}): CommandContent {\n let commandContent = parseCreateCommand(cmdInfo.pluginAlias)\n if (!commandContent) {\n commandContent = parseNormalCommand(cmdInfo.id, cmdInfo.aliases)\n }\n return commandContent\n}\n\nfunction parseNormalCommand(id: string, aliases: string[]): CommandContent {\n return {\n command: id.replace(/:/g, ' '),\n topic: parseTopic(id),\n alias: findAlias(aliases),\n }\n}\n\n/**\n * Create commands implement Init by default, so the name of the command must be extracted from\n * the plugin/module name. Neither alias or topic are supported\n *\n * @param commandClass - Oclif command configuration\n * @returns Command content with the name of the command or undefined otherwise\n */\nfunction parseCreateCommand(pluginAlias?: string): CommandContent | undefined {\n if (!pluginAlias?.startsWith('@shopify/create-')) {\n return undefined\n }\n\n return {command: pluginAlias.substring(pluginAlias.indexOf('/') + 1)}\n}\n\n/**\n * Commands use this pattern topic:subtopic1:...:subtopicN:command. This method extract the topic and subtopic\n * information replacing the ':' separator with one space\n *\n * @param cmd - Complete command string to extract the topic information\n * @returns The topic name or undefined otherwise\n */\nfunction parseTopic(cmd: string) {\n if (cmd.lastIndexOf(':') === -1) {\n return\n }\n return cmd.slice(0, cmd.lastIndexOf(':')).replace(/:/g, ' ')\n}\n\n/**\n * Identifies if the command was launched using an alias instead of the oficial command name\n *\n * @param aliases - List of possible alias a command has\n * @returns The alias used or undefined otherwise\n */\nfunction findAlias(aliases: string[]) {\n const existingAlias = aliases.find((alias) =>\n alias.split(':').every((aliasToken) => process.argv.includes(aliasToken)),\n )\n if (existingAlias) {\n return existingAlias.replace(/:/g, ' ')\n }\n}\n\n/**\n * Warns the user if there is a new version of the CLI available\n */\nexport async function warnOnAvailableUpgrade(): Promise<void> {\n const cliDependency = '@shopify/cli'\n const currentVersion = CLI_KIT_VERSION\n if (currentVersion.startsWith('0.0.0')) {\n // This is a nightly/snapshot/experimental version, so we don't want to check for updates\n return\n }\n\n // Check in the background, once daily\n // eslint-disable-next-line no-void\n void checkForNewVersion(cliDependency, currentVersion, {cacheExpiryInHours: 24})\n\n // Warn if we previously found a new version\n await runAtMinimumInterval('warn-on-available-upgrade', {days: 1}, async () => {\n const newerVersion = checkForCachedNewVersion(cliDependency, currentVersion)\n if (newerVersion) {\n outputWarn(getOutputUpdateCLIReminder(newerVersion))\n }\n })\n}\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NetworkRetryBehaviour } from '../../private/node/api.js';
|
|
1
2
|
import FormData from 'form-data';
|
|
2
3
|
import { RequestInfo, RequestInit, Response } from 'node-fetch';
|
|
3
4
|
export { FetchError, Request, Response } from 'node-fetch';
|
|
@@ -7,6 +8,43 @@ export { FetchError, Request, Response } from 'node-fetch';
|
|
|
7
8
|
* @returns A FormData object.
|
|
8
9
|
*/
|
|
9
10
|
export declare function formData(): FormData;
|
|
11
|
+
type AbortSignal = RequestInit['signal'];
|
|
12
|
+
type PresetFetchBehaviour = 'default' | 'non-blocking' | 'slow-request';
|
|
13
|
+
type AutomaticCancellationBehaviour = {
|
|
14
|
+
useAbortSignal: true;
|
|
15
|
+
timeoutMs: number;
|
|
16
|
+
} | {
|
|
17
|
+
useAbortSignal: false;
|
|
18
|
+
} | {
|
|
19
|
+
useAbortSignal: AbortSignal | (() => AbortSignal);
|
|
20
|
+
};
|
|
21
|
+
type RequestBehaviour = NetworkRetryBehaviour & AutomaticCancellationBehaviour;
|
|
22
|
+
type RequestModeInput = PresetFetchBehaviour | RequestBehaviour;
|
|
23
|
+
/**
|
|
24
|
+
* Specify the behaviour of a network request.
|
|
25
|
+
*
|
|
26
|
+
* - default: Requests are automatically retried, and are subject to automatic cancellation if they're taking too long.
|
|
27
|
+
* This is generally desirable.
|
|
28
|
+
* - non-blocking: Requests are not retried if they fail with a network error, and are automatically cancelled if
|
|
29
|
+
* they're taking too long. This is good for throwaway requests, like polling or tracking.
|
|
30
|
+
* - slow-request: Requests are not retried if they fail with a network error, and are not automatically cancelled.
|
|
31
|
+
* This is good for slow requests that should be give the chance to complete, and are unlikely to be safe to retry.
|
|
32
|
+
*
|
|
33
|
+
* Some request behaviours may be de-activated by the environment, and this function takes care of that concern. You
|
|
34
|
+
* can also provide a customised request behaviour.
|
|
35
|
+
*
|
|
36
|
+
* @param preset - The preset to use.
|
|
37
|
+
* @param env - Process environment variables.
|
|
38
|
+
* @returns A request behaviour object.
|
|
39
|
+
*/
|
|
40
|
+
export declare function requestMode(preset?: RequestModeInput, env?: NodeJS.ProcessEnv): RequestBehaviour;
|
|
41
|
+
/**
|
|
42
|
+
* Create an AbortSignal for automatic request cancellation, from a request behaviour.
|
|
43
|
+
*
|
|
44
|
+
* @param behaviour - The request behaviour.
|
|
45
|
+
* @returns An AbortSignal.
|
|
46
|
+
*/
|
|
47
|
+
export declare function abortSignalFromRequestBehaviour(behaviour: RequestBehaviour): AbortSignal;
|
|
10
48
|
/**
|
|
11
49
|
* An interface that abstracts way node-fetch. When Node has built-in
|
|
12
50
|
* support for "fetch" in the standard library, we can drop the node-fetch
|
|
@@ -15,21 +53,28 @@ export declare function formData(): FormData;
|
|
|
15
53
|
* they are consistent with the Web API so if we drop node-fetch in the future
|
|
16
54
|
* it won't require changes from the callers.
|
|
17
55
|
*
|
|
56
|
+
* The CLI's fetch function supports special behaviours, like automatic retries. These are disabled by default through
|
|
57
|
+
* this function.
|
|
58
|
+
*
|
|
18
59
|
* @param url - This defines the resource that you wish to fetch.
|
|
19
60
|
* @param init - An object containing any custom settings that you want to apply to the request.
|
|
61
|
+
* @param preferredBehaviour - A request behaviour object that overrides the default behaviour.
|
|
20
62
|
* @returns A promise that resolves with the response.
|
|
21
63
|
*/
|
|
22
|
-
export declare function fetch(url: RequestInfo, init?: RequestInit): Promise<Response>;
|
|
64
|
+
export declare function fetch(url: RequestInfo, init?: RequestInit, preferredBehaviour?: RequestModeInput): Promise<Response>;
|
|
23
65
|
/**
|
|
24
66
|
* A fetch function to use with Shopify services. The function ensures the right
|
|
25
67
|
* TLS configuragion is used based on the environment in which the service is running
|
|
26
|
-
* (e.g. Spin).
|
|
68
|
+
* (e.g. Spin). NB: headers/auth are the responsibility of the caller.
|
|
69
|
+
*
|
|
70
|
+
* By default, the CLI's fetch function's special behaviours, like automatic retries, are enabled.
|
|
27
71
|
*
|
|
28
72
|
* @param url - This defines the resource that you wish to fetch.
|
|
29
73
|
* @param init - An object containing any custom settings that you want to apply to the request.
|
|
74
|
+
* @param preferredBehaviour - A request behaviour object that overrides the default behaviour.
|
|
30
75
|
* @returns A promise that resolves with the response.
|
|
31
76
|
*/
|
|
32
|
-
export declare function shopifyFetch(url: RequestInfo, init?: RequestInit): Promise<Response>;
|
|
77
|
+
export declare function shopifyFetch(url: RequestInfo, init?: RequestInit, preferredBehaviour?: RequestModeInput): Promise<Response>;
|
|
33
78
|
/**
|
|
34
79
|
* Download a file from a URL to a local path.
|
|
35
80
|
*
|
package/dist/public/node/http.js
CHANGED
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
import { dirname } from './path.js';
|
|
3
3
|
import { createFileWriteStream, fileExistsSync, mkdirSync, unlinkFileSync } from './fs.js';
|
|
4
4
|
import { runWithTimer } from './metadata.js';
|
|
5
|
-
import {
|
|
5
|
+
import { maxRequestTimeForNetworkCallsMs, skipNetworkLevelRetry } from './environment.js';
|
|
6
|
+
import { httpsAgent, sanitizedHeadersOutput } from '../../private/node/api/headers.js';
|
|
6
7
|
import { sanitizeURL } from '../../private/node/api/urls.js';
|
|
7
|
-
import { outputContent, outputDebug } from '../../public/node/output.js';
|
|
8
|
+
import { outputContent, outputDebug, outputToken } from '../../public/node/output.js';
|
|
8
9
|
import { simpleRequestWithDebugLog } from '../../private/node/api.js';
|
|
10
|
+
import { DEFAULT_MAX_TIME_MS } from '../../private/node/sleep-with-backoff.js';
|
|
9
11
|
import FormData from 'form-data';
|
|
10
12
|
import nodeFetch from 'node-fetch';
|
|
11
13
|
export { FetchError, Request, Response } from 'node-fetch';
|
|
@@ -17,6 +19,98 @@ export { FetchError, Request, Response } from 'node-fetch';
|
|
|
17
19
|
export function formData() {
|
|
18
20
|
return new FormData();
|
|
19
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Specify the behaviour of a network request.
|
|
24
|
+
*
|
|
25
|
+
* - default: Requests are automatically retried, and are subject to automatic cancellation if they're taking too long.
|
|
26
|
+
* This is generally desirable.
|
|
27
|
+
* - non-blocking: Requests are not retried if they fail with a network error, and are automatically cancelled if
|
|
28
|
+
* they're taking too long. This is good for throwaway requests, like polling or tracking.
|
|
29
|
+
* - slow-request: Requests are not retried if they fail with a network error, and are not automatically cancelled.
|
|
30
|
+
* This is good for slow requests that should be give the chance to complete, and are unlikely to be safe to retry.
|
|
31
|
+
*
|
|
32
|
+
* Some request behaviours may be de-activated by the environment, and this function takes care of that concern. You
|
|
33
|
+
* can also provide a customised request behaviour.
|
|
34
|
+
*
|
|
35
|
+
* @param preset - The preset to use.
|
|
36
|
+
* @param env - Process environment variables.
|
|
37
|
+
* @returns A request behaviour object.
|
|
38
|
+
*/
|
|
39
|
+
export function requestMode(preset = 'default', env = process.env) {
|
|
40
|
+
const networkLevelRetryIsSupported = !skipNetworkLevelRetry(env);
|
|
41
|
+
switch (preset) {
|
|
42
|
+
case 'default':
|
|
43
|
+
return {
|
|
44
|
+
useNetworkLevelRetry: networkLevelRetryIsSupported,
|
|
45
|
+
maxRetryTimeMs: DEFAULT_MAX_TIME_MS,
|
|
46
|
+
useAbortSignal: true,
|
|
47
|
+
timeoutMs: maxRequestTimeForNetworkCallsMs(env),
|
|
48
|
+
};
|
|
49
|
+
case 'non-blocking':
|
|
50
|
+
return {
|
|
51
|
+
useNetworkLevelRetry: false,
|
|
52
|
+
useAbortSignal: true,
|
|
53
|
+
timeoutMs: maxRequestTimeForNetworkCallsMs(env),
|
|
54
|
+
};
|
|
55
|
+
case 'slow-request':
|
|
56
|
+
return {
|
|
57
|
+
useNetworkLevelRetry: false,
|
|
58
|
+
useAbortSignal: false,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
...preset,
|
|
63
|
+
useNetworkLevelRetry: networkLevelRetryIsSupported && preset.useNetworkLevelRetry,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Create an AbortSignal for automatic request cancellation, from a request behaviour.
|
|
68
|
+
*
|
|
69
|
+
* @param behaviour - The request behaviour.
|
|
70
|
+
* @returns An AbortSignal.
|
|
71
|
+
*/
|
|
72
|
+
export function abortSignalFromRequestBehaviour(behaviour) {
|
|
73
|
+
let signal;
|
|
74
|
+
if (behaviour.useAbortSignal === true) {
|
|
75
|
+
signal = AbortSignal.timeout(behaviour.timeoutMs);
|
|
76
|
+
}
|
|
77
|
+
else if (behaviour.useAbortSignal && typeof behaviour.useAbortSignal === 'function') {
|
|
78
|
+
signal = behaviour.useAbortSignal();
|
|
79
|
+
}
|
|
80
|
+
else if (behaviour.useAbortSignal) {
|
|
81
|
+
signal = behaviour.useAbortSignal;
|
|
82
|
+
}
|
|
83
|
+
return signal;
|
|
84
|
+
}
|
|
85
|
+
async function innerFetch({ url, behaviour, init, logRequest, useHttpsAgent }) {
|
|
86
|
+
if (logRequest) {
|
|
87
|
+
outputDebug(outputContent `Sending ${init?.method ?? 'GET'} request to URL ${sanitizeURL(url.toString())}
|
|
88
|
+
With request headers:
|
|
89
|
+
${sanitizedHeadersOutput((init?.headers ?? {}))}
|
|
90
|
+
`);
|
|
91
|
+
}
|
|
92
|
+
let agent;
|
|
93
|
+
if (useHttpsAgent) {
|
|
94
|
+
agent = await httpsAgent();
|
|
95
|
+
}
|
|
96
|
+
const request = async () => {
|
|
97
|
+
// each time we make the request, we need to potentially reset the abort signal, as the request logic may make
|
|
98
|
+
// the same request multiple times.
|
|
99
|
+
let signal = abortSignalFromRequestBehaviour(behaviour);
|
|
100
|
+
// it's possible to provide a signal through the request's init structure.
|
|
101
|
+
if (init?.signal) {
|
|
102
|
+
signal = init.signal;
|
|
103
|
+
}
|
|
104
|
+
return nodeFetch(url, { ...init, agent, signal });
|
|
105
|
+
};
|
|
106
|
+
return runWithTimer('cmd_all_timing_network_ms')(async () => {
|
|
107
|
+
return simpleRequestWithDebugLog({
|
|
108
|
+
url: url.toString(),
|
|
109
|
+
request,
|
|
110
|
+
...behaviour,
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
}
|
|
20
114
|
/**
|
|
21
115
|
* An interface that abstracts way node-fetch. When Node has built-in
|
|
22
116
|
* support for "fetch" in the standard library, we can drop the node-fetch
|
|
@@ -25,41 +119,47 @@ export function formData() {
|
|
|
25
119
|
* they are consistent with the Web API so if we drop node-fetch in the future
|
|
26
120
|
* it won't require changes from the callers.
|
|
27
121
|
*
|
|
122
|
+
* The CLI's fetch function supports special behaviours, like automatic retries. These are disabled by default through
|
|
123
|
+
* this function.
|
|
124
|
+
*
|
|
28
125
|
* @param url - This defines the resource that you wish to fetch.
|
|
29
126
|
* @param init - An object containing any custom settings that you want to apply to the request.
|
|
127
|
+
* @param preferredBehaviour - A request behaviour object that overrides the default behaviour.
|
|
30
128
|
* @returns A promise that resolves with the response.
|
|
31
129
|
*/
|
|
32
|
-
export async function fetch(url, init) {
|
|
33
|
-
|
|
130
|
+
export async function fetch(url, init, preferredBehaviour) {
|
|
131
|
+
const options = {
|
|
132
|
+
url,
|
|
133
|
+
init,
|
|
134
|
+
logRequest: false,
|
|
135
|
+
useHttpsAgent: false,
|
|
136
|
+
// all special behaviours are disabled by default
|
|
137
|
+
behaviour: preferredBehaviour ? requestMode(preferredBehaviour) : requestMode('non-blocking'),
|
|
138
|
+
};
|
|
139
|
+
return innerFetch(options);
|
|
34
140
|
}
|
|
35
141
|
/**
|
|
36
142
|
* A fetch function to use with Shopify services. The function ensures the right
|
|
37
143
|
* TLS configuragion is used based on the environment in which the service is running
|
|
38
|
-
* (e.g. Spin).
|
|
144
|
+
* (e.g. Spin). NB: headers/auth are the responsibility of the caller.
|
|
145
|
+
*
|
|
146
|
+
* By default, the CLI's fetch function's special behaviours, like automatic retries, are enabled.
|
|
39
147
|
*
|
|
40
148
|
* @param url - This defines the resource that you wish to fetch.
|
|
41
149
|
* @param init - An object containing any custom settings that you want to apply to the request.
|
|
150
|
+
* @param preferredBehaviour - A request behaviour object that overrides the default behaviour.
|
|
42
151
|
* @returns A promise that resolves with the response.
|
|
43
152
|
*/
|
|
44
|
-
export async function shopifyFetch(url, init) {
|
|
45
|
-
const sanitizedUrl = sanitizeURL(url.toString());
|
|
153
|
+
export async function shopifyFetch(url, init, preferredBehaviour) {
|
|
46
154
|
const options = {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
155
|
+
url,
|
|
156
|
+
init,
|
|
157
|
+
logRequest: true,
|
|
158
|
+
useHttpsAgent: true,
|
|
159
|
+
// special behaviours enabled by default
|
|
160
|
+
behaviour: preferredBehaviour ? requestMode(preferredBehaviour) : requestMode(),
|
|
52
161
|
};
|
|
53
|
-
|
|
54
|
-
With request headers:
|
|
55
|
-
${sanitizedHeadersOutput((options.headers ?? {}))}
|
|
56
|
-
`);
|
|
57
|
-
return runWithTimer('cmd_all_timing_network_ms')(async () => {
|
|
58
|
-
return simpleRequestWithDebugLog({
|
|
59
|
-
url: url.toString(),
|
|
60
|
-
request: async () => nodeFetch(url, { ...init, agent: await httpsAgent() }),
|
|
61
|
-
});
|
|
62
|
-
});
|
|
162
|
+
return innerFetch(options);
|
|
63
163
|
}
|
|
64
164
|
/**
|
|
65
165
|
* Download a file from a URL to a local path.
|
|
@@ -77,12 +177,22 @@ export function downloadFile(url, to) {
|
|
|
77
177
|
mkdirSync(dirname(to));
|
|
78
178
|
}
|
|
79
179
|
const file = createFileWriteStream(to);
|
|
180
|
+
// if we can't remove the file for some reason (seen on windows), that's ok -- it's in a temporary directory
|
|
181
|
+
const tryToRemoveFile = () => {
|
|
182
|
+
try {
|
|
183
|
+
unlinkFileSync(to);
|
|
184
|
+
// eslint-disable-next-line no-catch-all/no-catch-all, @typescript-eslint/no-explicit-any
|
|
185
|
+
}
|
|
186
|
+
catch (err) {
|
|
187
|
+
outputDebug(outputContent `Failed to remove file ${outputToken.path(to)}: ${err}`);
|
|
188
|
+
}
|
|
189
|
+
};
|
|
80
190
|
file.on('finish', () => {
|
|
81
191
|
file.close();
|
|
82
192
|
resolve(to);
|
|
83
193
|
});
|
|
84
194
|
file.on('error', (err) => {
|
|
85
|
-
|
|
195
|
+
tryToRemoveFile();
|
|
86
196
|
reject(err);
|
|
87
197
|
});
|
|
88
198
|
nodeFetch(url, { redirect: 'follow' })
|
|
@@ -90,7 +200,7 @@ export function downloadFile(url, to) {
|
|
|
90
200
|
res.body?.pipe(file);
|
|
91
201
|
})
|
|
92
202
|
.catch((err) => {
|
|
93
|
-
|
|
203
|
+
tryToRemoveFile();
|
|
94
204
|
reject(err);
|
|
95
205
|
});
|
|
96
206
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/public/node/http.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-base-to-string */\nimport {dirname} from './path.js'\nimport {createFileWriteStream, fileExistsSync, mkdirSync, unlinkFileSync} from './fs.js'\nimport {runWithTimer} from './metadata.js'\nimport {buildHeaders, httpsAgent, sanitizedHeadersOutput} from '../../private/node/api/headers.js'\nimport {sanitizeURL} from '../../private/node/api/urls.js'\nimport {outputContent, outputDebug} from '../../public/node/output.js'\nimport {simpleRequestWithDebugLog} from '../../private/node/api.js'\nimport FormData from 'form-data'\nimport nodeFetch, {RequestInfo, RequestInit, Response} from 'node-fetch'\n\nexport {FetchError, Request, Response} from 'node-fetch'\n\n/**\n * Create a new FormData object.\n *\n * @returns A FormData object.\n */\nexport function formData(): FormData {\n return new FormData()\n}\n\n/**\n * An interface that abstracts way node-fetch. When Node has built-in\n * support for \"fetch\" in the standard library, we can drop the node-fetch\n * dependency from here.\n * Note that we are exposing types from \"node-fetch\". The reason being is that\n * they are consistent with the Web API so if we drop node-fetch in the future\n * it won't require changes from the callers.\n *\n * @param url - This defines the resource that you wish to fetch.\n * @param init - An object containing any custom settings that you want to apply to the request.\n * @returns A promise that resolves with the response.\n */\nexport async function fetch(url: RequestInfo, init?: RequestInit): Promise<Response> {\n return runWithTimer('cmd_all_timing_network_ms')(() =>\n simpleRequestWithDebugLog({url: url.toString(), request: () => nodeFetch(url, init)}),\n )\n}\n\n/**\n * A fetch function to use with Shopify services. The function ensures the right\n * TLS configuragion is used based on the environment in which the service is running\n * (e.g. Spin).\n *\n * @param url - This defines the resource that you wish to fetch.\n * @param init - An object containing any custom settings that you want to apply to the request.\n * @returns A promise that resolves with the response.\n */\nexport async function shopifyFetch(url: RequestInfo, init?: RequestInit): Promise<Response> {\n const sanitizedUrl = sanitizeURL(url.toString())\n const options: RequestInit = {\n ...(init ?? {}),\n headers: {\n ...(await buildHeaders()),\n ...(init?.headers ?? {}),\n },\n }\n\n outputDebug(outputContent`Sending ${options.method ?? 'GET'} request to URL ${sanitizedUrl}\nWith request headers:\n${sanitizedHeadersOutput((options.headers ?? {}) as {[header: string]: string})}\n`)\n return runWithTimer('cmd_all_timing_network_ms')(async () => {\n return simpleRequestWithDebugLog({\n url: url.toString(),\n request: async () => nodeFetch(url, {...init, agent: await httpsAgent()}),\n })\n })\n}\n\n/**\n * Download a file from a URL to a local path.\n *\n * @param url - The URL to download from.\n * @param to - The local path to download to.\n * @returns - A promise that resolves with the local path.\n */\nexport function downloadFile(url: string, to: string): Promise<string> {\n const sanitizedUrl = sanitizeURL(url)\n outputDebug(`Downloading ${sanitizedUrl} to ${to}`)\n\n return runWithTimer('cmd_all_timing_network_ms')(() => {\n return new Promise<string>((resolve, reject) => {\n if (!fileExistsSync(dirname(to))) {\n mkdirSync(dirname(to))\n }\n\n const file = createFileWriteStream(to)\n\n file.on('finish', () => {\n file.close()\n resolve(to)\n })\n\n file.on('error', (err) => {\n unlinkFileSync(to)\n reject(err)\n })\n\n nodeFetch(url, {redirect: 'follow'})\n .then((res) => {\n res.body?.pipe(file)\n })\n .catch((err) => {\n unlinkFileSync(to)\n reject(err)\n })\n })\n })\n}\n"]}
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/public/node/http.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AACjC,OAAO,EAAC,qBAAqB,EAAE,cAAc,EAAE,SAAS,EAAE,cAAc,EAAC,MAAM,SAAS,CAAA;AACxF,OAAO,EAAC,YAAY,EAAC,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAC,+BAA+B,EAAE,qBAAqB,EAAC,MAAM,kBAAkB,CAAA;AACvF,OAAO,EAAC,UAAU,EAAE,sBAAsB,EAAC,MAAM,mCAAmC,CAAA;AACpF,OAAO,EAAC,WAAW,EAAC,MAAM,gCAAgC,CAAA;AAC1D,OAAO,EAAC,aAAa,EAAE,WAAW,EAAE,WAAW,EAAC,MAAM,6BAA6B,CAAA;AACnF,OAAO,EAAwB,yBAAyB,EAAC,MAAM,2BAA2B,CAAA;AAC1F,OAAO,EAAC,mBAAmB,EAAC,MAAM,0CAA0C,CAAA;AAC5E,OAAO,QAAQ,MAAM,WAAW,CAAA;AAChC,OAAO,SAA+C,MAAM,YAAY,CAAA;AAExE,OAAO,EAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAC,MAAM,YAAY,CAAA;AAExD;;;;GAIG;AACH,MAAM,UAAU,QAAQ;IACtB,OAAO,IAAI,QAAQ,EAAE,CAAA;AACvB,CAAC;AAsBD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,WAAW,CACzB,SAA2B,SAAS,EACpC,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,4BAA4B,GAAG,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAA;IAChE,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,SAAS;YACZ,OAAO;gBACL,oBAAoB,EAAE,4BAA4B;gBAClD,cAAc,EAAE,mBAAmB;gBACnC,cAAc,EAAE,IAAI;gBACpB,SAAS,EAAE,+BAA+B,CAAC,GAAG,CAAC;aAChD,CAAA;QACH,KAAK,cAAc;YACjB,OAAO;gBACL,oBAAoB,EAAE,KAAK;gBAC3B,cAAc,EAAE,IAAI;gBACpB,SAAS,EAAE,+BAA+B,CAAC,GAAG,CAAC;aAChD,CAAA;QACH,KAAK,cAAc;YACjB,OAAO;gBACL,oBAAoB,EAAE,KAAK;gBAC3B,cAAc,EAAE,KAAK;aACtB,CAAA;IACL,CAAC;IACD,OAAO;QACL,GAAG,MAAM;QACT,oBAAoB,EAAE,4BAA4B,IAAI,MAAM,CAAC,oBAAoB;KAC9D,CAAA;AACvB,CAAC;AAUD;;;;;GAKG;AACH,MAAM,UAAU,+BAA+B,CAAC,SAA2B;IACzE,IAAI,MAAmB,CAAA;IACvB,IAAI,SAAS,CAAC,cAAc,KAAK,IAAI,EAAE,CAAC;QACtC,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;IACnD,CAAC;SAAM,IAAI,SAAS,CAAC,cAAc,IAAI,OAAO,SAAS,CAAC,cAAc,KAAK,UAAU,EAAE,CAAC;QACtF,MAAM,GAAG,SAAS,CAAC,cAAc,EAAE,CAAA;IACrC,CAAC;SAAM,IAAI,SAAS,CAAC,cAAc,EAAE,CAAC;QACpC,MAAM,GAAG,SAAS,CAAC,cAAc,CAAA;IACnC,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,EAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,aAAa,EAAe;IACvF,IAAI,UAAU,EAAE,CAAC;QACf,WAAW,CAAC,aAAa,CAAA,WAAW,IAAI,EAAE,MAAM,IAAI,KAAK,mBAAmB,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;;EAEzG,sBAAsB,CAAC,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,CAA+B,CAAC;CAC5E,CAAC,CAAA;IACA,CAAC;IAED,IAAI,KAA2B,CAAA;IAC/B,IAAI,aAAa,EAAE,CAAC;QAClB,KAAK,GAAG,MAAM,UAAU,EAAE,CAAA;IAC5B,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,IAAI,EAAE;QACzB,8GAA8G;QAC9G,mCAAmC;QACnC,IAAI,MAAM,GAAG,+BAA+B,CAAC,SAAS,CAAC,CAAA;QAEvD,0EAA0E;QAC1E,IAAI,IAAI,EAAE,MAAM,EAAE,CAAC;YACjB,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;QACtB,CAAC;QAED,OAAO,SAAS,CAAC,GAAG,EAAE,EAAC,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,EAAC,CAAC,CAAA;IACjD,CAAC,CAAA;IAED,OAAO,YAAY,CAAC,2BAA2B,CAAC,CAAC,KAAK,IAAI,EAAE;QAC1D,OAAO,yBAAyB,CAAC;YAC/B,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE;YACnB,OAAO;YACP,GAAG,SAAS;SACb,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CACzB,GAAgB,EAChB,IAAkB,EAClB,kBAAqC;IAErC,MAAM,OAAO,GAAG;QACd,GAAG;QACH,IAAI;QACJ,UAAU,EAAE,KAAK;QACjB,aAAa,EAAE,KAAK;QACpB,iDAAiD;QACjD,SAAS,EAAE,kBAAkB,CAAC,CAAC,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,cAAc,CAAC;KACrF,CAAA;IAEV,OAAO,UAAU,CAAC,OAAO,CAAC,CAAA;AAC5B,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,GAAgB,EAChB,IAAkB,EAClB,kBAAqC;IAErC,MAAM,OAAO,GAAG;QACd,GAAG;QACH,IAAI;QACJ,UAAU,EAAE,IAAI;QAChB,aAAa,EAAE,IAAI;QACnB,wCAAwC;QACxC,SAAS,EAAE,kBAAkB,CAAC,CAAC,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;KAChF,CAAA;IAED,OAAO,UAAU,CAAC,OAAO,CAAC,CAAA;AAC5B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,EAAU;IAClD,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,CAAC,CAAA;IACrC,WAAW,CAAC,eAAe,YAAY,OAAO,EAAE,EAAE,CAAC,CAAA;IAEnD,OAAO,YAAY,CAAC,2BAA2B,CAAC,CAAC,GAAG,EAAE;QACpD,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC7C,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;gBACjC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAA;YACxB,CAAC;YAED,MAAM,IAAI,GAAG,qBAAqB,CAAC,EAAE,CAAC,CAAA;YAEtC,4GAA4G;YAC5G,MAAM,eAAe,GAAG,GAAG,EAAE;gBAC3B,IAAI,CAAC;oBACH,cAAc,CAAC,EAAE,CAAC,CAAA;oBAClB,yFAAyF;gBAC3F,CAAC;gBAAC,OAAO,GAAQ,EAAE,CAAC;oBAClB,WAAW,CAAC,aAAa,CAAA,yBAAyB,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,GAAG,EAAE,CAAC,CAAA;gBACnF,CAAC;YACH,CAAC,CAAA;YAED,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;gBACrB,IAAI,CAAC,KAAK,EAAE,CAAA;gBACZ,OAAO,CAAC,EAAE,CAAC,CAAA;YACb,CAAC,CAAC,CAAA;YAEF,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;gBACvB,eAAe,EAAE,CAAA;gBACjB,MAAM,CAAC,GAAG,CAAC,CAAA;YACb,CAAC,CAAC,CAAA;YAEF,SAAS,CAAC,GAAG,EAAE,EAAC,QAAQ,EAAE,QAAQ,EAAC,CAAC;iBACjC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;gBACZ,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;YACtB,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;gBACb,eAAe,EAAE,CAAA;gBACjB,MAAM,CAAC,GAAG,CAAC,CAAA;YACb,CAAC,CAAC,CAAA;QACN,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC","sourcesContent":["/* eslint-disable @typescript-eslint/no-base-to-string */\nimport {dirname} from './path.js'\nimport {createFileWriteStream, fileExistsSync, mkdirSync, unlinkFileSync} from './fs.js'\nimport {runWithTimer} from './metadata.js'\nimport {maxRequestTimeForNetworkCallsMs, skipNetworkLevelRetry} from './environment.js'\nimport {httpsAgent, sanitizedHeadersOutput} from '../../private/node/api/headers.js'\nimport {sanitizeURL} from '../../private/node/api/urls.js'\nimport {outputContent, outputDebug, outputToken} from '../../public/node/output.js'\nimport {NetworkRetryBehaviour, simpleRequestWithDebugLog} from '../../private/node/api.js'\nimport {DEFAULT_MAX_TIME_MS} from '../../private/node/sleep-with-backoff.js'\nimport FormData from 'form-data'\nimport nodeFetch, {RequestInfo, RequestInit, Response} from 'node-fetch'\n\nexport {FetchError, Request, Response} from 'node-fetch'\n\n/**\n * Create a new FormData object.\n *\n * @returns A FormData object.\n */\nexport function formData(): FormData {\n return new FormData()\n}\n\ntype AbortSignal = RequestInit['signal']\n\ntype PresetFetchBehaviour = 'default' | 'non-blocking' | 'slow-request'\n\ntype AutomaticCancellationBehaviour =\n | {\n useAbortSignal: true\n timeoutMs: number\n }\n | {\n useAbortSignal: false\n }\n | {\n useAbortSignal: AbortSignal | (() => AbortSignal)\n }\n\ntype RequestBehaviour = NetworkRetryBehaviour & AutomaticCancellationBehaviour\n\ntype RequestModeInput = PresetFetchBehaviour | RequestBehaviour\n\n/**\n * Specify the behaviour of a network request.\n *\n * - default: Requests are automatically retried, and are subject to automatic cancellation if they're taking too long.\n * This is generally desirable.\n * - non-blocking: Requests are not retried if they fail with a network error, and are automatically cancelled if\n * they're taking too long. This is good for throwaway requests, like polling or tracking.\n * - slow-request: Requests are not retried if they fail with a network error, and are not automatically cancelled.\n * This is good for slow requests that should be give the chance to complete, and are unlikely to be safe to retry.\n *\n * Some request behaviours may be de-activated by the environment, and this function takes care of that concern. You\n * can also provide a customised request behaviour.\n *\n * @param preset - The preset to use.\n * @param env - Process environment variables.\n * @returns A request behaviour object.\n */\nexport function requestMode(\n preset: RequestModeInput = 'default',\n env: NodeJS.ProcessEnv = process.env,\n): RequestBehaviour {\n const networkLevelRetryIsSupported = !skipNetworkLevelRetry(env)\n switch (preset) {\n case 'default':\n return {\n useNetworkLevelRetry: networkLevelRetryIsSupported,\n maxRetryTimeMs: DEFAULT_MAX_TIME_MS,\n useAbortSignal: true,\n timeoutMs: maxRequestTimeForNetworkCallsMs(env),\n }\n case 'non-blocking':\n return {\n useNetworkLevelRetry: false,\n useAbortSignal: true,\n timeoutMs: maxRequestTimeForNetworkCallsMs(env),\n }\n case 'slow-request':\n return {\n useNetworkLevelRetry: false,\n useAbortSignal: false,\n }\n }\n return {\n ...preset,\n useNetworkLevelRetry: networkLevelRetryIsSupported && preset.useNetworkLevelRetry,\n } as RequestBehaviour\n}\n\ninterface FetchOptions {\n url: RequestInfo\n behaviour: RequestBehaviour\n init?: RequestInit\n logRequest: boolean\n useHttpsAgent: boolean\n}\n\n/**\n * Create an AbortSignal for automatic request cancellation, from a request behaviour.\n *\n * @param behaviour - The request behaviour.\n * @returns An AbortSignal.\n */\nexport function abortSignalFromRequestBehaviour(behaviour: RequestBehaviour): AbortSignal {\n let signal: AbortSignal\n if (behaviour.useAbortSignal === true) {\n signal = AbortSignal.timeout(behaviour.timeoutMs)\n } else if (behaviour.useAbortSignal && typeof behaviour.useAbortSignal === 'function') {\n signal = behaviour.useAbortSignal()\n } else if (behaviour.useAbortSignal) {\n signal = behaviour.useAbortSignal\n }\n return signal\n}\n\nasync function innerFetch({url, behaviour, init, logRequest, useHttpsAgent}: FetchOptions): Promise<Response> {\n if (logRequest) {\n outputDebug(outputContent`Sending ${init?.method ?? 'GET'} request to URL ${sanitizeURL(url.toString())}\nWith request headers:\n${sanitizedHeadersOutput((init?.headers ?? {}) as {[header: string]: string})}\n`)\n }\n\n let agent: RequestInit['agent']\n if (useHttpsAgent) {\n agent = await httpsAgent()\n }\n\n const request = async () => {\n // each time we make the request, we need to potentially reset the abort signal, as the request logic may make\n // the same request multiple times.\n let signal = abortSignalFromRequestBehaviour(behaviour)\n\n // it's possible to provide a signal through the request's init structure.\n if (init?.signal) {\n signal = init.signal\n }\n\n return nodeFetch(url, {...init, agent, signal})\n }\n\n return runWithTimer('cmd_all_timing_network_ms')(async () => {\n return simpleRequestWithDebugLog({\n url: url.toString(),\n request,\n ...behaviour,\n })\n })\n}\n\n/**\n * An interface that abstracts way node-fetch. When Node has built-in\n * support for \"fetch\" in the standard library, we can drop the node-fetch\n * dependency from here.\n * Note that we are exposing types from \"node-fetch\". The reason being is that\n * they are consistent with the Web API so if we drop node-fetch in the future\n * it won't require changes from the callers.\n *\n * The CLI's fetch function supports special behaviours, like automatic retries. These are disabled by default through\n * this function.\n *\n * @param url - This defines the resource that you wish to fetch.\n * @param init - An object containing any custom settings that you want to apply to the request.\n * @param preferredBehaviour - A request behaviour object that overrides the default behaviour.\n * @returns A promise that resolves with the response.\n */\nexport async function fetch(\n url: RequestInfo,\n init?: RequestInit,\n preferredBehaviour?: RequestModeInput,\n): Promise<Response> {\n const options = {\n url,\n init,\n logRequest: false,\n useHttpsAgent: false,\n // all special behaviours are disabled by default\n behaviour: preferredBehaviour ? requestMode(preferredBehaviour) : requestMode('non-blocking'),\n } as const\n\n return innerFetch(options)\n}\n\n/**\n * A fetch function to use with Shopify services. The function ensures the right\n * TLS configuragion is used based on the environment in which the service is running\n * (e.g. Spin). NB: headers/auth are the responsibility of the caller.\n *\n * By default, the CLI's fetch function's special behaviours, like automatic retries, are enabled.\n *\n * @param url - This defines the resource that you wish to fetch.\n * @param init - An object containing any custom settings that you want to apply to the request.\n * @param preferredBehaviour - A request behaviour object that overrides the default behaviour.\n * @returns A promise that resolves with the response.\n */\nexport async function shopifyFetch(\n url: RequestInfo,\n init?: RequestInit,\n preferredBehaviour?: RequestModeInput,\n): Promise<Response> {\n const options = {\n url,\n init,\n logRequest: true,\n useHttpsAgent: true,\n // special behaviours enabled by default\n behaviour: preferredBehaviour ? requestMode(preferredBehaviour) : requestMode(),\n }\n\n return innerFetch(options)\n}\n\n/**\n * Download a file from a URL to a local path.\n *\n * @param url - The URL to download from.\n * @param to - The local path to download to.\n * @returns - A promise that resolves with the local path.\n */\nexport function downloadFile(url: string, to: string): Promise<string> {\n const sanitizedUrl = sanitizeURL(url)\n outputDebug(`Downloading ${sanitizedUrl} to ${to}`)\n\n return runWithTimer('cmd_all_timing_network_ms')(() => {\n return new Promise<string>((resolve, reject) => {\n if (!fileExistsSync(dirname(to))) {\n mkdirSync(dirname(to))\n }\n\n const file = createFileWriteStream(to)\n\n // if we can't remove the file for some reason (seen on windows), that's ok -- it's in a temporary directory\n const tryToRemoveFile = () => {\n try {\n unlinkFileSync(to)\n // eslint-disable-next-line no-catch-all/no-catch-all, @typescript-eslint/no-explicit-any\n } catch (err: any) {\n outputDebug(outputContent`Failed to remove file ${outputToken.path(to)}: ${err}`)\n }\n }\n\n file.on('finish', () => {\n file.close()\n resolve(to)\n })\n\n file.on('error', (err) => {\n tryToRemoveFile()\n reject(err)\n })\n\n nodeFetch(url, {redirect: 'follow'})\n .then((res) => {\n res.body?.pipe(file)\n })\n .catch((err) => {\n tryToRemoveFile()\n reject(err)\n })\n })\n })\n}\n"]}
|
|
@@ -26,7 +26,7 @@ export async function publishMonorailEvent(schemaId, publicData, sensitiveData)
|
|
|
26
26
|
const payload = { ...publicData, ...sensitiveData };
|
|
27
27
|
const body = JSON.stringify({ schema_id: schemaId, payload });
|
|
28
28
|
const headers = buildHeaders(currentTime);
|
|
29
|
-
const response = await fetch(url, { method: 'POST', body, headers });
|
|
29
|
+
const response = await fetch(url, { method: 'POST', body, headers }, 'non-blocking');
|
|
30
30
|
if (response.status === 200) {
|
|
31
31
|
outputDebug(outputContent `Analytics event sent: ${outputToken.json(sanitizePayload(payload))}`);
|
|
32
32
|
return { type: 'ok' };
|