@shopify/cli-kit 0.0.0-snapshot-20260319110410 → 0.0.0-snapshot-20260320103300

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/api/graphql/admin/generated/find_development_theme_by_name.d.ts +16 -0
  3. package/dist/cli/api/graphql/admin/generated/find_development_theme_by_name.js +60 -0
  4. package/dist/cli/api/graphql/admin/generated/find_development_theme_by_name.js.map +1 -0
  5. package/dist/private/node/constants.d.ts +1 -0
  6. package/dist/private/node/constants.js +1 -0
  7. package/dist/private/node/constants.js.map +1 -1
  8. package/dist/private/node/session/exchange.d.ts +20 -6
  9. package/dist/private/node/session/exchange.js +31 -8
  10. package/dist/private/node/session/exchange.js.map +1 -1
  11. package/dist/private/node/session/schema.d.ts +62 -62
  12. package/dist/private/node/session/scopes.js +1 -1
  13. package/dist/private/node/session/scopes.js.map +1 -1
  14. package/dist/private/node/session/validate.d.ts +5 -4
  15. package/dist/private/node/session/validate.js +34 -7
  16. package/dist/private/node/session/validate.js.map +1 -1
  17. package/dist/private/node/session.d.ts +1 -1
  18. package/dist/private/node/session.js +68 -22
  19. package/dist/private/node/session.js.map +1 -1
  20. package/dist/private/node/testing/ui.js +1 -1
  21. package/dist/private/node/testing/ui.js.map +1 -1
  22. package/dist/private/node/ui/components/AutocompletePrompt.test.js +5 -5
  23. package/dist/private/node/ui/components/AutocompletePrompt.test.js.map +1 -1
  24. package/dist/private/node/ui/components/ConcurrentOutput.test.js +2 -2
  25. package/dist/private/node/ui/components/ConcurrentOutput.test.js.map +1 -1
  26. package/dist/private/node/ui/components/SelectInput.test.js +10 -10
  27. package/dist/private/node/ui/components/SelectInput.test.js.map +1 -1
  28. package/dist/private/node/ui/components/Tasks.test.js +6 -6
  29. package/dist/private/node/ui/components/Tasks.test.js.map +1 -1
  30. package/dist/private/node/ui/components/TextAnimation.test.js +1 -1
  31. package/dist/private/node/ui/components/TextAnimation.test.js.map +1 -1
  32. package/dist/private/node/ui/components/TextInput.test.js +4 -4
  33. package/dist/private/node/ui/components/TextInput.test.js.map +1 -1
  34. package/dist/public/common/version.d.ts +1 -1
  35. package/dist/public/common/version.js +1 -1
  36. package/dist/public/common/version.js.map +1 -1
  37. package/dist/public/node/api/rest-api-throttler.d.ts +14 -0
  38. package/dist/public/node/api/rest-api-throttler.js +14 -87
  39. package/dist/public/node/api/rest-api-throttler.js.map +1 -1
  40. package/dist/public/node/archiver.js +7 -6
  41. package/dist/public/node/archiver.js.map +1 -1
  42. package/dist/public/node/environment.d.ts +7 -7
  43. package/dist/public/node/environment.js +27 -9
  44. package/dist/public/node/environment.js.map +1 -1
  45. package/dist/public/node/hooks/prerun.js +2 -0
  46. package/dist/public/node/hooks/prerun.js.map +1 -1
  47. package/dist/public/node/session.js +3 -3
  48. package/dist/public/node/session.js.map +1 -1
  49. package/dist/public/node/themes/api.d.ts +1 -0
  50. package/dist/public/node/themes/api.js +27 -0
  51. package/dist/public/node/themes/api.js.map +1 -1
  52. package/dist/public/node/themes/theme-manager.d.ts +2 -2
  53. package/dist/public/node/themes/theme-manager.js +13 -8
  54. package/dist/public/node/themes/theme-manager.js.map +1 -1
  55. package/dist/tsconfig.tsbuildinfo +1 -1
  56. package/package.json +3 -1
