@shopify/cli-kit 3.68.0 → 3.69.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/cli/api/graphql/admin/generated/public_api_versions.d.ts +14 -0
- package/dist/cli/api/graphql/admin/generated/public_api_versions.js +28 -0
- package/dist/cli/api/graphql/admin/generated/public_api_versions.js.map +1 -0
- package/dist/private/node/api/graphql.d.ts +1 -1
- package/dist/private/node/api/graphql.js +1 -0
- package/dist/private/node/api/graphql.js.map +1 -1
- package/dist/private/node/api/headers.js +2 -2
- package/dist/private/node/api/headers.js.map +1 -1
- package/dist/private/node/api/rest.js +3 -1
- package/dist/private/node/api/rest.js.map +1 -1
- package/dist/private/node/api.d.ts +2 -2
- package/dist/private/node/api.js +8 -6
- package/dist/private/node/api.js.map +1 -1
- package/dist/private/node/constants.d.ts +0 -1
- package/dist/private/node/constants.js +0 -1
- package/dist/private/node/constants.js.map +1 -1
- package/dist/private/node/demo-recorder.js +1 -0
- package/dist/private/node/demo-recorder.js.map +1 -1
- package/dist/private/node/session/device-authorization.js +15 -7
- package/dist/private/node/session/device-authorization.js.map +1 -1
- package/dist/private/node/session/exchange.d.ts +0 -8
- package/dist/private/node/session/exchange.js +2 -19
- package/dist/private/node/session/exchange.js.map +1 -1
- package/dist/private/node/session/validate.js +1 -0
- package/dist/private/node/session/validate.js.map +1 -1
- package/dist/private/node/session.d.ts +5 -5
- package/dist/private/node/session.js +4 -12
- package/dist/private/node/session.js.map +1 -1
- package/dist/private/node/testing/ui.js +0 -3
- package/dist/private/node/testing/ui.js.map +1 -1
- package/dist/private/node/themes/generate-theme-name.js +1 -0
- package/dist/private/node/themes/generate-theme-name.js.map +1 -1
- package/dist/private/node/ui/components/AutocompletePrompt.test.js +0 -3
- package/dist/private/node/ui/components/AutocompletePrompt.test.js.map +1 -1
- package/dist/private/node/ui/components/Banner.js +1 -0
- package/dist/private/node/ui/components/Banner.js.map +1 -1
- package/dist/private/node/ui/components/ConcurrentOutput.test.js +7 -7
- package/dist/private/node/ui/components/ConcurrentOutput.test.js.map +1 -1
- package/dist/private/node/ui/components/FatalError.js +1 -0
- package/dist/private/node/ui/components/FatalError.js.map +1 -1
- package/dist/private/node/ui/components/List.js +1 -1
- package/dist/private/node/ui/components/List.js.map +1 -1
- package/dist/private/node/ui/components/Prompts/InfoTable.js +1 -0
- package/dist/private/node/ui/components/Prompts/InfoTable.js.map +1 -1
- package/dist/private/node/ui/components/SelectInput.js +1 -1
- package/dist/private/node/ui/components/SelectInput.js.map +1 -1
- package/dist/private/node/ui/components/SelectPrompt.test.js +0 -4
- package/dist/private/node/ui/components/SelectPrompt.test.js.map +1 -1
- package/dist/private/node/ui/components/Table/Row.js.map +1 -1
- package/dist/private/node/ui/components/Tasks.js +2 -1
- package/dist/private/node/ui/components/Tasks.js.map +1 -1
- package/dist/private/node/ui/components/TextPrompt.d.ts +1 -1
- package/dist/private/node/ui/components/TextPrompt.js.map +1 -1
- package/dist/private/node/ui/components/TokenizedText.js +1 -0
- package/dist/private/node/ui/components/TokenizedText.js.map +1 -1
- package/dist/private/node/ui/hooks/use-abort-signal.js +1 -1
- package/dist/private/node/ui/hooks/use-abort-signal.js.map +1 -1
- package/dist/private/node/ui.js +3 -1
- package/dist/private/node/ui.js.map +1 -1
- package/dist/public/common/array.js +1 -0
- package/dist/public/common/array.js.map +1 -1
- package/dist/public/common/string.js +3 -0
- package/dist/public/common/string.js.map +1 -1
- 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.d.ts +14 -1
- package/dist/public/node/api/admin.js +29 -28
- package/dist/public/node/api/admin.js.map +1 -1
- package/dist/public/node/api/app-management.d.ts +5 -3
- package/dist/public/node/api/app-management.js +16 -11
- package/dist/public/node/api/app-management.js.map +1 -1
- package/dist/public/node/api/graphql.js +13 -1
- package/dist/public/node/api/graphql.js.map +1 -1
- package/dist/public/node/api/rest-api-throttler.js +10 -3
- package/dist/public/node/api/rest-api-throttler.js.map +1 -1
- package/dist/public/node/archiver.js +6 -2
- package/dist/public/node/archiver.js.map +1 -1
- package/dist/public/node/base-command.js +1 -1
- package/dist/public/node/base-command.js.map +1 -1
- package/dist/public/node/context/local.d.ts +0 -9
- package/dist/public/node/context/local.js +0 -13
- package/dist/public/node/context/local.js.map +1 -1
- package/dist/public/node/context/spin.js +1 -1
- package/dist/public/node/context/spin.js.map +1 -1
- package/dist/public/node/custom-oclif-loader.js +5 -4
- package/dist/public/node/custom-oclif-loader.js.map +1 -1
- package/dist/public/node/dot-env.js +2 -1
- package/dist/public/node/dot-env.js.map +1 -1
- package/dist/public/node/environments.js +1 -1
- package/dist/public/node/environments.js.map +1 -1
- package/dist/public/node/error-handler.js +1 -1
- package/dist/public/node/error-handler.js.map +1 -1
- package/dist/public/node/framework.js +5 -4
- package/dist/public/node/framework.js.map +1 -1
- package/dist/public/node/fs.d.ts +2 -1
- package/dist/public/node/fs.js +2 -2
- package/dist/public/node/fs.js.map +1 -1
- package/dist/public/node/git.js +2 -0
- package/dist/public/node/git.js.map +1 -1
- package/dist/public/node/github.js +2 -0
- package/dist/public/node/github.js.map +1 -1
- package/dist/public/node/hooks/deprecations.js +1 -1
- package/dist/public/node/hooks/deprecations.js.map +1 -1
- package/dist/public/node/hooks/postrun.js +2 -1
- package/dist/public/node/hooks/postrun.js.map +1 -1
- package/dist/public/node/hooks/prerun.js +1 -1
- package/dist/public/node/hooks/prerun.js.map +1 -1
- package/dist/public/node/http.js +2 -1
- package/dist/public/node/http.js.map +1 -1
- package/dist/public/node/json-schema.d.ts +1 -1
- package/dist/public/node/json-schema.js.map +1 -1
- package/dist/public/node/liquid.js +12 -2
- package/dist/public/node/liquid.js.map +1 -1
- package/dist/public/node/local-storage.d.ts +1 -1
- package/dist/public/node/local-storage.js.map +1 -1
- package/dist/public/node/metadata.js +1 -0
- package/dist/public/node/metadata.js.map +1 -1
- package/dist/public/node/monorail.d.ts +2 -1
- package/dist/public/node/monorail.js +1 -1
- package/dist/public/node/monorail.js.map +1 -1
- package/dist/public/node/output.js +2 -1
- package/dist/public/node/output.js.map +1 -1
- package/dist/public/node/ruby.js +1 -0
- package/dist/public/node/ruby.js.map +1 -1
- package/dist/public/node/session.d.ts +7 -6
- package/dist/public/node/session.js +2 -1
- package/dist/public/node/session.js.map +1 -1
- package/dist/public/node/system.js +1 -1
- package/dist/public/node/system.js.map +1 -1
- package/dist/public/node/themes/api.js +34 -4
- package/dist/public/node/themes/api.js.map +1 -1
- package/dist/public/node/themes/factories.js +1 -0
- package/dist/public/node/themes/factories.js.map +1 -1
- package/dist/public/node/themes/types.d.ts +2 -3
- package/dist/public/node/themes/types.js.map +1 -1
- package/dist/public/node/themes/urls.d.ts +1 -0
- package/dist/public/node/themes/urls.js +3 -0
- package/dist/public/node/themes/urls.js.map +1 -1
- package/dist/public/node/tree-kill.js +8 -4
- package/dist/public/node/tree-kill.js.map +1 -1
- package/dist/public/node/ui.js +5 -2
- package/dist/public/node/ui.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -5
- package/assets/auth-error.html +0 -23
- package/assets/empty-url.html +0 -23
- package/assets/favicon.svg +0 -26
- package/assets/missing-code.html +0 -23
- package/assets/missing-state.html +0 -23
- package/assets/style.css +0 -58
- package/assets/success.html +0 -20
- package/dist/private/node/session/authorize.d.ts +0 -5
- package/dist/private/node/session/authorize.js +0 -69
- package/dist/private/node/session/authorize.js.map +0 -1
- package/dist/private/node/session/post-auth.d.ts +0 -10
- package/dist/private/node/session/post-auth.js +0 -61
- package/dist/private/node/session/post-auth.js.map +0 -1
- package/dist/private/node/session/redirect-listener.d.ts +0 -34
- package/dist/private/node/session/redirect-listener.js +0 -105
- package/dist/private/node/session/redirect-listener.js.map +0 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as Types from './types.js';
|
|
2
|
+
import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
|
|
3
|
+
export type PublicApiVersionsQueryVariables = Types.Exact<{
|
|
4
|
+
[key: string]: never;
|
|
5
|
+
}>;
|
|
6
|
+
export type PublicApiVersionsQuery = {
|
|
7
|
+
publicApiVersions: {
|
|
8
|
+
handle: string;
|
|
9
|
+
supported: boolean;
|
|
10
|
+
}[];
|
|
11
|
+
};
|
|
12
|
+
export declare const PublicApiVersions: DocumentNode<PublicApiVersionsQuery, Types.Exact<{
|
|
13
|
+
[key: string]: never;
|
|
14
|
+
}>>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export const PublicApiVersions = {
|
|
2
|
+
kind: 'Document',
|
|
3
|
+
definitions: [
|
|
4
|
+
{
|
|
5
|
+
kind: 'OperationDefinition',
|
|
6
|
+
operation: 'query',
|
|
7
|
+
name: { kind: 'Name', value: 'publicApiVersions' },
|
|
8
|
+
selectionSet: {
|
|
9
|
+
kind: 'SelectionSet',
|
|
10
|
+
selections: [
|
|
11
|
+
{
|
|
12
|
+
kind: 'Field',
|
|
13
|
+
name: { kind: 'Name', value: 'publicApiVersions' },
|
|
14
|
+
selectionSet: {
|
|
15
|
+
kind: 'SelectionSet',
|
|
16
|
+
selections: [
|
|
17
|
+
{ kind: 'Field', name: { kind: 'Name', value: 'handle' } },
|
|
18
|
+
{ kind: 'Field', name: { kind: 'Name', value: 'supported' } },
|
|
19
|
+
{ kind: 'Field', name: { kind: 'Name', value: '__typename' } },
|
|
20
|
+
],
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=public_api_versions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public_api_versions.js","sourceRoot":"","sources":["../../../../../../src/cli/api/graphql/admin/generated/public_api_versions.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE;QACX;YACE,IAAI,EAAE,qBAAqB;YAC3B,SAAS,EAAE,OAAO;YAClB,IAAI,EAAE,EAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,EAAC;YAChD,YAAY,EAAE;gBACZ,IAAI,EAAE,cAAc;gBACpB,UAAU,EAAE;oBACV;wBACE,IAAI,EAAE,OAAO;wBACb,IAAI,EAAE,EAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,EAAC;wBAChD,YAAY,EAAE;4BACZ,IAAI,EAAE,cAAc;4BACpB,UAAU,EAAE;gCACV,EAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAC,EAAC;gCACtD,EAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAC,EAAC;gCACzD,EAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAC,EAAC;6BAC3D;yBACF;qBACF;iBACF;aACF;SACF;KACF;CACkF,CAAA","sourcesContent":["/* eslint-disable @typescript-eslint/consistent-type-definitions */\nimport * as Types from './types.js'\n\nimport {TypedDocumentNode as DocumentNode} from '@graphql-typed-document-node/core'\n\nexport type PublicApiVersionsQueryVariables = Types.Exact<{[key: string]: never}>\n\nexport type PublicApiVersionsQuery = {publicApiVersions: {handle: string; supported: boolean}[]}\n\nexport const PublicApiVersions = {\n kind: 'Document',\n definitions: [\n {\n kind: 'OperationDefinition',\n operation: 'query',\n name: {kind: 'Name', value: 'publicApiVersions'},\n selectionSet: {\n kind: 'SelectionSet',\n selections: [\n {\n kind: 'Field',\n name: {kind: 'Name', value: 'publicApiVersions'},\n selectionSet: {\n kind: 'SelectionSet',\n selections: [\n {kind: 'Field', name: {kind: 'Name', value: 'handle'}},\n {kind: 'Field', name: {kind: 'Name', value: 'supported'}},\n {kind: 'Field', name: {kind: 'Name', value: '__typename'}},\n ],\n },\n },\n ],\n },\n },\n ],\n} as unknown as DocumentNode<PublicApiVersionsQuery, PublicApiVersionsQueryVariables>\n"]}
|
|
@@ -2,4 +2,4 @@ import { RequestDocument, Variables } from 'graphql-request';
|
|
|
2
2
|
export declare function debugLogRequestInfo(api: string, query: RequestDocument, variables?: Variables, headers?: {
|
|
3
3
|
[key: string]: string;
|
|
4
4
|
}): void;
|
|
5
|
-
export declare function errorHandler(api: string): (error: unknown, requestId?: string) =>
|
|
5
|
+
export declare function errorHandler(api: string): (error: unknown, requestId?: string) => unknown;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-base-to-string */
|
|
1
2
|
import { GraphQLClientError, sanitizedHeadersOutput } from './headers.js';
|
|
2
3
|
import { stringifyMessage, outputContent, outputToken, outputDebug } from '../../../public/node/output.js';
|
|
3
4
|
import { AbortError } from '../../../public/node/error.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graphql.js","sourceRoot":"","sources":["../../../../src/private/node/api/graphql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,kBAAkB,EAAE,sBAAsB,EAAC,MAAM,cAAc,CAAA;AACvE,OAAO,EAAC,gBAAgB,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAC,MAAM,gCAAgC,CAAA;AACxG,OAAO,EAAC,UAAU,EAAC,MAAM,+BAA+B,CAAA;AACxD,OAAO,EAAC,WAAW,EAA6B,MAAM,iBAAiB,CAAA;AAEvE,MAAM,UAAU,mBAAmB,CACjC,GAAW,EACX,KAAsB,EACtB,SAAqB,EACrB,UAAmC,EAAE;IAErC,WAAW,CAAC,aAAa,CAAA,WAAW,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC;IACvD,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;EAC1C,SAAS,CAAC,CAAC,CAAC,sBAAsB,iBAAiB,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;;EAEvE,sBAAsB,CAAC,OAAO,CAAC;CAChC,CAAC,CAAA;AACF,CAAC;AAED,SAAS,iBAAiB,CAAC,SAAoB;IAC7C,MAAM,MAAM,GAAc,EAAC,GAAG,SAAS,EAAC,CAAA;IACxC,IAAI,QAAQ,IAAI,MAAM,EAAE;QACtB,MAAM,CAAC,MAAM,GAAG,OAAO,CAAA;KACxB;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;AACxC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,OAAO,CAAC,KAAc,EAAE,SAAkB,EAAE,EAAE;QAC5C,IAAI,KAAK,YAAY,WAAW,EAAE;YAChC,MAAM,EAAC,MAAM,EAAC,GAAG,KAAK,CAAC,QAAQ,CAAA;YAC/B,IAAI,YAAY,GAAG,gBAAgB,CAAC,aAAa,CAAA;MACjD,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,6CAClB,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,oBAAoB,MAAM,MAClD;;EAEJ,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;OAClC,CAAC,CAAA;YACF,IAAI,SAAS,EAAE;gBACb,YAAY,IAAI;cACV,SAAS;CACtB,CAAA;aACM;YACD,IAAI,WAAkB,CAAA;YACtB,IAAI,MAAM,GAAG,GAAG,EAAE;gBAChB,WAAW,GAAG,IAAI,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;aAClF;iBAAM;gBACL,WAAW,GAAG,IAAI,UAAU,CAAC,YAAY,CAAC,CAAA;aAC3C;YACD,WAAW,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAA;YAC/B,OAAO,WAAW,CAAA;SACnB;aAAM;YACL,OAAO,KAAK,CAAA;SACb;IACH,CAAC,CAAA;AACH,CAAC","sourcesContent":["
|
|
1
|
+
{"version":3,"file":"graphql.js","sourceRoot":"","sources":["../../../../src/private/node/api/graphql.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,OAAO,EAAC,kBAAkB,EAAE,sBAAsB,EAAC,MAAM,cAAc,CAAA;AACvE,OAAO,EAAC,gBAAgB,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAC,MAAM,gCAAgC,CAAA;AACxG,OAAO,EAAC,UAAU,EAAC,MAAM,+BAA+B,CAAA;AACxD,OAAO,EAAC,WAAW,EAA6B,MAAM,iBAAiB,CAAA;AAEvE,MAAM,UAAU,mBAAmB,CACjC,GAAW,EACX,KAAsB,EACtB,SAAqB,EACrB,UAAmC,EAAE;IAErC,WAAW,CAAC,aAAa,CAAA,WAAW,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC;IACvD,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;EAC1C,SAAS,CAAC,CAAC,CAAC,sBAAsB,iBAAiB,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;;EAEvE,sBAAsB,CAAC,OAAO,CAAC;CAChC,CAAC,CAAA;AACF,CAAC;AAED,SAAS,iBAAiB,CAAC,SAAoB;IAC7C,MAAM,MAAM,GAAc,EAAC,GAAG,SAAS,EAAC,CAAA;IACxC,IAAI,QAAQ,IAAI,MAAM,EAAE;QACtB,MAAM,CAAC,MAAM,GAAG,OAAO,CAAA;KACxB;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;AACxC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,OAAO,CAAC,KAAc,EAAE,SAAkB,EAAE,EAAE;QAC5C,IAAI,KAAK,YAAY,WAAW,EAAE;YAChC,MAAM,EAAC,MAAM,EAAC,GAAG,KAAK,CAAC,QAAQ,CAAA;YAC/B,IAAI,YAAY,GAAG,gBAAgB,CAAC,aAAa,CAAA;MACjD,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,6CAClB,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,oBAAoB,MAAM,MAClD;;EAEJ,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;OAClC,CAAC,CAAA;YACF,IAAI,SAAS,EAAE;gBACb,YAAY,IAAI;cACV,SAAS;CACtB,CAAA;aACM;YACD,IAAI,WAAkB,CAAA;YACtB,IAAI,MAAM,GAAG,GAAG,EAAE;gBAChB,WAAW,GAAG,IAAI,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;aAClF;iBAAM;gBACL,WAAW,GAAG,IAAI,UAAU,CAAC,YAAY,CAAC,CAAA;aAC3C;YACD,WAAW,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAA;YAC/B,OAAO,WAAW,CAAA;SACnB;aAAM;YACL,OAAO,KAAK,CAAA;SACb;IACH,CAAC,CAAA;AACH,CAAC","sourcesContent":["/* eslint-disable @typescript-eslint/no-base-to-string */\nimport {GraphQLClientError, sanitizedHeadersOutput} from './headers.js'\nimport {stringifyMessage, outputContent, outputToken, outputDebug} from '../../../public/node/output.js'\nimport {AbortError} from '../../../public/node/error.js'\nimport {ClientError, RequestDocument, Variables} from 'graphql-request'\n\nexport function debugLogRequestInfo(\n api: string,\n query: RequestDocument,\n variables?: Variables,\n headers: {[key: string]: string} = {},\n) {\n outputDebug(outputContent`Sending ${outputToken.json(api)} GraphQL request:\n ${outputToken.raw(query.toString().trim())}\n${variables ? `\\nWith variables:\\n${sanitizeVariables(variables)}\\n` : ''}\nWith request headers:\n${sanitizedHeadersOutput(headers)}\n`)\n}\n\nfunction sanitizeVariables(variables: Variables): string {\n const result: Variables = {...variables}\n if ('apiKey' in result) {\n result.apiKey = '*****'\n }\n return JSON.stringify(result, null, 2)\n}\n\nexport function errorHandler(api: string): (error: unknown, requestId?: string) => unknown {\n return (error: unknown, requestId?: string) => {\n if (error instanceof ClientError) {\n const {status} = error.response\n let errorMessage = stringifyMessage(outputContent`\nThe ${outputToken.raw(api)} GraphQL API responded unsuccessfully with${\n status === 200 ? '' : ` the HTTP status ${status} and`\n } errors:\n\n${outputToken.json(error.response.errors)}\n `)\n if (requestId) {\n errorMessage += `\nRequest ID: ${requestId}\n`\n }\n let mappedError: Error\n if (status < 500) {\n mappedError = new GraphQLClientError(errorMessage, status, error.response.errors)\n } else {\n mappedError = new AbortError(errorMessage)\n }\n mappedError.stack = error.stack\n return mappedError\n } else {\n return error\n }\n }\n}\n"]}
|
|
@@ -27,6 +27,7 @@ export function sanitizedHeadersOutput(headers) {
|
|
|
27
27
|
const keywords = ['token', 'authorization', 'subject_token'];
|
|
28
28
|
Object.keys(headers).forEach((header) => {
|
|
29
29
|
if (keywords.find((keyword) => header.toLocaleLowerCase().includes(keyword)) === undefined) {
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
30
31
|
sanitized[header] = headers[header];
|
|
31
32
|
}
|
|
32
33
|
});
|
|
@@ -48,8 +49,7 @@ export function buildHeaders(token) {
|
|
|
48
49
|
};
|
|
49
50
|
if (token) {
|
|
50
51
|
const authString = token.match(/^shp(at|ua|ca)/) ? token : `Bearer ${token}`;
|
|
51
|
-
|
|
52
|
-
headers['authorization'] = authString;
|
|
52
|
+
headers.authorization = authString;
|
|
53
53
|
headers['X-Shopify-Access-Token'] = authString;
|
|
54
54
|
}
|
|
55
55
|
return headers;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headers.js","sourceRoot":"","sources":["../../../../src/private/node/api/headers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,mCAAmC,CAAA;AACjE,OAAO,EAAC,aAAa,EAAC,MAAM,uCAAuC,CAAA;AACnE,OAAO,EAAC,WAAW,EAAE,kBAAkB,EAAC,MAAM,uBAAuB,CAAA;AACrE,OAAO,EAAC,eAAe,EAAC,MAAM,+BAA+B,CAAA;AAC7D,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,MAAM,OAAO,kBAAmB,SAAQ,eAAe;IAErD,YAAmB,OAAe,EAAE,UAAkB;QACpD,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;IAC9B,CAAC;CACF;AACD,MAAM,OAAO,kBAAmB,SAAQ,kBAAkB;IAIxD,8DAA8D;IAC9D,YAAmB,OAAe,EAAE,UAAkB,EAAE,MAAc;QACpE,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;QAC1B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,KAAK,GAAG,SAAS,CAAA;IACxB,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAgC;IACrE,MAAM,SAAS,GAA4B,EAAE,CAAA;IAC7C,MAAM,QAAQ,GAAG,CAAC,OAAO,EAAE,eAAe,EAAE,eAAe,CAAC,CAAA;IAC5D,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;QACtC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,SAAS,EAAE;YAC1F,SAAS,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAE,CAAA;SACrC;IACH,CAAC,CAAC,CAAA;IACF,OAAO,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;SAC1B,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;QACd,OAAO,MAAM,MAAM,KAAK,SAAS,CAAC,MAAM,CAAC,EAAE,CAAA;IAC7C,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAA;AACf,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,MAAM,SAAS,GAAG,kBAAkB,eAAe,EAAE,CAAA;IAErD,MAAM,OAAO,GAA+B;QAC1C,YAAY,EAAE,SAAS;QACvB,YAAY,EAAE,YAAY;QAC1B,0DAA0D;QAC1D,oBAAoB,EAAE,OAAO,CAAC,QAAQ;QACtC,cAAc,EAAE,kBAAkB;QAClC,GAAG,CAAC,aAAa,EAAE,IAAI,EAAC,wBAAwB,EAAE,GAAG,EAAC,CAAC;KACxD,CAAA;IACD,IAAI,KAAK,EAAE;QACT,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,KAAK,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"headers.js","sourceRoot":"","sources":["../../../../src/private/node/api/headers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,mCAAmC,CAAA;AACjE,OAAO,EAAC,aAAa,EAAC,MAAM,uCAAuC,CAAA;AACnE,OAAO,EAAC,WAAW,EAAE,kBAAkB,EAAC,MAAM,uBAAuB,CAAA;AACrE,OAAO,EAAC,eAAe,EAAC,MAAM,+BAA+B,CAAA;AAC7D,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,MAAM,OAAO,kBAAmB,SAAQ,eAAe;IAErD,YAAmB,OAAe,EAAE,UAAkB;QACpD,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;IAC9B,CAAC;CACF;AACD,MAAM,OAAO,kBAAmB,SAAQ,kBAAkB;IAIxD,8DAA8D;IAC9D,YAAmB,OAAe,EAAE,UAAkB,EAAE,MAAc;QACpE,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;QAC1B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,KAAK,GAAG,SAAS,CAAA;IACxB,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAgC;IACrE,MAAM,SAAS,GAA4B,EAAE,CAAA;IAC7C,MAAM,QAAQ,GAAG,CAAC,OAAO,EAAE,eAAe,EAAE,eAAe,CAAC,CAAA;IAC5D,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;QACtC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,SAAS,EAAE;YAC1F,oEAAoE;YACpE,SAAS,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAE,CAAA;SACrC;IACH,CAAC,CAAC,CAAA;IACF,OAAO,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;SAC1B,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;QACd,OAAO,MAAM,MAAM,KAAK,SAAS,CAAC,MAAM,CAAC,EAAE,CAAA;IAC7C,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAA;AACf,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,MAAM,SAAS,GAAG,kBAAkB,eAAe,EAAE,CAAA;IAErD,MAAM,OAAO,GAA+B;QAC1C,YAAY,EAAE,SAAS;QACvB,YAAY,EAAE,YAAY;QAC1B,0DAA0D;QAC1D,oBAAoB,EAAE,OAAO,CAAC,QAAQ;QACtC,cAAc,EAAE,kBAAkB;QAClC,GAAG,CAAC,aAAa,EAAE,IAAI,EAAC,wBAAwB,EAAE,GAAG,EAAC,CAAC;KACxD,CAAA;IACD,IAAI,KAAK,EAAE;QACT,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,KAAK,EAAE,CAAA;QAE5E,OAAO,CAAC,aAAa,GAAG,UAAU,CAAA;QAClC,OAAO,CAAC,wBAAwB,CAAC,GAAG,UAAU,CAAA;KAC/C;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC;QACrB,kBAAkB,EAAE,MAAM,gCAAgC,EAAE;QAC5D,SAAS,EAAE,IAAI;KAChB,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,KAAK,UAAU,gCAAgC;IAC7C,OAAO,CAAC,MAAM,kBAAkB,EAAE,CAAC,KAAK,WAAW,CAAC,IAAI,CAAA;AAC1D,CAAC","sourcesContent":["import {CLI_KIT_VERSION} from '../../../public/common/version.js'\nimport {firstPartyDev} from '../../../public/node/context/local.js'\nimport {Environment, serviceEnvironment} from '../context/service.js'\nimport {ExtendableError} from '../../../public/node/error.js'\nimport https from 'https'\n\nexport class RequestClientError extends ExtendableError {\n statusCode: number\n public constructor(message: string, statusCode: number) {\n super(message)\n this.statusCode = statusCode\n }\n}\nexport class GraphQLClientError extends RequestClientError {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n errors?: any[]\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n public constructor(message: string, statusCode: number, errors?: any[]) {\n super(message, statusCode)\n this.errors = errors\n this.stack = undefined\n }\n}\n\n/**\n * Removes the sensitive data from the headers and outputs them as a string.\n * @param headers - HTTP headers.\n * @returns A sanitized version of the headers as a string.\n */\nexport function sanitizedHeadersOutput(headers: {[key: string]: string}): string {\n const sanitized: {[key: string]: string} = {}\n const keywords = ['token', 'authorization', 'subject_token']\n Object.keys(headers).forEach((header) => {\n if (keywords.find((keyword) => header.toLocaleLowerCase().includes(keyword)) === undefined) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n sanitized[header] = headers[header]!\n }\n })\n return Object.keys(sanitized)\n .map((header) => {\n return ` - ${header}: ${sanitized[header]}`\n })\n .join('\\n')\n}\n\nexport function buildHeaders(token?: string): {[key: string]: string} {\n const userAgent = `Shopify CLI; v=${CLI_KIT_VERSION}`\n\n const headers: {[header: string]: string} = {\n 'User-Agent': userAgent,\n 'Keep-Alive': 'timeout=30',\n // 'Sec-CH-UA': secCHUA, This header requires the Git sha.\n 'Sec-CH-UA-PLATFORM': process.platform,\n 'Content-Type': 'application/json',\n ...(firstPartyDev() && {'X-Shopify-Cli-Employee': '1'}),\n }\n if (token) {\n const authString = token.match(/^shp(at|ua|ca)/) ? token : `Bearer ${token}`\n\n headers.authorization = authString\n headers['X-Shopify-Access-Token'] = authString\n }\n\n return headers\n}\n\n/**\n * This utility function returns the https.Agent to use for a given service. The agent\n * includes the right configuration based on the service's environment. For example,\n * if the service is running in a Spin environment, the attribute \"rejectUnauthorized\" is\n * set to false\n */\nexport async function httpsAgent(): Promise<https.Agent> {\n return new https.Agent({\n rejectUnauthorized: await shouldRejectUnauthorizedRequests(),\n keepAlive: true,\n })\n}\n\n/**\n * Spin stores the CA certificate in the keychain and it should be used when sending HTTP\n * requests to Spin instances. However, Node doesn't read certificates from the Keychain\n * by default, which leads to Shopifolks running into issues that they workaround by setting the\n * NODE_TLS_REJECT_UNAUTHORIZED=0 environment variable, which applies to all the HTTP\n * requests sent from the CLI (context: https://github.com/nodejs/node/issues/39657)\n * This utility function allows controlling the behavior in a per-service level by returning\n * the value of for the \"rejectUnauthorized\" attribute that's used in the https agent.\n *\n * @returns A promise that resolves with a boolean indicating whether\n * unauthorized requests should be rejected or not.\n */\nasync function shouldRejectUnauthorizedRequests(): Promise<boolean> {\n return (await serviceEnvironment()) !== Environment.Spin\n}\n"]}
|
|
@@ -11,7 +11,9 @@ export function restRequestUrl(session, apiVersion, path, searchParams = {}, env
|
|
|
11
11
|
const url = new URL(isThemeAccessSession(session)
|
|
12
12
|
? `https://${themeKitAccessDomain}/cli/admin/api/${apiVersion}${path}.json`
|
|
13
13
|
: `https://${session.storeFqdn}/admin/api/${apiVersion}${path}.json`);
|
|
14
|
-
Object.entries(searchParams).forEach(([name, value]) =>
|
|
14
|
+
Object.entries(searchParams).forEach(([name, value]) => {
|
|
15
|
+
url.searchParams.set(name, value);
|
|
16
|
+
});
|
|
15
17
|
return url.toString();
|
|
16
18
|
}
|
|
17
19
|
export function restRequestHeaders(session) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rest.js","sourceRoot":"","sources":["../../../../src/private/node/api/rest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,cAAc,CAAA;AACzC,OAAO,EAAC,2BAA2B,EAAE,oBAAoB,EAAC,MAAM,iBAAiB,CAAA;AAGjF,MAAM,UAAU,eAAe,CAAI,WAAe;IAChD,IAAI,CAAC,WAAW,EAAE;QAChB,OAAM;KACP;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;AACpC,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,OAAqB,EACrB,UAAkB,EAClB,IAAY,EACZ,eAAyC,EAAE,EAC3C,GAAG,GAAG,OAAO,CAAC,GAAG;IAEjB,MAAM,oBAAoB,GAAG,GAAG,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,IAAI,2BAA2B,CAAA;IAC1G,MAAM,GAAG,GAAG,IAAI,GAAG,CACjB,oBAAoB,CAAC,OAAO,CAAC;QAC3B,CAAC,CAAC,WAAW,oBAAoB,kBAAkB,UAAU,GAAG,IAAI,OAAO;QAC3E,CAAC,CAAC,WAAW,OAAO,CAAC,SAAS,cAAc,UAAU,GAAG,IAAI,OAAO,CACvE,CAAA;IACD,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"rest.js","sourceRoot":"","sources":["../../../../src/private/node/api/rest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,cAAc,CAAA;AACzC,OAAO,EAAC,2BAA2B,EAAE,oBAAoB,EAAC,MAAM,iBAAiB,CAAA;AAGjF,MAAM,UAAU,eAAe,CAAI,WAAe;IAChD,IAAI,CAAC,WAAW,EAAE;QAChB,OAAM;KACP;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;AACpC,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,OAAqB,EACrB,UAAkB,EAClB,IAAY,EACZ,eAAyC,EAAE,EAC3C,GAAG,GAAG,OAAO,CAAC,GAAG;IAEjB,MAAM,oBAAoB,GAAG,GAAG,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,IAAI,2BAA2B,CAAA;IAC1G,MAAM,GAAG,GAAG,IAAI,GAAG,CACjB,oBAAoB,CAAC,OAAO,CAAC;QAC3B,CAAC,CAAC,WAAW,oBAAoB,kBAAkB,UAAU,GAAG,IAAI,OAAO;QAC3E,CAAC,CAAC,WAAW,OAAO,CAAC,SAAS,cAAc,UAAU,GAAG,IAAI,OAAO,CACvE,CAAA;IACD,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE;QACrD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IACnC,CAAC,CAAC,CAAA;IAEF,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAA;AACvB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAqB;IACtD,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAA;IAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAA;IAC3B,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IAE3C,IAAI,oBAAoB,CAAC,OAAO,CAAC,EAAE;QACjC,OAAO,CAAC,gBAAgB,CAAC,GAAG,KAAK,CAAA;QACjC,OAAO,CAAC,wBAAwB,CAAC,GAAG,KAAK,CAAA;KAC1C;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,OAAqB;IACxD,OAAO,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAA;AAC5C,CAAC","sourcesContent":["import {buildHeaders} from './headers.js'\nimport {defaultThemeKitAccessDomain, environmentVariables} from '../constants.js'\nimport {AdminSession} from '@shopify/cli-kit/node/session'\n\nexport function restRequestBody<T>(requestBody?: T) {\n if (!requestBody) {\n return\n }\n return JSON.stringify(requestBody)\n}\n\nexport function restRequestUrl(\n session: AdminSession,\n apiVersion: string,\n path: string,\n searchParams: {[name: string]: string} = {},\n env = process.env,\n) {\n const themeKitAccessDomain = env[environmentVariables.themeKitAccessDomain] || defaultThemeKitAccessDomain\n const url = new URL(\n isThemeAccessSession(session)\n ? `https://${themeKitAccessDomain}/cli/admin/api/${apiVersion}${path}.json`\n : `https://${session.storeFqdn}/admin/api/${apiVersion}${path}.json`,\n )\n Object.entries(searchParams).forEach(([name, value]) => {\n url.searchParams.set(name, value)\n })\n\n return url.toString()\n}\n\nexport function restRequestHeaders(session: AdminSession) {\n const store = session.storeFqdn\n const token = session.token\n const headers = buildHeaders(session.token)\n\n if (isThemeAccessSession(session)) {\n headers['X-Shopify-Shop'] = store\n headers['X-Shopify-Access-Token'] = token\n }\n\n return headers\n}\n\nexport function isThemeAccessSession(session: AdminSession) {\n return session.token.startsWith('shptka_')\n}\n"]}
|
|
@@ -8,11 +8,11 @@ interface RequestOptions<T> {
|
|
|
8
8
|
export declare function simpleRequestWithDebugLog<T extends {
|
|
9
9
|
headers: Headers;
|
|
10
10
|
status: number;
|
|
11
|
-
}>({ request, url }: RequestOptions<T>, errorHandler?: (error: unknown, requestId: string | undefined) =>
|
|
11
|
+
}>({ request, url }: RequestOptions<T>, errorHandler?: (error: unknown, requestId: string | undefined) => unknown): Promise<T>;
|
|
12
12
|
export declare function retryAwareRequest<T extends {
|
|
13
13
|
headers: Headers;
|
|
14
14
|
status: number;
|
|
15
|
-
}>({ request, url }: RequestOptions<T>, errorHandler?: (error: unknown, requestId: string | undefined) =>
|
|
15
|
+
}>({ request, url }: RequestOptions<T>, errorHandler?: (error: unknown, requestId: string | undefined) => unknown, retryOptions?: {
|
|
16
16
|
limitRetriesTo?: number;
|
|
17
17
|
defaultDelayMs?: number;
|
|
18
18
|
scheduleDelay: (fn: () => void, delay: number) => void;
|
package/dist/private/node/api.js
CHANGED
|
@@ -36,14 +36,14 @@ async function makeVerboseRequest({ request, url, }) {
|
|
|
36
36
|
const t1 = performance.now();
|
|
37
37
|
duration = Math.round(t1 - t0);
|
|
38
38
|
if (err instanceof ClientError) {
|
|
39
|
-
if (err.response
|
|
40
|
-
for (const [key, value] of err.response
|
|
39
|
+
if (err.response.headers) {
|
|
40
|
+
for (const [key, value] of err.response.headers) {
|
|
41
41
|
if (responseHeaderIsInteresting(key))
|
|
42
42
|
responseHeaders[key] = value;
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
const sanitizedHeaders = sanitizedHeadersOutput(responseHeaders);
|
|
46
|
-
if (err.response.errors?.some((error) => error.extensions
|
|
46
|
+
if (err.response.errors?.some((error) => error.extensions.code === '429') || err.response.status === 429) {
|
|
47
47
|
let delayMs;
|
|
48
48
|
try {
|
|
49
49
|
delayMs = responseHeaders['retry-after'] ? Number.parseInt(responseHeaders['retry-after'], 10) : undefined;
|
|
@@ -174,9 +174,11 @@ ${result.sanitizedHeaders}
|
|
|
174
174
|
const retryDelayMs = result.delayMs ?? retryOptions.defaultDelayMs ?? DEFAULT_RETRY_DELAY_MS;
|
|
175
175
|
outputDebug(`Scheduling retry request #${retriesUsed} to ${result.sanitizedUrl} in ${retryDelayMs} ms`);
|
|
176
176
|
// eslint-disable-next-line no-await-in-loop
|
|
177
|
-
result = await new Promise((resolve) =>
|
|
178
|
-
|
|
179
|
-
|
|
177
|
+
result = await new Promise((resolve) => {
|
|
178
|
+
retryOptions.scheduleDelay(() => {
|
|
179
|
+
resolve(makeVerboseRequest({ request, url }));
|
|
180
|
+
}, retryDelayMs);
|
|
181
|
+
});
|
|
180
182
|
}
|
|
181
183
|
}
|
|
182
184
|
//# sourceMappingURL=api.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/private/node/api.ts"],"names":[],"mappings":"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","sourcesContent":["import {sanitizedHeadersOutput} from './api/headers.js'\nimport {sanitizeURL} from './api/urls.js'\nimport {outputDebug} from '@shopify/cli-kit/node/output'\nimport {Headers} from 'form-data'\nimport {ClientError} from 'graphql-request'\nimport {performance} from 'perf_hooks'\n\nexport type API = 'admin' | 'storefront-renderer' | 'partners' | 'business-platform' | 'app-management'\n\nexport const allAPIs: API[] = ['admin', 'storefront-renderer', 'partners', 'business-platform', 'app-management']\n\nconst DEFAULT_RETRY_DELAY_MS = 1000\nconst DEFAULT_RETRY_LIMIT = 10\n\ninterface RequestOptions<T> {\n request: () => Promise<T>\n url: string\n}\n\nconst interestingResponseHeaders = new Set([\n 'cache-control',\n 'content-type',\n 'etag',\n 'x-request-id',\n 'server-timing',\n 'retry-after',\n])\n\nfunction responseHeaderIsInteresting(header: string): boolean {\n return interestingResponseHeaders.has(header)\n}\n\ntype VerboseResponse<T> = {\n duration: number\n sanitizedHeaders: string\n sanitizedUrl: string\n requestId?: string\n} & (\n | {status: 'ok'; response: T}\n | {status: 'client-error'; clientError: ClientError}\n | {status: 'unknown-error'; error: unknown}\n | {status: 'can-retry'; clientError: ClientError; delayMs: number | undefined}\n)\n\nasync function makeVerboseRequest<T extends {headers: Headers; status: number}>({\n request,\n url,\n}: RequestOptions<T>): Promise<VerboseResponse<T>> {\n const t0 = performance.now()\n let duration = 0\n const responseHeaders: {[key: string]: string} = {}\n const sanitizedUrl = sanitizeURL(url)\n let response: T = {} as T\n try {\n response = await request()\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n response.headers.forEach((value: any, key: any) => {\n if (responseHeaderIsInteresting(key)) responseHeaders[key] = value\n })\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (err) {\n const t1 = performance.now()\n duration = Math.round(t1 - t0)\n\n if (err instanceof ClientError) {\n if (err.response?.headers) {\n for (const [key, value] of err.response?.headers as Iterable<[string, string]>) {\n if (responseHeaderIsInteresting(key)) responseHeaders[key] = value\n }\n }\n const sanitizedHeaders = sanitizedHeadersOutput(responseHeaders)\n\n if (err.response.errors?.some((error) => error.extensions?.code === '429') || err.response.status === 429) {\n let delayMs: number | undefined\n\n try {\n delayMs = responseHeaders['retry-after'] ? Number.parseInt(responseHeaders['retry-after'], 10) : undefined\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch {\n // ignore errors in extracting retry-after header\n }\n return {\n status: 'can-retry',\n clientError: err,\n duration,\n sanitizedHeaders,\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n delayMs,\n }\n }\n\n return {\n status: 'client-error',\n clientError: err,\n duration,\n sanitizedHeaders,\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n }\n }\n return {\n status: 'unknown-error',\n error: err,\n duration,\n sanitizedHeaders: sanitizedHeadersOutput(responseHeaders),\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n }\n }\n const t1 = performance.now()\n duration = Math.round(t1 - t0)\n return {\n status: 'ok',\n response,\n duration,\n sanitizedHeaders: sanitizedHeadersOutput(responseHeaders),\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n }\n}\n\nexport async function simpleRequestWithDebugLog<T extends {headers: Headers; status: number}>(\n {request, url}: RequestOptions<T>,\n errorHandler?: (error: unknown, requestId: string | undefined) => Error | unknown,\n): Promise<T> {\n const result = await makeVerboseRequest({request, url})\n\n outputDebug(`Request to ${result.sanitizedUrl} completed in ${result.duration} ms\nWith response headers:\n${result.sanitizedHeaders}\n `)\n\n switch (result.status) {\n case 'ok': {\n return result.response\n }\n case 'client-error': {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n case 'unknown-error': {\n if (errorHandler) {\n throw errorHandler(result.error, result.requestId)\n } else {\n throw result.error\n }\n }\n case 'can-retry': {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n }\n}\n\nexport async function retryAwareRequest<T extends {headers: Headers; status: number}>(\n {request, url}: RequestOptions<T>,\n errorHandler?: (error: unknown, requestId: string | undefined) => Error | unknown,\n retryOptions: {\n limitRetriesTo?: number\n defaultDelayMs?: number\n scheduleDelay: (fn: () => void, delay: number) => void\n } = {\n scheduleDelay: setTimeout,\n },\n): Promise<T> {\n let retriesUsed = 0\n const limitRetriesTo = retryOptions.limitRetriesTo ?? DEFAULT_RETRY_LIMIT\n\n let result = await makeVerboseRequest({request, url})\n\n outputDebug(`Request to ${result.sanitizedUrl} completed in ${result.duration} ms\nWith response headers:\n${result.sanitizedHeaders}\n `)\n\n while (true) {\n if (result.status === 'ok') {\n if (retriesUsed > 0) {\n outputDebug(`Request to ${result.sanitizedUrl} succeeded after ${retriesUsed} retries`)\n }\n return result.response\n } else if (result.status === 'client-error') {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n } else if (result.status === 'unknown-error') {\n if (errorHandler) {\n throw errorHandler(result.error, result.requestId)\n } else {\n throw result.error\n }\n }\n\n if (limitRetriesTo <= retriesUsed) {\n outputDebug(`${limitRetriesTo} retries exhausted for request to ${result.sanitizedUrl}`)\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n retriesUsed += 1\n\n // prefer to wait based on a header if given; the caller's preference if not; and a default if neither.\n const retryDelayMs = result.delayMs ?? retryOptions.defaultDelayMs ?? DEFAULT_RETRY_DELAY_MS\n outputDebug(`Scheduling retry request #${retriesUsed} to ${result.sanitizedUrl} in ${retryDelayMs} ms`)\n\n // eslint-disable-next-line no-await-in-loop\n result = await new Promise<VerboseResponse<T>>((resolve) =>\n retryOptions.scheduleDelay(() => {\n resolve(makeVerboseRequest({request, url}))\n }, retryDelayMs),\n )\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/private/node/api.ts"],"names":[],"mappings":"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","sourcesContent":["import {sanitizedHeadersOutput} from './api/headers.js'\nimport {sanitizeURL} from './api/urls.js'\nimport {outputDebug} from '@shopify/cli-kit/node/output'\nimport {Headers} from 'form-data'\nimport {ClientError} from 'graphql-request'\nimport {performance} from 'perf_hooks'\n\nexport type API = 'admin' | 'storefront-renderer' | 'partners' | 'business-platform' | 'app-management'\n\nexport const allAPIs: API[] = ['admin', 'storefront-renderer', 'partners', 'business-platform', 'app-management']\n\nconst DEFAULT_RETRY_DELAY_MS = 1000\nconst DEFAULT_RETRY_LIMIT = 10\n\ninterface RequestOptions<T> {\n request: () => Promise<T>\n url: string\n}\n\nconst interestingResponseHeaders = new Set([\n 'cache-control',\n 'content-type',\n 'etag',\n 'x-request-id',\n 'server-timing',\n 'retry-after',\n])\n\nfunction responseHeaderIsInteresting(header: string): boolean {\n return interestingResponseHeaders.has(header)\n}\n\ntype VerboseResponse<T> = {\n duration: number\n sanitizedHeaders: string\n sanitizedUrl: string\n requestId?: string\n} & (\n | {status: 'ok'; response: T}\n | {status: 'client-error'; clientError: ClientError}\n | {status: 'unknown-error'; error: unknown}\n | {status: 'can-retry'; clientError: ClientError; delayMs: number | undefined}\n)\n\nasync function makeVerboseRequest<T extends {headers: Headers; status: number}>({\n request,\n url,\n}: RequestOptions<T>): Promise<VerboseResponse<T>> {\n const t0 = performance.now()\n let duration = 0\n const responseHeaders: {[key: string]: string} = {}\n const sanitizedUrl = sanitizeURL(url)\n let response: T = {} as T\n try {\n response = await request()\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n response.headers.forEach((value: any, key: any) => {\n if (responseHeaderIsInteresting(key)) responseHeaders[key] = value\n })\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (err) {\n const t1 = performance.now()\n duration = Math.round(t1 - t0)\n\n if (err instanceof ClientError) {\n if (err.response.headers) {\n for (const [key, value] of err.response.headers as Iterable<[string, string]>) {\n if (responseHeaderIsInteresting(key)) responseHeaders[key] = value\n }\n }\n const sanitizedHeaders = sanitizedHeadersOutput(responseHeaders)\n\n if (err.response.errors?.some((error) => error.extensions.code === '429') || err.response.status === 429) {\n let delayMs: number | undefined\n\n try {\n delayMs = responseHeaders['retry-after'] ? Number.parseInt(responseHeaders['retry-after'], 10) : undefined\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch {\n // ignore errors in extracting retry-after header\n }\n return {\n status: 'can-retry',\n clientError: err,\n duration,\n sanitizedHeaders,\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n delayMs,\n }\n }\n\n return {\n status: 'client-error',\n clientError: err,\n duration,\n sanitizedHeaders,\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n }\n }\n return {\n status: 'unknown-error',\n error: err,\n duration,\n sanitizedHeaders: sanitizedHeadersOutput(responseHeaders),\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n }\n }\n const t1 = performance.now()\n duration = Math.round(t1 - t0)\n return {\n status: 'ok',\n response,\n duration,\n sanitizedHeaders: sanitizedHeadersOutput(responseHeaders),\n sanitizedUrl,\n requestId: responseHeaders['x-request-id'],\n }\n}\n\nexport async function simpleRequestWithDebugLog<T extends {headers: Headers; status: number}>(\n {request, url}: RequestOptions<T>,\n errorHandler?: (error: unknown, requestId: string | undefined) => unknown,\n): Promise<T> {\n const result = await makeVerboseRequest({request, url})\n\n outputDebug(`Request to ${result.sanitizedUrl} completed in ${result.duration} ms\nWith response headers:\n${result.sanitizedHeaders}\n `)\n\n switch (result.status) {\n case 'ok': {\n return result.response\n }\n case 'client-error': {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n case 'unknown-error': {\n if (errorHandler) {\n throw errorHandler(result.error, result.requestId)\n } else {\n throw result.error\n }\n }\n case 'can-retry': {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n }\n}\n\nexport async function retryAwareRequest<T extends {headers: Headers; status: number}>(\n {request, url}: RequestOptions<T>,\n errorHandler?: (error: unknown, requestId: string | undefined) => unknown,\n retryOptions: {\n limitRetriesTo?: number\n defaultDelayMs?: number\n scheduleDelay: (fn: () => void, delay: number) => void\n } = {\n scheduleDelay: setTimeout,\n },\n): Promise<T> {\n let retriesUsed = 0\n const limitRetriesTo = retryOptions.limitRetriesTo ?? DEFAULT_RETRY_LIMIT\n\n let result = await makeVerboseRequest({request, url})\n\n outputDebug(`Request to ${result.sanitizedUrl} completed in ${result.duration} ms\nWith response headers:\n${result.sanitizedHeaders}\n `)\n\n while (true) {\n if (result.status === 'ok') {\n if (retriesUsed > 0) {\n outputDebug(`Request to ${result.sanitizedUrl} succeeded after ${retriesUsed} retries`)\n }\n return result.response\n } else if (result.status === 'client-error') {\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n } else if (result.status === 'unknown-error') {\n if (errorHandler) {\n throw errorHandler(result.error, result.requestId)\n } else {\n throw result.error\n }\n }\n\n if (limitRetriesTo <= retriesUsed) {\n outputDebug(`${limitRetriesTo} retries exhausted for request to ${result.sanitizedUrl}`)\n if (errorHandler) {\n throw errorHandler(result.clientError, result.requestId)\n } else {\n throw result.clientError\n }\n }\n retriesUsed += 1\n\n // prefer to wait based on a header if given; the caller's preference if not; and a default if neither.\n const retryDelayMs = result.delayMs ?? retryOptions.defaultDelayMs ?? DEFAULT_RETRY_DELAY_MS\n outputDebug(`Scheduling retry request #${retriesUsed} to ${result.sanitizedUrl} in ${retryDelayMs} ms`)\n\n // eslint-disable-next-line no-await-in-loop\n result = await new Promise<VerboseResponse<T>>((resolve) => {\n retryOptions.scheduleDelay(() => {\n resolve(makeVerboseRequest({request, url}))\n }, retryDelayMs)\n })\n }\n}\n"]}
|
|
@@ -13,7 +13,6 @@ export const environmentVariables = {
|
|
|
13
13
|
alwaysLogAnalytics: 'SHOPIFY_CLI_ALWAYS_LOG_ANALYTICS',
|
|
14
14
|
alwaysLogMetrics: 'SHOPIFY_CLI_ALWAYS_LOG_METRICS',
|
|
15
15
|
deviceAuth: 'SHOPIFY_CLI_DEVICE_AUTH',
|
|
16
|
-
accessCodeAuth: 'SHOPIFY_CLI_ACCESS_CODE_AUTH',
|
|
17
16
|
enableCliRedirect: 'SHOPIFY_CLI_ENABLE_CLI_REDIRECT',
|
|
18
17
|
env: 'SHOPIFY_CLI_ENV',
|
|
19
18
|
firstPartyDev: 'SHOPIFY_CLI_1P_DEV',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/private/node/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,2BAA2B,CAAA;AAClD,OAAO,QAAQ,MAAM,WAAW,CAAA;AAEhC,MAAM,UAAU,GAAG,aAAa,CAAA;AAEhC,MAAM,WAAW,GAAG,GAAG,EAAE;IACvB,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAA;IACjE,OAAO,QAAQ,CAAC,UAAU,CAAC,CAAC,KAAK,CAAA;AACnC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,EAAE;IAC7B,OAAO,QAAQ,CAAC,UAAU,CAAC,CAAC,GAAG,CAAA;AACjC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,kBAAkB,EAAE,kCAAkC;IACtD,gBAAgB,EAAE,gCAAgC;IAClD,UAAU,EAAE,yBAAyB;IACrC,
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/private/node/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,2BAA2B,CAAA;AAClD,OAAO,QAAQ,MAAM,WAAW,CAAA;AAEhC,MAAM,UAAU,GAAG,aAAa,CAAA;AAEhC,MAAM,WAAW,GAAG,GAAG,EAAE;IACvB,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAA;IACjE,OAAO,QAAQ,CAAC,UAAU,CAAC,CAAC,KAAK,CAAA;AACnC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,EAAE;IAC7B,OAAO,QAAQ,CAAC,UAAU,CAAC,CAAC,GAAG,CAAA;AACjC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,kBAAkB,EAAE,kCAAkC;IACtD,gBAAgB,EAAE,gCAAgC;IAClD,UAAU,EAAE,yBAAyB;IACrC,iBAAiB,EAAE,iCAAiC;IACpD,GAAG,EAAE,iBAAiB;IACtB,aAAa,EAAE,oBAAoB;IACnC,WAAW,EAAE,0BAA0B;IACvC,aAAa,EAAE,4BAA4B;IAC3C,SAAS,EAAE,qBAAqB;IAChC,UAAU,EAAE,qBAAqB;IACjC,eAAe,EAAE,+BAA+B;IAChD,YAAY,EAAE,eAAe;IAC7B,UAAU,EAAE,yBAAyB;IACrC,QAAQ,EAAE,mBAAmB;IAC7B,OAAO,EAAE,sBAAsB;IAC/B,eAAe,EAAE,+BAA+B;IAChD,eAAe,EAAE,+BAA+B;IAChD,mEAAmE;IACnE,UAAU,EAAE,YAAY;IACxB,aAAa,EAAE,gBAAgB;IAC/B,6BAA6B,EAAE,0CAA0C;IACzE,MAAM,EAAE,sBAAsB;IAC9B,UAAU,EAAE,aAAa;IACzB,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,aAAa;IAC1B,WAAW,EAAE,eAAe;IAC5B,YAAY,EAAE,0BAA0B;IACxC,aAAa,EAAE,4BAA4B;IAC3C,YAAY,EAAE,2BAA2B;IACzC,OAAO,EAAE,yCAAyC;IAClD,oBAAoB,EAAE,qCAAqC;CAC5D,CAAA;AAED,MAAM,CAAC,MAAM,2BAA2B,GAAG,kCAAkC,CAAA;AAE7E,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,WAAW,EAAE,cAAc;CAC5B,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,WAAW,EAAE;QACX,GAAG,EAAE,kBAAkB;KACxB;IACD,WAAW,EAAE;QACX,KAAK,EAAE;YACL,IAAI,EAAE,GAAG,EAAE;gBACT,OAAO,WAAW,EAAE,CAAA;YACtB,CAAC;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,GAAG,EAAE;oBACT,OAAO,QAAQ,CAAC,WAAW,EAAE,EAAE,QAAQ,CAAC,CAAA;gBAC1C,CAAC;gBACD,QAAQ,EAAE,GAAG,EAAE;oBACb,OAAO,QAAQ,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAA;gBACtD,CAAC;aACF;SACF;KACF;CACF,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,6BAA6B,EAAE,CAAC;CACjC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,kCAAkC,CAAA;AAE/D,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAC,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAC,IAAI,EAAE,CAAC,EAAC,EAAC,CAAA","sourcesContent":["import {joinPath} from '../../public/node/path.js'\nimport envPaths from 'env-paths'\n\nconst identifier = 'shopify-cli'\n\nconst cacheFolder = () => {\n if (process.env.XDG_CACHE_HOME) return process.env.XDG_CACHE_HOME\n return envPaths(identifier).cache\n}\n\nexport const logsFolder = () => {\n return envPaths(identifier).log\n}\n\nexport const environmentVariables = {\n alwaysLogAnalytics: 'SHOPIFY_CLI_ALWAYS_LOG_ANALYTICS',\n alwaysLogMetrics: 'SHOPIFY_CLI_ALWAYS_LOG_METRICS',\n deviceAuth: 'SHOPIFY_CLI_DEVICE_AUTH',\n enableCliRedirect: 'SHOPIFY_CLI_ENABLE_CLI_REDIRECT',\n env: 'SHOPIFY_CLI_ENV',\n firstPartyDev: 'SHOPIFY_CLI_1P_DEV',\n noAnalytics: 'SHOPIFY_CLI_NO_ANALYTICS',\n partnersToken: 'SHOPIFY_CLI_PARTNERS_TOKEN',\n runAsUser: 'SHOPIFY_RUN_AS_USER',\n serviceEnv: 'SHOPIFY_SERVICE_ENV',\n skipCliRedirect: 'SHOPIFY_CLI_SKIP_CLI_REDIRECT',\n spinInstance: 'SPIN_INSTANCE',\n themeToken: 'SHOPIFY_CLI_THEME_TOKEN',\n unitTest: 'SHOPIFY_UNIT_TEST',\n verbose: 'SHOPIFY_FLAG_VERBOSE',\n noThemeBundling: 'SHOPIFY_CLI_NO_THEME_BUNDLING',\n bundledThemeCLI: 'SHOPIFY_CLI_BUNDLED_THEME_CLI',\n // Variables to detect if the CLI is running in a cloud environment\n codespaces: 'CODESPACES',\n codespaceName: 'CODESPACE_NAME',\n codespacePortForwardingDomain: 'GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN',\n gitpod: 'GITPOD_WORKSPACE_URL',\n cloudShell: 'CLOUD_SHELL',\n spin: 'SPIN',\n spinAppPort: 'SERVER_PORT',\n spinAppHost: 'SPIN_APP_HOST',\n organization: 'SHOPIFY_CLI_ORGANIZATION',\n identityToken: 'SHOPIFY_CLI_IDENTITY_TOKEN',\n refreshToken: 'SHOPIFY_CLI_REFRESH_TOKEN',\n otelURL: 'SHOPIFY_CLI_OTEL_EXPORTER_OTLP_ENDPOINT',\n themeKitAccessDomain: 'SHOPIFY_CLI_THEME_KIT_ACCESS_DOMAIN',\n}\n\nexport const defaultThemeKitAccessDomain = 'theme-kit-access.shopifyapps.com'\n\nexport const systemEnvironmentVariables = {\n backendPort: 'BACKEND_PORT',\n}\n\nexport const pathConstants = {\n executables: {\n dev: '/opt/dev/bin/dev',\n },\n directories: {\n cache: {\n path: () => {\n return cacheFolder()\n },\n vendor: {\n path: () => {\n return joinPath(cacheFolder(), 'vendor')\n },\n binaries: () => {\n return joinPath(cacheFolder(), 'vendor', 'binaries')\n },\n },\n },\n },\n}\n\nexport const sessionConstants = {\n expirationTimeMarginInMinutes: 4,\n}\n\nexport const bugsnagApiKey = '9e1e6889176fd0c795d5c659225e0fae'\n\nexport const reportingRateLimit = {limit: 300, timeout: {days: 1}}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"demo-recorder.js","sourceRoot":"","sources":["../../../src/private/node/demo-recorder.ts"],"names":[],"mappings":"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","sourcesContent":["
|
|
1
|
+
{"version":3,"file":"demo-recorder.js","sourceRoot":"","sources":["../../../src/private/node/demo-recorder.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-non-null-assertion */\nimport {isTruthy} from '../../public/node/context/utilities.js'\n\ninterface Event {\n type: string\n properties: {[key: string]: unknown}\n // Only used within this recorder for tracking concurrency timeline\n concurrencyStart?: number\n}\n\ninterface ConcurrencyStep {\n timestamp: number\n endMessage: string\n}\n\ninterface ConcurrencyProcess {\n prefix: string\n steps: ConcurrencyStep[]\n}\n\nclass DemoRecorder {\n recorded: Event[]\n sleepStart: number\n command: string\n\n constructor() {\n this.recorded = []\n this.sleepStart = Date.now()\n this.command = ['shopify', ...process.argv.slice(2)].join(' ')\n }\n\n addEvent({type, properties}: Event) {\n if (type === 'taskbar') {\n this.resetSleep()\n } else {\n this.addSleep()\n }\n this.recorded.push({type, properties: JSON.parse(JSON.stringify(properties))})\n this.sleepStart = Date.now()\n }\n\n recordedEventsJson() {\n return JSON.stringify(\n {\n command: this.command,\n steps: this.withFormattedConcurrent(this.recorded),\n },\n null,\n 2,\n )\n }\n\n addSleep() {\n const duration = (Date.now() - this.sleepStart) / 1000\n this.sleepStart = Date.now()\n if (duration > 0.1) {\n this.recorded.push({type: 'sleep', properties: {duration}})\n }\n }\n\n resetSleep() {\n this.sleepStart = Date.now()\n }\n\n addOrUpdateConcurrentOutput({prefix, index, output}: {prefix: string; index: number; output: string}) {\n let last = this.recorded[this.recorded.length - 1]\n if (last?.type === 'concurrent') {\n // Don't sleep between concurrent lines\n this.resetSleep()\n } else {\n const eventProperties: Event = {\n type: 'concurrent',\n properties: {processes: [], concurrencyStart: Date.now()},\n }\n this.addEvent(eventProperties)\n last = this.recorded[this.recorded.length - 1]\n }\n const {processes} = last!.properties as {processes: ConcurrencyProcess[]}\n while (processes.length <= index) {\n processes.push({prefix: '', steps: []})\n }\n processes[index]!.prefix = prefix\n processes[index]!.steps.push({timestamp: Date.now(), endMessage: output})\n }\n\n withFormattedConcurrent(recorded: Event[]) {\n return recorded.map((event) => {\n if (event.type === 'concurrent') {\n const {processes, footer, concurrencyStart} = event.properties as {\n processes: ConcurrencyProcess[]\n footer?: string\n concurrencyStart: number\n }\n const formatted = processes.map(({prefix, steps}: {prefix: string; steps: ConcurrencyStep[]}) => {\n let mostRecentTimestamp = concurrencyStart\n const formattedSteps = steps.map(({timestamp, endMessage}) => {\n const duration = (timestamp - mostRecentTimestamp) / 1000\n mostRecentTimestamp = timestamp\n return {duration, endMessage}\n })\n return {prefix, steps: formattedSteps}\n })\n return {type: 'concurrent', properties: {footer, processes: formatted}}\n }\n return event\n })\n }\n}\n\nclass NoopDemoRecorder {\n addEvent(_event: Event) {}\n\n recordedEventsJson() {\n return JSON.stringify({steps: []}, null, 2)\n }\n\n addSleep() {}\n resetSleep() {}\n\n addOrUpdateConcurrentOutput(..._args: unknown[]) {}\n}\n\nlet _instance: {\n addEvent: (event: Event) => void\n recordedEventsJson: () => string\n resetSleep: () => void\n addSleep: () => void\n addOrUpdateConcurrentOutput: ({prefix, index, output}: {prefix: string; index: number; output: string}) => void\n}\n\nfunction ensureInstance() {\n if (!_instance) {\n if (isRecording()) {\n _instance = new DemoRecorder()\n } else {\n _instance = new NoopDemoRecorder()\n }\n }\n}\n\nexport function initDemoRecorder() {\n ensureInstance()\n}\n\nexport function recordUIEvent(event: Event) {\n ensureInstance()\n _instance.addEvent(event)\n}\n\nexport function resetRecordedSleep() {\n ensureInstance()\n _instance.resetSleep()\n}\n\nexport function printEventsJson(): void {\n if (isRecording()) {\n ensureInstance()\n _instance.addSleep()\n // eslint-disable-next-line no-console\n console.log(_instance.recordedEventsJson())\n }\n}\n\nexport function addOrUpdateConcurrentUIEventOutput(data: {prefix: string; index: number; output: string}) {\n ensureInstance()\n _instance.addOrUpdateConcurrentOutput(data)\n}\n\nfunction isRecording() {\n return isTruthy(process.env.RECORD_DEMO)\n}\n"]}
|
|
@@ -73,20 +73,28 @@ export async function pollForDeviceAuthorization(code, interval = 5) {
|
|
|
73
73
|
return new Promise((resolve, reject) => {
|
|
74
74
|
const onPoll = async () => {
|
|
75
75
|
const result = await exchangeDeviceCodeForAccessToken(code);
|
|
76
|
-
if (!result.isErr())
|
|
77
|
-
|
|
76
|
+
if (!result.isErr()) {
|
|
77
|
+
resolve(result.value);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
78
80
|
const error = result.error ?? 'unknown_failure';
|
|
79
81
|
outputDebug(outputContent `Polling for device authorization... status: ${error}`);
|
|
80
82
|
switch (error) {
|
|
81
|
-
case 'authorization_pending':
|
|
82
|
-
|
|
83
|
+
case 'authorization_pending': {
|
|
84
|
+
startPolling();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
83
87
|
case 'slow_down':
|
|
84
88
|
currentIntervalInSeconds += 5;
|
|
85
|
-
|
|
89
|
+
{
|
|
90
|
+
startPolling();
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
86
93
|
case 'access_denied':
|
|
87
94
|
case 'expired_token':
|
|
88
|
-
case 'unknown_failure':
|
|
89
|
-
|
|
95
|
+
case 'unknown_failure': {
|
|
96
|
+
reject(result);
|
|
97
|
+
}
|
|
90
98
|
}
|
|
91
99
|
};
|
|
92
100
|
const startPolling = () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-authorization.js","sourceRoot":"","sources":["../../../../src/private/node/session/device-authorization.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"device-authorization.js","sourceRoot":"","sources":["../../../../src/private/node/session/device-authorization.ts"],"names":[],"mappings":"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","sourcesContent":["import {clientId} from './identity.js'\nimport {exchangeDeviceCodeForAccessToken} from './exchange.js'\nimport {IdentityToken} from './schema.js'\nimport {identityFqdn} from '../../../public/node/context/fqdn.js'\nimport {shopifyFetch} from '../../../public/node/http.js'\nimport {outputContent, outputDebug, outputInfo, outputToken} from '../../../public/node/output.js'\nimport {AbortError, BugError} from '../../../public/node/error.js'\nimport {isCloudEnvironment} from '../../../public/node/context/local.js'\nimport {openURL} from '../../../public/node/system.js'\nimport {isTTY, keypress} from '../../../public/node/ui.js'\n\nexport interface DeviceAuthorizationResponse {\n deviceCode: string\n userCode: string\n verificationUri: string\n expiresIn: number\n verificationUriComplete?: string\n interval?: number\n}\n\n/**\n * Initiate a device authorization flow.\n * This will return a DeviceAuthorizationResponse containing the URL where user\n * should go to authorize the device without the need of a callback to the CLI.\n *\n * Also returns a `deviceCode` used for polling the token endpoint in the next step.\n *\n * @param scopes - The scopes to request\n * @returns An object with the device authorization response.\n */\nexport async function requestDeviceAuthorization(scopes: string[]): Promise<DeviceAuthorizationResponse> {\n const fqdn = await identityFqdn()\n const identityClientId = clientId()\n const queryParams = {client_id: identityClientId, scope: scopes.join(' ')}\n const url = `https://${fqdn}/oauth/device_authorization`\n\n const response = await shopifyFetch(url, {\n method: 'POST',\n headers: {'Content-type': 'application/x-www-form-urlencoded'},\n body: convertRequestToParams(queryParams),\n })\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const jsonResult: any = await response.json()\n\n outputDebug(outputContent`Received device authorization code: ${outputToken.json(jsonResult)}`)\n if (!jsonResult.device_code || !jsonResult.verification_uri_complete) {\n throw new BugError('Failed to start authorization process')\n }\n\n outputInfo('\\nTo run this command, log in to Shopify.')\n\n if (!isTTY()) {\n throw new AbortError(\n 'Authorization is required to continue, but the current environment does not support interactive prompts.',\n 'To resolve this, specify credentials in your environment, or run the command in an interactive environment such as your local terminal.',\n )\n }\n\n outputInfo(outputContent`User verification code: ${jsonResult.user_code}`)\n const linkToken = outputToken.link(jsonResult.verification_uri_complete)\n\n if (isCloudEnvironment()) {\n outputInfo(outputContent`👉 Open this link to start the auth process: ${linkToken}`)\n } else {\n outputInfo('👉 Press any key to open the login page on your browser')\n await keypress()\n await openURL(jsonResult.verification_uri_complete)\n outputInfo(outputContent`Opened link to start the auth process: ${linkToken}`)\n }\n\n return {\n deviceCode: jsonResult.device_code,\n userCode: jsonResult.user_code,\n verificationUri: jsonResult.verification_uri,\n expiresIn: jsonResult.expires_in,\n verificationUriComplete: jsonResult.verification_uri_complete,\n interval: jsonResult.interval,\n }\n}\n\n/**\n * Poll the Oauth token endpoint with the device code obtained from a DeviceAuthorizationResponse.\n * The endpoint will return `authorization_pending` until the user completes the auth flow in the browser.\n * Once the user completes the auth flow, the endpoint will return the identity token.\n *\n * Timeout for the polling is defined by the server and is around 600 seconds.\n *\n * @param code - The device code obtained after starting a device identity flow\n * @param interval - The interval to poll the token endpoint\n * @returns The identity token\n */\nexport async function pollForDeviceAuthorization(code: string, interval = 5): Promise<IdentityToken> {\n let currentIntervalInSeconds = interval\n\n return new Promise<IdentityToken>((resolve, reject) => {\n const onPoll = async () => {\n const result = await exchangeDeviceCodeForAccessToken(code)\n if (!result.isErr()) {\n resolve(result.value)\n return\n }\n\n const error = result.error ?? 'unknown_failure'\n\n outputDebug(outputContent`Polling for device authorization... status: ${error}`)\n switch (error) {\n case 'authorization_pending': {\n startPolling()\n return\n }\n case 'slow_down':\n currentIntervalInSeconds += 5\n {\n startPolling()\n return\n }\n case 'access_denied':\n case 'expired_token':\n case 'unknown_failure': {\n reject(result)\n }\n }\n }\n\n const startPolling = () => {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n setTimeout(onPoll, currentIntervalInSeconds * 1000)\n }\n\n startPolling()\n })\n}\n\nfunction convertRequestToParams(queryParams: {client_id: string; scope: string}): string {\n return Object.entries(queryParams)\n .map(([key, value]) => value && `${key}=${value}`)\n .filter((hasValue) => Boolean(hasValue))\n .join('&')\n}\n"]}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { ApplicationToken, IdentityToken } from './schema.js';
|
|
2
|
-
import { CodeAuthResult } from './authorize.js';
|
|
3
2
|
import { Result } from '../../../public/node/result.js';
|
|
4
3
|
import { ExtendableError } from '../../../public/node/error.js';
|
|
5
4
|
export declare class InvalidGrantError extends ExtendableError {
|
|
@@ -13,13 +12,6 @@ export interface ExchangeScopes {
|
|
|
13
12
|
businessPlatform: string[];
|
|
14
13
|
appManagement: string[];
|
|
15
14
|
}
|
|
16
|
-
/**
|
|
17
|
-
* Given a valid authorization code, request an identity access token.
|
|
18
|
-
* This token can then be used to get API specific tokens.
|
|
19
|
-
* @param codeData - code and codeVerifier from the authorize endpoint
|
|
20
|
-
* @returns An instance with the identity access tokens.
|
|
21
|
-
*/
|
|
22
|
-
export declare function exchangeCodeForAccessToken(codeData: CodeAuthResult): Promise<IdentityToken>;
|
|
23
15
|
/**
|
|
24
16
|
* Given an identity token, request an application token.
|
|
25
17
|
* @param identityToken - access token obtained in a previous step
|
|
@@ -13,25 +13,6 @@ export class InvalidRequestError extends ExtendableError {
|
|
|
13
13
|
}
|
|
14
14
|
class InvalidTargetError extends AbortError {
|
|
15
15
|
}
|
|
16
|
-
/**
|
|
17
|
-
* Given a valid authorization code, request an identity access token.
|
|
18
|
-
* This token can then be used to get API specific tokens.
|
|
19
|
-
* @param codeData - code and codeVerifier from the authorize endpoint
|
|
20
|
-
* @returns An instance with the identity access tokens.
|
|
21
|
-
*/
|
|
22
|
-
export async function exchangeCodeForAccessToken(codeData) {
|
|
23
|
-
const clientId = await getIdentityClientId();
|
|
24
|
-
const params = {
|
|
25
|
-
grant_type: 'authorization_code',
|
|
26
|
-
code: codeData.code,
|
|
27
|
-
redirect_uri: 'http://127.0.0.1:3456',
|
|
28
|
-
client_id: clientId,
|
|
29
|
-
code_verifier: codeData.codeVerifier,
|
|
30
|
-
};
|
|
31
|
-
const tokenResult = await tokenRequest(params);
|
|
32
|
-
const value = tokenResult.mapError(tokenRequestErrorHandler).valueOrBug();
|
|
33
|
-
return buildIdentityToken(value);
|
|
34
|
-
}
|
|
35
16
|
/**
|
|
36
17
|
* Given an identity token, request an application token.
|
|
37
18
|
* @param identityToken - access token obtained in a previous step
|
|
@@ -81,6 +62,7 @@ export async function exchangeCustomPartnerToken(token) {
|
|
|
81
62
|
const appId = applicationId('partners');
|
|
82
63
|
try {
|
|
83
64
|
const newToken = await requestAppToken('partners', token, ['https://api.shopify.com/auth/partners.app.cli.access']);
|
|
65
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
84
66
|
const accessToken = newToken[appId].accessToken;
|
|
85
67
|
const userId = nonRandomUUID(token);
|
|
86
68
|
setLastSeenUserIdAfterAuth(userId);
|
|
@@ -172,6 +154,7 @@ async function tokenRequest(params) {
|
|
|
172
154
|
return err(payload.error);
|
|
173
155
|
}
|
|
174
156
|
function buildIdentityToken(result, existingUserId) {
|
|
157
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
175
158
|
const userId = existingUserId ?? (result.id_token ? jose.decodeJwt(result.id_token).sub : undefined);
|
|
176
159
|
if (!userId) {
|
|
177
160
|
throw new BugError('Error setting userId for session. No id_token or pre-existing user ID provided.');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exchange.js","sourceRoot":"","sources":["../../../../src/private/node/session/exchange.ts"],"names":[],"mappings":"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","sourcesContent":["import {ApplicationToken, IdentityToken} from './schema.js'\nimport {applicationId, clientId as getIdentityClientId} from './identity.js'\nimport {CodeAuthResult} from './authorize.js'\nimport {API} from '../api.js'\nimport {identityFqdn} from '../../../public/node/context/fqdn.js'\nimport {shopifyFetch} from '../../../public/node/http.js'\nimport {err, ok, Result} from '../../../public/node/result.js'\nimport {AbortError, BugError, ExtendableError} from '../../../public/node/error.js'\nimport {setLastSeenAuthMethod, setLastSeenUserIdAfterAuth} from '../session.js'\nimport {isTruthy} from '@shopify/cli-kit/node/context/utilities'\nimport * as jose from 'jose'\nimport {nonRandomUUID} from '@shopify/cli-kit/node/crypto'\n\nexport class InvalidGrantError extends ExtendableError {}\nexport class InvalidRequestError extends ExtendableError {}\nclass InvalidTargetError extends AbortError {}\n\nexport interface ExchangeScopes {\n admin: string[]\n partners: string[]\n storefront: string[]\n businessPlatform: string[]\n appManagement: string[]\n}\n/**\n * Given a valid authorization code, request an identity access token.\n * This token can then be used to get API specific tokens.\n * @param codeData - code and codeVerifier from the authorize endpoint\n * @returns An instance with the identity access tokens.\n */\nexport async function exchangeCodeForAccessToken(codeData: CodeAuthResult): Promise<IdentityToken> {\n const clientId = await getIdentityClientId()\n const params = {\n grant_type: 'authorization_code',\n code: codeData.code,\n redirect_uri: 'http://127.0.0.1:3456',\n client_id: clientId,\n code_verifier: codeData.codeVerifier,\n }\n\n const tokenResult = await tokenRequest(params)\n const value = tokenResult.mapError(tokenRequestErrorHandler).valueOrBug()\n return buildIdentityToken(value)\n}\n\n/**\n * Given an identity token, request an application token.\n * @param identityToken - access token obtained in a previous step\n * @param store - the store to use, only needed for admin API\n * @returns An array with the application access tokens.\n */\nexport async function exchangeAccessForApplicationTokens(\n identityToken: IdentityToken,\n scopes: ExchangeScopes,\n store?: string,\n): Promise<{[x: string]: ApplicationToken}> {\n const token = identityToken.accessToken\n const appManagementEnabled = isTruthy(process.env.USE_APP_MANAGEMENT_API)\n\n const [partners, storefront, businessPlatform, admin, appManagement] = await Promise.all([\n requestAppToken('partners', token, scopes.partners),\n requestAppToken('storefront-renderer', token, scopes.storefront),\n requestAppToken('business-platform', token, scopes.businessPlatform),\n store ? requestAppToken('admin', token, scopes.admin, store) : {},\n appManagementEnabled ? requestAppToken('app-management', token, scopes.appManagement) : {},\n ])\n\n return {\n ...partners,\n ...storefront,\n ...businessPlatform,\n ...admin,\n ...appManagement,\n }\n}\n\n/**\n * Given an expired access token, refresh it to get a new one.\n */\nexport async function refreshAccessToken(currentToken: IdentityToken): Promise<IdentityToken> {\n const clientId = getIdentityClientId()\n const params = {\n grant_type: 'refresh_token',\n access_token: currentToken.accessToken,\n refresh_token: currentToken.refreshToken,\n client_id: clientId,\n }\n const tokenResult = await tokenRequest(params)\n const value = tokenResult.mapError(tokenRequestErrorHandler).valueOrBug()\n return buildIdentityToken(value, currentToken.userId)\n}\n\n/**\n * Given a custom CLI token passed as ENV variable, request a valid partners API token\n * This token does not accept extra scopes, just the cli one.\n * @param token - The CLI token passed as ENV variable\n * @returns An instance with the application access tokens.\n */\nexport async function exchangeCustomPartnerToken(token: string): Promise<{accessToken: string; userId: string}> {\n const appId = applicationId('partners')\n try {\n const newToken = await requestAppToken('partners', token, ['https://api.shopify.com/auth/partners.app.cli.access'])\n const accessToken = newToken[appId]!.accessToken\n const userId = nonRandomUUID(token)\n setLastSeenUserIdAfterAuth(userId)\n setLastSeenAuthMethod('partners_token')\n return {accessToken, userId}\n } catch (error) {\n throw new AbortError('The custom token provided is invalid.', 'Ensure the token is correct and not expired.')\n }\n}\n\ntype IdentityDeviceError = 'authorization_pending' | 'access_denied' | 'expired_token' | 'slow_down' | 'unknown_failure'\n\n/**\n * Given a deviceCode obtained after starting a device identity flow, request an identity token.\n * @param deviceCode - The device code obtained after starting a device identity flow\n * @param scopes - The scopes to request\n * @returns An instance with the identity access tokens.\n */\nexport async function exchangeDeviceCodeForAccessToken(\n deviceCode: string,\n): Promise<Result<IdentityToken, IdentityDeviceError>> {\n const clientId = await getIdentityClientId()\n\n const params = {\n grant_type: 'urn:ietf:params:oauth:grant-type:device_code',\n device_code: deviceCode,\n client_id: clientId,\n }\n\n const tokenResult = await tokenRequest(params)\n if (tokenResult.isErr()) {\n return err(tokenResult.error as IdentityDeviceError)\n }\n const identityToken = buildIdentityToken(tokenResult.value)\n return ok(identityToken)\n}\n\nasync function requestAppToken(\n api: API,\n token: string,\n scopes: string[] = [],\n store?: string,\n): Promise<{[x: string]: ApplicationToken}> {\n const appId = applicationId(api)\n const clientId = await getIdentityClientId()\n\n const params = {\n grant_type: 'urn:ietf:params:oauth:grant-type:token-exchange',\n requested_token_type: 'urn:ietf:params:oauth:token-type:access_token',\n subject_token_type: 'urn:ietf:params:oauth:token-type:access_token',\n client_id: clientId,\n audience: appId,\n scope: scopes.join(' '),\n subject_token: token,\n ...(api === 'admin' && {destination: `https://${store}/admin`}),\n }\n\n let identifier = appId\n if (api === 'admin' && store) {\n identifier = `${store}-${appId}`\n }\n const tokenResult = await tokenRequest(params)\n const value = tokenResult.mapError(tokenRequestErrorHandler).valueOrBug()\n const appToken = buildApplicationToken(value)\n return {[identifier]: appToken}\n}\n\ninterface TokenRequestResult {\n access_token: string\n expires_in: number\n refresh_token: string\n scope: string\n id_token?: string\n}\n\nfunction tokenRequestErrorHandler(error: string) {\n const invalidTargetErrorMessage =\n 'You are not authorized to use the CLI to develop in the provided store.' +\n '\\n\\n' +\n \"You can't use Shopify CLI with development stores if you only have Partner \" +\n 'staff member access. If you want to use Shopify CLI to work on a development store, then ' +\n 'you should be the store owner or create a staff account on the store.' +\n '\\n\\n' +\n \"If you're the store owner, then you need to log in to the store directly using the \" +\n 'store URL at least once before you log in using Shopify CLI.' +\n 'Logging in to the Shopify admin directly connects the development ' +\n 'store with your Shopify login.'\n if (error === 'invalid_grant') {\n // There's an scenario when Identity returns \"invalid_grant\" when trying to refresh the token\n // using a valid refresh token. When that happens, we take the user through the authentication flow.\n return new InvalidGrantError()\n }\n if (error === 'invalid_request') {\n // There's an scenario when Identity returns \"invalid_request\" when exchanging an identity token.\n // This means the token is invalid. We clear the session and throw an error to let the caller know.\n return new InvalidRequestError()\n }\n if (error === 'invalid_target') {\n return new InvalidTargetError(invalidTargetErrorMessage)\n }\n // eslint-disable-next-line @shopify/cli/no-error-factory-functions\n return new AbortError(error)\n}\n\nasync function tokenRequest(params: {[key: string]: string}): Promise<Result<TokenRequestResult, string>> {\n const fqdn = await identityFqdn()\n const url = new URL(`https://${fqdn}/oauth/token`)\n url.search = new URLSearchParams(Object.entries(params)).toString()\n const res = await shopifyFetch(url.href, {method: 'POST'})\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const payload: any = await res.json()\n\n if (res.ok) return ok(payload)\n return err(payload.error)\n}\n\nfunction buildIdentityToken(result: TokenRequestResult, existingUserId?: string): IdentityToken {\n const userId = existingUserId ?? (result.id_token ? jose.decodeJwt(result.id_token).sub! : undefined)\n\n if (!userId) {\n throw new BugError('Error setting userId for session. No id_token or pre-existing user ID provided.')\n }\n\n return {\n accessToken: result.access_token,\n refreshToken: result.refresh_token,\n expiresAt: new Date(Date.now() + result.expires_in * 1000),\n scopes: result.scope.split(' '),\n userId,\n }\n}\n\nfunction buildApplicationToken(result: TokenRequestResult): ApplicationToken {\n return {\n accessToken: result.access_token,\n expiresAt: new Date(Date.now() + result.expires_in * 1000),\n scopes: result.scope.split(' '),\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"exchange.js","sourceRoot":"","sources":["../../../../src/private/node/session/exchange.ts"],"names":[],"mappings":"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","sourcesContent":["import {ApplicationToken, IdentityToken} from './schema.js'\nimport {applicationId, clientId as getIdentityClientId} from './identity.js'\nimport {API} from '../api.js'\nimport {identityFqdn} from '../../../public/node/context/fqdn.js'\nimport {shopifyFetch} from '../../../public/node/http.js'\nimport {err, ok, Result} from '../../../public/node/result.js'\nimport {AbortError, BugError, ExtendableError} from '../../../public/node/error.js'\nimport {setLastSeenAuthMethod, setLastSeenUserIdAfterAuth} from '../session.js'\nimport {isTruthy} from '@shopify/cli-kit/node/context/utilities'\nimport * as jose from 'jose'\nimport {nonRandomUUID} from '@shopify/cli-kit/node/crypto'\n\nexport class InvalidGrantError extends ExtendableError {}\nexport class InvalidRequestError extends ExtendableError {}\nclass InvalidTargetError extends AbortError {}\n\nexport interface ExchangeScopes {\n admin: string[]\n partners: string[]\n storefront: string[]\n businessPlatform: string[]\n appManagement: string[]\n}\n\n/**\n * Given an identity token, request an application token.\n * @param identityToken - access token obtained in a previous step\n * @param store - the store to use, only needed for admin API\n * @returns An array with the application access tokens.\n */\nexport async function exchangeAccessForApplicationTokens(\n identityToken: IdentityToken,\n scopes: ExchangeScopes,\n store?: string,\n): Promise<{[x: string]: ApplicationToken}> {\n const token = identityToken.accessToken\n const appManagementEnabled = isTruthy(process.env.USE_APP_MANAGEMENT_API)\n\n const [partners, storefront, businessPlatform, admin, appManagement] = await Promise.all([\n requestAppToken('partners', token, scopes.partners),\n requestAppToken('storefront-renderer', token, scopes.storefront),\n requestAppToken('business-platform', token, scopes.businessPlatform),\n store ? requestAppToken('admin', token, scopes.admin, store) : {},\n appManagementEnabled ? requestAppToken('app-management', token, scopes.appManagement) : {},\n ])\n\n return {\n ...partners,\n ...storefront,\n ...businessPlatform,\n ...admin,\n ...appManagement,\n }\n}\n\n/**\n * Given an expired access token, refresh it to get a new one.\n */\nexport async function refreshAccessToken(currentToken: IdentityToken): Promise<IdentityToken> {\n const clientId = getIdentityClientId()\n const params = {\n grant_type: 'refresh_token',\n access_token: currentToken.accessToken,\n refresh_token: currentToken.refreshToken,\n client_id: clientId,\n }\n const tokenResult = await tokenRequest(params)\n const value = tokenResult.mapError(tokenRequestErrorHandler).valueOrBug()\n return buildIdentityToken(value, currentToken.userId)\n}\n\n/**\n * Given a custom CLI token passed as ENV variable, request a valid partners API token\n * This token does not accept extra scopes, just the cli one.\n * @param token - The CLI token passed as ENV variable\n * @returns An instance with the application access tokens.\n */\nexport async function exchangeCustomPartnerToken(token: string): Promise<{accessToken: string; userId: string}> {\n const appId = applicationId('partners')\n try {\n const newToken = await requestAppToken('partners', token, ['https://api.shopify.com/auth/partners.app.cli.access'])\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const accessToken = newToken[appId]!.accessToken\n const userId = nonRandomUUID(token)\n setLastSeenUserIdAfterAuth(userId)\n setLastSeenAuthMethod('partners_token')\n return {accessToken, userId}\n } catch (error) {\n throw new AbortError('The custom token provided is invalid.', 'Ensure the token is correct and not expired.')\n }\n}\n\ntype IdentityDeviceError = 'authorization_pending' | 'access_denied' | 'expired_token' | 'slow_down' | 'unknown_failure'\n\n/**\n * Given a deviceCode obtained after starting a device identity flow, request an identity token.\n * @param deviceCode - The device code obtained after starting a device identity flow\n * @param scopes - The scopes to request\n * @returns An instance with the identity access tokens.\n */\nexport async function exchangeDeviceCodeForAccessToken(\n deviceCode: string,\n): Promise<Result<IdentityToken, IdentityDeviceError>> {\n const clientId = await getIdentityClientId()\n\n const params = {\n grant_type: 'urn:ietf:params:oauth:grant-type:device_code',\n device_code: deviceCode,\n client_id: clientId,\n }\n\n const tokenResult = await tokenRequest(params)\n if (tokenResult.isErr()) {\n return err(tokenResult.error as IdentityDeviceError)\n }\n const identityToken = buildIdentityToken(tokenResult.value)\n return ok(identityToken)\n}\n\nasync function requestAppToken(\n api: API,\n token: string,\n scopes: string[] = [],\n store?: string,\n): Promise<{[x: string]: ApplicationToken}> {\n const appId = applicationId(api)\n const clientId = await getIdentityClientId()\n\n const params = {\n grant_type: 'urn:ietf:params:oauth:grant-type:token-exchange',\n requested_token_type: 'urn:ietf:params:oauth:token-type:access_token',\n subject_token_type: 'urn:ietf:params:oauth:token-type:access_token',\n client_id: clientId,\n audience: appId,\n scope: scopes.join(' '),\n subject_token: token,\n ...(api === 'admin' && {destination: `https://${store}/admin`}),\n }\n\n let identifier = appId\n if (api === 'admin' && store) {\n identifier = `${store}-${appId}`\n }\n const tokenResult = await tokenRequest(params)\n const value = tokenResult.mapError(tokenRequestErrorHandler).valueOrBug()\n const appToken = buildApplicationToken(value)\n return {[identifier]: appToken}\n}\n\ninterface TokenRequestResult {\n access_token: string\n expires_in: number\n refresh_token: string\n scope: string\n id_token?: string\n}\n\nfunction tokenRequestErrorHandler(error: string) {\n const invalidTargetErrorMessage =\n 'You are not authorized to use the CLI to develop in the provided store.' +\n '\\n\\n' +\n \"You can't use Shopify CLI with development stores if you only have Partner \" +\n 'staff member access. If you want to use Shopify CLI to work on a development store, then ' +\n 'you should be the store owner or create a staff account on the store.' +\n '\\n\\n' +\n \"If you're the store owner, then you need to log in to the store directly using the \" +\n 'store URL at least once before you log in using Shopify CLI.' +\n 'Logging in to the Shopify admin directly connects the development ' +\n 'store with your Shopify login.'\n if (error === 'invalid_grant') {\n // There's an scenario when Identity returns \"invalid_grant\" when trying to refresh the token\n // using a valid refresh token. When that happens, we take the user through the authentication flow.\n return new InvalidGrantError()\n }\n if (error === 'invalid_request') {\n // There's an scenario when Identity returns \"invalid_request\" when exchanging an identity token.\n // This means the token is invalid. We clear the session and throw an error to let the caller know.\n return new InvalidRequestError()\n }\n if (error === 'invalid_target') {\n return new InvalidTargetError(invalidTargetErrorMessage)\n }\n // eslint-disable-next-line @shopify/cli/no-error-factory-functions\n return new AbortError(error)\n}\n\nasync function tokenRequest(params: {[key: string]: string}): Promise<Result<TokenRequestResult, string>> {\n const fqdn = await identityFqdn()\n const url = new URL(`https://${fqdn}/oauth/token`)\n url.search = new URLSearchParams(Object.entries(params)).toString()\n const res = await shopifyFetch(url.href, {method: 'POST'})\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const payload: any = await res.json()\n\n if (res.ok) return ok(payload)\n return err(payload.error)\n}\n\nfunction buildIdentityToken(result: TokenRequestResult, existingUserId?: string): IdentityToken {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const userId = existingUserId ?? (result.id_token ? jose.decodeJwt(result.id_token).sub! : undefined)\n\n if (!userId) {\n throw new BugError('Error setting userId for session. No id_token or pre-existing user ID provided.')\n }\n\n return {\n accessToken: result.access_token,\n refreshToken: result.refresh_token,\n expiresAt: new Date(Date.now() + result.expires_in * 1000),\n scopes: result.scope.split(' '),\n userId,\n }\n}\n\nfunction buildApplicationToken(result: TokenRequestResult): ApplicationToken {\n return {\n accessToken: result.access_token,\n expiresAt: new Date(Date.now() + result.expires_in * 1000),\n scopes: result.scope.split(' '),\n }\n}\n"]}
|