package/README.md CHANGED
@@ -37,7 +37,7 @@ Learn more in the docs: [Create an app](https://shopify.dev/apps/getting-started
37
37
 
38
38
  To work with themes, the CLI needs to be installed globally with:
39
39
 
40
- - `npm install -g @shopify/cli @shopify/theme`
40
+ - `npm install -g @shopify/cli`
41
41
 
42
42
  You can also use do it through Homebrew on macOS: `brew tap shopify/shopify && brew install shopify-cli`
43
43
 
@@ -0,0 +1,16 @@
1
+ import * as Types from './types.js';
2
+ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
3
+ export type FindDevelopmentThemeByNameQueryVariables = Types.Exact<{
4
+ name: Types.Scalars['String']['input'];
5
+ }>;
6
+ export type FindDevelopmentThemeByNameQuery = {
7
+ themes?: {
8
+ nodes: {
9
+ id: string;
10
+ name: string;
11
+ role: Types.ThemeRole;
12
+ processing: boolean;
13
+ }[];
14
+ } | null;
15
+ };
16
+ export declare const FindDevelopmentThemeByName: DocumentNode<FindDevelopmentThemeByNameQuery, FindDevelopmentThemeByNameQueryVariables>;
@@ -0,0 +1,60 @@
1
+ export const FindDevelopmentThemeByName = {
2
+ kind: 'Document',
3
+ definitions: [
4
+ {
5
+ kind: 'OperationDefinition',
6
+ operation: 'query',
7
+ name: { kind: 'Name', value: 'findDevelopmentThemeByName' },
8
+ variableDefinitions: [
9
+ {
10
+ kind: 'VariableDefinition',
11
+ variable: { kind: 'Variable', name: { kind: 'Name', value: 'name' } },
12
+ type: { kind: 'NonNullType', type: { kind: 'NamedType', name: { kind: 'Name', value: 'String' } } },
13
+ },
14
+ ],
15
+ selectionSet: {
16
+ kind: 'SelectionSet',
17
+ selections: [
18
+ {
19
+ kind: 'Field',
20
+ name: { kind: 'Name', value: 'themes' },
21
+ arguments: [
22
+ { kind: 'Argument', name: { kind: 'Name', value: 'first' }, value: { kind: 'IntValue', value: '2' } },
23
+ {
24
+ kind: 'Argument',
25
+ name: { kind: 'Name', value: 'names' },
26
+ value: { kind: 'ListValue', values: [{ kind: 'Variable', name: { kind: 'Name', value: 'name' } }] },
27
+ },
28
+ {
29
+ kind: 'Argument',
30
+ name: { kind: 'Name', value: 'roles' },
31
+ value: { kind: 'ListValue', values: [{ kind: 'EnumValue', value: 'DEVELOPMENT' }] },
32
+ },
33
+ ],
34
+ selectionSet: {
35
+ kind: 'SelectionSet',
36
+ selections: [
37
+ {
38
+ kind: 'Field',
39
+ name: { kind: 'Name', value: 'nodes' },
40
+ selectionSet: {
41
+ kind: 'SelectionSet',
42
+ selections: [
43
+ { kind: 'Field', name: { kind: 'Name', value: 'id' } },
44
+ { kind: 'Field', name: { kind: 'Name', value: 'name' } },
45
+ { kind: 'Field', name: { kind: 'Name', value: 'role' } },
46
+ { kind: 'Field', name: { kind: 'Name', value: 'processing' } },
47
+ { kind: 'Field', name: { kind: 'Name', value: '__typename' } },
48
+ ],
49
+ },
50
+ },
51
+ { kind: 'Field', name: { kind: 'Name', value: '__typename' } },
52
+ ],
53
+ },
54
+ },
55
+ ],
56
+ },
57
+ },
58
+ ],
59
+ };
60
+ //# sourceMappingURL=find_development_theme_by_name.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find_development_theme_by_name.js","sourceRoot":"","sources":["../../../../../../src/cli/api/graphql/admin/generated/find_development_theme_by_name.ts"],"names":[],"mappings":"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","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 FindDevelopmentThemeByNameQueryVariables = Types.Exact<{\n name: Types.Scalars['String']['input']\n}>\n\nexport type FindDevelopmentThemeByNameQuery = {\n themes?: {nodes: {id: string; name: string; role: Types.ThemeRole; processing: boolean}[]} | null\n}\n\nexport const FindDevelopmentThemeByName = {\n kind: 'Document',\n definitions: [\n {\n kind: 'OperationDefinition',\n operation: 'query',\n name: {kind: 'Name', value: 'findDevelopmentThemeByName'},\n variableDefinitions: [\n {\n kind: 'VariableDefinition',\n variable: {kind: 'Variable', name: {kind: 'Name', value: 'name'}},\n type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'String'}}},\n },\n ],\n selectionSet: {\n kind: 'SelectionSet',\n selections: [\n {\n kind: 'Field',\n name: {kind: 'Name', value: 'themes'},\n arguments: [\n {kind: 'Argument', name: {kind: 'Name', value: 'first'}, value: {kind: 'IntValue', value: '2'}},\n {\n kind: 'Argument',\n name: {kind: 'Name', value: 'names'},\n value: {kind: 'ListValue', values: [{kind: 'Variable', name: {kind: 'Name', value: 'name'}}]},\n },\n {\n kind: 'Argument',\n name: {kind: 'Name', value: 'roles'},\n value: {kind: 'ListValue', values: [{kind: 'EnumValue', value: 'DEVELOPMENT'}]},\n },\n ],\n selectionSet: {\n kind: 'SelectionSet',\n selections: [\n {\n kind: 'Field',\n name: {kind: 'Name', value: 'nodes'},\n selectionSet: {\n kind: 'SelectionSet',\n selections: [\n {kind: 'Field', name: {kind: 'Name', value: 'id'}},\n {kind: 'Field', name: {kind: 'Name', value: 'name'}},\n {kind: 'Field', name: {kind: 'Name', value: 'role'}},\n {kind: 'Field', name: {kind: 'Name', value: 'processing'}},\n {kind: 'Field', name: {kind: 'Name', value: '__typename'}},\n ],\n },\n },\n {kind: 'Field', name: {kind: 'Name', value: '__typename'}},\n ],\n },\n },\n ],\n },\n },\n ],\n} as unknown as DocumentNode<FindDevelopmentThemeByNameQuery, FindDevelopmentThemeByNameQueryVariables>\n"]}
@@ -8,6 +8,7 @@ export declare const environmentVariables: {
8
8
  env: string;
9
9
  firstPartyDev: string;
10
10
  noAnalytics: string;
11
+ cliToken: string;
11
12
  partnersToken: string;
12
13
  runAsUser: string;
13
14
  serviceEnv: string;
@@ -18,6 +18,7 @@ export const environmentVariables = {
18
18
  env: 'SHOPIFY_CLI_ENV',
19
19
  firstPartyDev: 'SHOPIFY_CLI_1P_DEV',
20
20
  noAnalytics: 'SHOPIFY_CLI_NO_ANALYTICS',
21
+ cliToken: 'SHOPIFY_CLI_TOKEN',
21
22
  partnersToken: 'SHOPIFY_CLI_PARTNERS_TOKEN',
22
23
  runAsUser: 'SHOPIFY_RUN_AS_USER',
23
24
  serviceEnv: 'SHOPIFY_SERVICE_ENV',
@@ -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,MAAM,EAAE,oBAAoB;IAC5B,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,mEAAmE;IACnE,UAAU,EAAE,YAAY;IACxB,aAAa,EAAE,gBAAgB;IAC/B,6BAA6B,EAAE,0CAA0C;IACzE,MAAM,EAAE,sBAAsB;IAC9B,UAAU,EAAE,aAAa;IACzB,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;IAC3D,IAAI,EAAE,mBAAmB;IACzB,mBAAmB,EAAE,oCAAoC;IACzD,qBAAqB,EAAE,sCAAsC;IAC7D,6BAA6B,EAAE,gDAAgD;CAChF,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;AAElE,MAAM,CAAC,MAAM,oBAAoB,GAC/B,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,IAAI,2BAA2B,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 doctor: 'SHOPIFY_CLI_DOCTOR',\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 // 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 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 json: 'SHOPIFY_FLAG_JSON',\n neverUsePartnersApi: 'SHOPIFY_CLI_NEVER_USE_PARTNERS_API',\n skipNetworkLevelRetry: 'SHOPIFY_CLI_SKIP_NETWORK_LEVEL_RETRY',\n maxRequestTimeForNetworkCalls: 'SHOPIFY_CLI_MAX_REQUEST_TIME_FOR_NETWORK_CALLS',\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\nexport const themeKitAccessDomain =\n process.env[environmentVariables.themeKitAccessDomain] ?? defaultThemeKitAccessDomain\n"]}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/private/node/constants.ts"],"names":[],"mappings":"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","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 doctor: 'SHOPIFY_CLI_DOCTOR',\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 cliToken: 'SHOPIFY_CLI_TOKEN',\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 // 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 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 json: 'SHOPIFY_FLAG_JSON',\n neverUsePartnersApi: 'SHOPIFY_CLI_NEVER_USE_PARTNERS_API',\n skipNetworkLevelRetry: 'SHOPIFY_CLI_SKIP_NETWORK_LEVEL_RETRY',\n maxRequestTimeForNetworkCalls: 'SHOPIFY_CLI_MAX_REQUEST_TIME_FOR_NETWORK_CALLS',\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\nexport const themeKitAccessDomain =\n process.env[environmentVariables.themeKitAccessDomain] ?? defaultThemeKitAccessDomain\n"]}
@@ -6,14 +6,28 @@ export declare class InvalidGrantError extends ExtendableError {
6
6
  }
7
7
  export declare class InvalidRequestError extends ExtendableError {
8
8
  }
9
+ export interface ExchangeScopes {
10
+ admin: string[];
11
+ partners: string[];
12
+ storefront: string[];
13
+ businessPlatform: string[];
14
+ appManagement: string[];
15
+ }
16
+ /**
17
+ * Given an identity token, request an application token.
18
+ * @param identityToken - access token obtained in a previous step
19
+ * @param store - the store to use, only needed for admin API
20
+ * @returns An array with the application access tokens.
21
+ */
22
+ export declare function exchangeAccessForApplicationTokens(identityToken: IdentityToken, scopes: ExchangeScopes, store?: string): Promise<Record<string, ApplicationToken>>;
9
23
  /**
10
24
  * Given an expired access token, refresh it to get a new one.
11
25
  */
12
26
  export declare function refreshAccessToken(currentToken: IdentityToken): Promise<IdentityToken>;
13
27
  /**
14
- * Given a custom CLI token passed as ENV variable, request a valid Partners API token
28
+ * Given a custom CLI token passed as ENV variable, request a valid Partners API token.
15
29
  * This token does not accept extra scopes, just the cli one.
16
- * @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_PARTNERS_TOKEN`
30
+ * @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_TOKEN`
17
31
  * @returns An instance with the application access tokens.
18
32
  */
19
33
  export declare function exchangeCustomPartnerToken(token: string): Promise<{
@@ -21,8 +35,8 @@ export declare function exchangeCustomPartnerToken(token: string): Promise<{
21
35
  userId: string;
22
36
  }>;
23
37
  /**
24
- * Given a custom CLI token passed as ENV variable, request a valid App Management API token
25
- * @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_PARTNERS_TOKEN`
38
+ * Given a custom CLI token passed as ENV variable, request a valid App Management API token.
39
+ * @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_TOKEN`
26
40
  * @returns An instance with the application access tokens.
27
41
  */
28
42
  export declare function exchangeCliTokenForAppManagementAccessToken(token: string): Promise<{
@@ -30,8 +44,8 @@ export declare function exchangeCliTokenForAppManagementAccessToken(token: strin
30
44
  userId: string;
31
45
  }>;
32
46
  /**
33
- * Given a custom CLI token passed as ENV variable, request a valid Business Platform API token
34
- * @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_PARTNERS_TOKEN`
47
+ * Given a custom CLI token passed as ENV variable, request a valid Business Platform API token.
48
+ * @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_TOKEN`
35
49
  * @returns An instance with the application access tokens.
36
50
  */
37
51
  export declare function exchangeCliTokenForBusinessPlatformAccessToken(token: string): Promise<{
@@ -13,6 +13,29 @@ export class InvalidRequestError extends ExtendableError {
13
13
  }
14
14
  class InvalidTargetError extends AbortError {
15
15
  }
16
+ /**
17
+ * Given an identity token, request an application token.
18
+ * @param identityToken - access token obtained in a previous step
19
+ * @param store - the store to use, only needed for admin API
20
+ * @returns An array with the application access tokens.
21
+ */
22
+ export async function exchangeAccessForApplicationTokens(identityToken, scopes, store) {
23
+ const token = identityToken.accessToken;
24
+ const [partners, storefront, businessPlatform, admin, appManagement] = await Promise.all([
25
+ requestAppToken('partners', token, scopes.partners),
26
+ requestAppToken('storefront-renderer', token, scopes.storefront),
27
+ requestAppToken('business-platform', token, scopes.businessPlatform),
28
+ store ? requestAppToken('admin', token, scopes.admin, store) : {},
29
+ requestAppToken('app-management', token, scopes.appManagement),
30
+ ]);
31
+ return {
32
+ ...partners,
33
+ ...storefront,
34
+ ...businessPlatform,
35
+ ...admin,
36
+ ...appManagement,
37
+ };
38
+ }
16
39
  /**
17
40
  * Given an expired access token, refresh it to get a new one.
18
41
  */
@@ -29,8 +52,8 @@ export async function refreshAccessToken(currentToken) {
29
52
  return buildIdentityToken(value, currentToken.userId, currentToken.alias);
30
53
  }
31
54
  /**
32
- * Given a custom CLI token passed as ENV variable request a valid API access token
33
- * @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_PARTNERS_TOKEN`
55
+ * Given a custom CLI token passed as ENV variable, request a valid API access token.
56
+ * @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_TOKEN`
34
57
  * @param apiName - The API to exchange for the access token
35
58
  * @param scopes - The scopes to request with the access token
36
59
  * @returns An instance with the application access tokens.
@@ -51,25 +74,25 @@ async function exchangeCliTokenForAccessToken(apiName, token, scopes) {
51
74
  }
52
75
  }
53
76
  /**
54
- * Given a custom CLI token passed as ENV variable, request a valid Partners API token
77
+ * Given a custom CLI token passed as ENV variable, request a valid Partners API token.
55
78
  * This token does not accept extra scopes, just the cli one.
56
- * @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_PARTNERS_TOKEN`
79
+ * @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_TOKEN`
57
80
  * @returns An instance with the application access tokens.
58
81
  */
59
82
  export async function exchangeCustomPartnerToken(token) {
60
83
  return exchangeCliTokenForAccessToken('partners', token, tokenExchangeScopes('partners'));
61
84
  }
62
85
  /**
63
- * Given a custom CLI token passed as ENV variable, request a valid App Management API token
64
- * @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_PARTNERS_TOKEN`
86
+ * Given a custom CLI token passed as ENV variable, request a valid App Management API token.
87
+ * @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_TOKEN`
65
88
  * @returns An instance with the application access tokens.
66
89
  */
67
90
  export async function exchangeCliTokenForAppManagementAccessToken(token) {
68
91
  return exchangeCliTokenForAccessToken('app-management', token, tokenExchangeScopes('app-management'));
69
92
  }
70
93
  /**
71
- * Given a custom CLI token passed as ENV variable, request a valid Business Platform API token
72
- * @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_PARTNERS_TOKEN`
94
+ * Given a custom CLI token passed as ENV variable, request a valid Business Platform API token.
95
+ * @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_TOKEN`
73
96
  * @returns An instance with the application access tokens.
74
97
  */
75
98
  export async function exchangeCliTokenForBusinessPlatformAccessToken(token) {
@@ -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 {tokenExchangeScopes} from './scopes.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 {nonRandomUUID} from '../../../public/node/crypto.js'\n\nimport * as jose from 'jose'\n\nexport class InvalidGrantError extends ExtendableError {}\nexport class InvalidRequestError extends ExtendableError {}\nclass InvalidTargetError extends AbortError {}\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, currentToken.alias)\n}\n\n/**\n * Given a custom CLI token passed as ENV variable request a valid API access token\n * @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_PARTNERS_TOKEN`\n * @param apiName - The API to exchange for the access token\n * @param scopes - The scopes to request with the access token\n * @returns An instance with the application access tokens.\n */\nasync function exchangeCliTokenForAccessToken(\n apiName: API,\n token: string,\n scopes: string[],\n): Promise<{accessToken: string; userId: string}> {\n const appId = applicationId(apiName)\n try {\n const newToken = await requestAppToken(apiName, token, scopes)\n\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 const prettyName = apiName.replace(/-/g, ' ').replace(/\\b\\w/g, (char) => char.toUpperCase())\n throw new AbortError(\n `The custom token provided can't be used for the ${prettyName} API.`,\n 'Ensure the token is correct and not expired.',\n )\n }\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 `SHOPIFY_CLI_PARTNERS_TOKEN`\n * @returns An instance with the application access tokens.\n */\nexport async function exchangeCustomPartnerToken(token: string): Promise<{accessToken: string; userId: string}> {\n return exchangeCliTokenForAccessToken('partners', token, tokenExchangeScopes('partners'))\n}\n\n/**\n * Given a custom CLI token passed as ENV variable, request a valid App Management API token\n * @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_PARTNERS_TOKEN`\n * @returns An instance with the application access tokens.\n */\nexport async function exchangeCliTokenForAppManagementAccessToken(\n token: string,\n): Promise<{accessToken: string; userId: string}> {\n return exchangeCliTokenForAccessToken('app-management', token, tokenExchangeScopes('app-management'))\n}\n\n/**\n * Given a custom CLI token passed as ENV variable, request a valid Business Platform API token\n * @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_PARTNERS_TOKEN`\n * @returns An instance with the application access tokens.\n */\nexport async function exchangeCliTokenForBusinessPlatformAccessToken(\n token: string,\n): Promise<{accessToken: string; userId: string}> {\n return exchangeCliTokenForAccessToken('business-platform', token, tokenExchangeScopes('business-platform'))\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.error as IdentityDeviceError)\n }\n const identityToken = buildIdentityToken(tokenResult.value)\n return ok(identityToken)\n}\n\nexport async function requestAppToken(\n api: API,\n token: string,\n scopes: string[] = [],\n store?: string,\n): Promise<Record<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`, store}),\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, store}: {error: string; store?: string}) {\n const invalidTargetErrorMessage = `You are not authorized to use the CLI to develop in the provided store${\n store ? `: ${store}` : '.'\n }`\n\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 'Ensure you have logged in to the store using the Shopify admin at least once.',\n 'Ensure you are the store owner, or have a staff account if you are attempting to log in to a dev store.',\n 'Ensure you are using the permanent store domain, not a vanity domain.',\n ])\n }\n // eslint-disable-next-line @shopify/cli/no-error-factory-functions\n return new AbortError(error)\n}\n\nasync function tokenRequest(\n params: Record<string, string>,\n): Promise<Result<TokenRequestResult, {error: string; store?: 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\n const res = await shopifyFetch(url.href, {method: 'POST'})\n try {\n const responseText = await res.text()\n\n const payload = JSON.parse(responseText)\n if (res.ok) return ok(payload)\n\n return err({error: payload.error, store: params.store})\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new AbortError(\n `Received invalid response from authentication service (HTTP ${res.status}).`,\n 'The response could not be parsed as JSON. The service may be temporarily unavailable. Please try again.',\n )\n }\n throw error\n }\n}\n\nfunction buildIdentityToken(\n result: TokenRequestResult,\n existingUserId?: string,\n existingAlias?: string,\n): 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 alias: existingAlias,\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 {tokenExchangeScopes} from './scopes.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 {nonRandomUUID} from '../../../public/node/crypto.js'\n\nimport * as jose from 'jose'\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<Record<string, ApplicationToken>> {\n const token = identityToken.accessToken\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 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, currentToken.alias)\n}\n\n/**\n * Given a custom CLI token passed as ENV variable, request a valid API access token.\n * @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_TOKEN`\n * @param apiName - The API to exchange for the access token\n * @param scopes - The scopes to request with the access token\n * @returns An instance with the application access tokens.\n */\nasync function exchangeCliTokenForAccessToken(\n apiName: API,\n token: string,\n scopes: string[],\n): Promise<{accessToken: string; userId: string}> {\n const appId = applicationId(apiName)\n try {\n const newToken = await requestAppToken(apiName, token, scopes)\n\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 const prettyName = apiName.replace(/-/g, ' ').replace(/\\b\\w/g, (char) => char.toUpperCase())\n throw new AbortError(\n `The custom token provided can't be used for the ${prettyName} API.`,\n 'Ensure the token is correct and not expired.',\n )\n }\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 `SHOPIFY_CLI_TOKEN`\n * @returns An instance with the application access tokens.\n */\nexport async function exchangeCustomPartnerToken(token: string): Promise<{accessToken: string; userId: string}> {\n return exchangeCliTokenForAccessToken('partners', token, tokenExchangeScopes('partners'))\n}\n\n/**\n * Given a custom CLI token passed as ENV variable, request a valid App Management API token.\n * @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_TOKEN`\n * @returns An instance with the application access tokens.\n */\nexport async function exchangeCliTokenForAppManagementAccessToken(\n token: string,\n): Promise<{accessToken: string; userId: string}> {\n return exchangeCliTokenForAccessToken('app-management', token, tokenExchangeScopes('app-management'))\n}\n\n/**\n * Given a custom CLI token passed as ENV variable, request a valid Business Platform API token.\n * @param token - The CLI token passed as ENV variable `SHOPIFY_CLI_TOKEN`\n * @returns An instance with the application access tokens.\n */\nexport async function exchangeCliTokenForBusinessPlatformAccessToken(\n token: string,\n): Promise<{accessToken: string; userId: string}> {\n return exchangeCliTokenForAccessToken('business-platform', token, tokenExchangeScopes('business-platform'))\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.error as IdentityDeviceError)\n }\n const identityToken = buildIdentityToken(tokenResult.value)\n return ok(identityToken)\n}\n\nexport async function requestAppToken(\n api: API,\n token: string,\n scopes: string[] = [],\n store?: string,\n): Promise<Record<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`, store}),\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, store}: {error: string; store?: string}) {\n const invalidTargetErrorMessage = `You are not authorized to use the CLI to develop in the provided store${\n store ? `: ${store}` : '.'\n }`\n\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 'Ensure you have logged in to the store using the Shopify admin at least once.',\n 'Ensure you are the store owner, or have a staff account if you are attempting to log in to a dev store.',\n 'Ensure you are using the permanent store domain, not a vanity domain.',\n ])\n }\n // eslint-disable-next-line @shopify/cli/no-error-factory-functions\n return new AbortError(error)\n}\n\nasync function tokenRequest(\n params: Record<string, string>,\n): Promise<Result<TokenRequestResult, {error: string; store?: 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\n const res = await shopifyFetch(url.href, {method: 'POST'})\n try {\n const responseText = await res.text()\n\n const payload = JSON.parse(responseText)\n if (res.ok) return ok(payload)\n\n return err({error: payload.error, store: params.store})\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new AbortError(\n `Received invalid response from authentication service (HTTP ${res.status}).`,\n 'The response could not be parsed as JSON. The service may be temporarily unavailable. Please try again.',\n )\n }\n throw error\n }\n}\n\nfunction buildIdentityToken(\n result: TokenRequestResult,\n existingUserId?: string,\n existingAlias?: string,\n): 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 alias: existingAlias,\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"]}