shopify 3.93.2 → 3.94.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/dist/assets/dev-console/extensions/dev-console/assets/index-Bm_GpKQW.js +51 -0
  2. package/dist/assets/dev-console/index.html +1 -1
  3. package/dist/assets/hydrogen/starter/CHANGELOG.md +0 -64
  4. package/dist/assets/hydrogen/starter/app/components/Aside.tsx +2 -4
  5. package/dist/assets/hydrogen/starter/app/components/CartMain.tsx +3 -6
  6. package/dist/assets/hydrogen/starter/app/components/CartSummary.tsx +23 -117
  7. package/dist/assets/hydrogen/starter/app/components/Header.tsx +3 -3
  8. package/dist/assets/hydrogen/starter/app/components/PaginatedResourceSection.tsx +4 -24
  9. package/dist/assets/hydrogen/starter/app/components/ProductPrice.tsx +1 -1
  10. package/dist/assets/hydrogen/starter/app/routes/[robots.txt].tsx +53 -14
  11. package/dist/assets/hydrogen/starter/app/routes/_index.tsx +4 -11
  12. package/dist/assets/hydrogen/starter/app/routes/account.$.tsx +1 -1
  13. package/dist/assets/hydrogen/starter/app/routes/account.addresses.tsx +2 -2
  14. package/dist/assets/hydrogen/starter/app/routes/account.profile.tsx +1 -1
  15. package/dist/assets/hydrogen/starter/app/routes/api.$version.[graphql.json].tsx +14 -0
  16. package/dist/assets/hydrogen/starter/package.json +5 -5
  17. package/dist/assets/hydrogen/starter/storefrontapi.generated.d.ts +11 -0
  18. package/dist/assets/hydrogen/starter/vite.config.ts +1 -1
  19. package/dist/assets/hydrogen/vite/vite.config.js +1 -1
  20. package/dist/{chunk-5FCKEHCK.js → chunk-3CRQIN6A.js} +154 -154
  21. package/dist/{chunk-4VZV4LQX.js → chunk-3TG7H626.js} +66 -66
  22. package/dist/chunk-52KHWFYF.js +1 -0
  23. package/dist/{chunk-IG47ZDRU.js → chunk-6OKIHCZG.js} +1 -1
  24. package/dist/chunk-7FYGRWMW.js +415 -0
  25. package/dist/{chunk-MX6WWR5F.js → chunk-D24XVLOA.js} +16 -16
  26. package/dist/chunk-EU23C3Y3.js +3 -0
  27. package/dist/chunk-FU2Y2M3M.js +5 -0
  28. package/dist/chunk-JBSYWYIP.js +2 -0
  29. package/dist/chunk-QYR5VPQA.js +4 -0
  30. package/dist/{chunk-XVFYDYZA.js → chunk-SVA22NZQ.js} +209 -211
  31. package/dist/cli/commands/config/autoupgrade/constants.d.ts +5 -0
  32. package/dist/cli/commands/config/autoupgrade/constants.js +6 -0
  33. package/dist/cli/commands/config/autoupgrade/off.d.ts +7 -0
  34. package/dist/cli/commands/config/autoupgrade/off.js +22 -0
  35. package/dist/cli/commands/config/autoupgrade/on.d.ts +7 -0
  36. package/dist/cli/commands/config/autoupgrade/on.js +22 -0
  37. package/dist/cli/commands/config/autoupgrade/status.d.ts +7 -0
  38. package/dist/cli/commands/config/autoupgrade/status.js +30 -0
  39. package/dist/cli/commands/docs/generate.d.ts +1 -1
  40. package/dist/cli/commands/docs/generate.js +6 -3
  41. package/dist/cli/commands/upgrade.js +3 -1
  42. package/dist/cli/services/kitchen-sink/static.js +1 -1
  43. package/dist/configs/all.yml +3 -0
  44. package/dist/configs/recommended.yml +3 -0
  45. package/dist/data/filters.json +30 -0
  46. package/dist/data/objects.json +17 -1
  47. package/dist/data/setting.json +25 -0
  48. package/dist/data/shopify_system_translations.json +29 -6
  49. package/dist/error-handler-YQEGKTYS.js +1 -0
  50. package/dist/hooks/postrun.js +1 -1
  51. package/dist/hooks/prerun.js +1 -1
  52. package/dist/{http-proxy-node16-DSQMBVDI.js → http-proxy-node16-TTURN6MD.js} +1 -1
  53. package/dist/index.js +1117 -1121
  54. package/dist/lib-3WHF5XD3.js +1 -0
  55. package/dist/{local-WHQ3ZS4K.js → local-J5FE2ICC.js} +1 -1
  56. package/dist/{morph-Q32V442A.js → morph-DQREIZD2.js} +1 -1
  57. package/dist/node-package-manager-AKAMTDCS.js +1 -0
  58. package/dist/path-HUAU3YBW.js +1 -0
  59. package/dist/tsconfig.tsbuildinfo +1 -1
  60. package/dist/{ui-GZ7DOSHP.js → ui-65JEOETJ.js} +1 -1
  61. package/dist/{workerd-LJU6AVMQ.js → workerd-2QD5AUPI.js} +1 -1
  62. package/oclif.manifest.json +65 -4
  63. package/package.json +8 -7
  64. package/dist/assets/dev-console/extensions/dev-console/assets/index-BnXVL6nA.js +0 -78
  65. package/dist/chunk-4QL77VYJ.js +0 -415
  66. package/dist/chunk-DDTYWTF2.js +0 -1
  67. package/dist/chunk-FYQIRCLV.js +0 -5
  68. package/dist/chunk-NOSKVZWJ.js +0 -2
  69. package/dist/chunk-QJEBL3WX.js +0 -4
  70. package/dist/cli/commands/store/auth.d.ts +0 -15
  71. package/dist/cli/commands/store/auth.js +0 -46
  72. package/dist/cli/commands/store/execute.d.ts +0 -21
  73. package/dist/cli/commands/store/execute.js +0 -89
  74. package/dist/cli/services/store/auth/callback.d.ts +0 -8
  75. package/dist/cli/services/store/auth/callback.js +0 -140
  76. package/dist/cli/services/store/auth/config.d.ts +0 -6
  77. package/dist/cli/services/store/auth/config.js +0 -15
  78. package/dist/cli/services/store/auth/existing-scopes.d.ts +0 -5
  79. package/dist/cli/services/store/auth/existing-scopes.js +0 -40
  80. package/dist/cli/services/store/auth/index.d.ts +0 -18
  81. package/dist/cli/services/store/auth/index.js +0 -88
  82. package/dist/cli/services/store/auth/pkce.d.ts +0 -36
  83. package/dist/cli/services/store/auth/pkce.js +0 -49
  84. package/dist/cli/services/store/auth/recovery.d.ts +0 -4
  85. package/dist/cli/services/store/auth/recovery.js +0 -17
  86. package/dist/cli/services/store/auth/result.d.ts +0 -24
  87. package/dist/cli/services/store/auth/result.js +0 -39
  88. package/dist/cli/services/store/auth/scopes.d.ts +0 -4
  89. package/dist/cli/services/store/auth/scopes.js +0 -53
  90. package/dist/cli/services/store/auth/session-lifecycle.d.ts +0 -3
  91. package/dist/cli/services/store/auth/session-lifecycle.js +0 -69
  92. package/dist/cli/services/store/auth/session-store.d.ts +0 -32
  93. package/dist/cli/services/store/auth/session-store.js +0 -127
  94. package/dist/cli/services/store/auth/token-client.d.ts +0 -40
  95. package/dist/cli/services/store/auth/token-client.js +0 -95
  96. package/dist/cli/services/store/execute/admin-context.d.ts +0 -11
  97. package/dist/cli/services/store/execute/admin-context.js +0 -41
  98. package/dist/cli/services/store/execute/admin-transport.d.ts +0 -6
  99. package/dist/cli/services/store/execute/admin-transport.js +0 -42
  100. package/dist/cli/services/store/execute/index.d.ts +0 -13
  101. package/dist/cli/services/store/execute/index.js +0 -22
  102. package/dist/cli/services/store/execute/request.d.ts +0 -21
  103. package/dist/cli/services/store/execute/request.js +0 -88
  104. package/dist/cli/services/store/execute/result.d.ts +0 -3
  105. package/dist/cli/services/store/execute/result.js +0 -29
  106. package/dist/cli/services/store/execute/targets.d.ts +0 -18
  107. package/dist/cli/services/store/execute/targets.js +0 -21
  108. package/dist/error-handler-GZ2I7BG5.js +0 -1
  109. package/dist/lib-GGVLMXY5.js +0 -1
  110. package/dist/node-package-manager-6XMPTNUI.js +0 -1
  111. package/dist/path-IT7KPARG.js +0 -1
@@ -1,88 +0,0 @@
1
- import { normalizeStoreFqdn } from '@shopify/cli-kit/node/context/fqdn';
2
- import { AbortError } from '@shopify/cli-kit/node/error';
3
- import { outputContent, outputDebug, outputToken } from '@shopify/cli-kit/node/output';
4
- import { openURL } from '@shopify/cli-kit/node/system';
5
- import { STORE_AUTH_APP_CLIENT_ID } from './config.js';
6
- import { setStoredStoreAppSession } from './session-store.js';
7
- import { exchangeStoreAuthCodeForToken } from './token-client.js';
8
- import { waitForStoreAuthCode } from './callback.js';
9
- import { createPkceBootstrap } from './pkce.js';
10
- import { mergeRequestedAndStoredScopes, parseStoreAuthScopes, resolveGrantedScopes } from './scopes.js';
11
- import { resolveExistingStoreAuthScopes } from './existing-scopes.js';
12
- import { createStoreAuthPresenter } from './result.js';
13
- const defaultStoreAuthDependencies = {
14
- openURL,
15
- waitForStoreAuthCode,
16
- exchangeStoreAuthCodeForToken,
17
- resolveExistingScopes: resolveExistingStoreAuthScopes,
18
- presenter: createStoreAuthPresenter('text'),
19
- };
20
- export async function authenticateStoreWithApp(input, dependencies = {}) {
21
- const resolvedDependencies = { ...defaultStoreAuthDependencies, ...dependencies };
22
- const store = normalizeStoreFqdn(input.store);
23
- const requestedScopes = parseStoreAuthScopes(input.scopes);
24
- const existingScopeResolution = await resolvedDependencies.resolveExistingScopes(store);
25
- const scopes = mergeRequestedAndStoredScopes(requestedScopes, existingScopeResolution.scopes);
26
- const validationScopes = existingScopeResolution.authoritative ? scopes : requestedScopes;
27
- if (existingScopeResolution.scopes.length > 0) {
28
- outputDebug(outputContent `Merged requested scopes ${outputToken.raw(requestedScopes.join(','))} with existing scopes ${outputToken.raw(existingScopeResolution.scopes.join(','))} for ${outputToken.raw(store)}`);
29
- }
30
- const bootstrap = createPkceBootstrap({
31
- store,
32
- scopes,
33
- exchangeCodeForToken: resolvedDependencies.exchangeStoreAuthCodeForToken,
34
- });
35
- const { authorization: { authorizationUrl }, } = bootstrap;
36
- resolvedDependencies.presenter.openingBrowser();
37
- const code = await resolvedDependencies.waitForStoreAuthCode({
38
- ...bootstrap.waitForAuthCodeOptions,
39
- onListening: async () => {
40
- const opened = await resolvedDependencies.openURL(authorizationUrl);
41
- if (!opened)
42
- resolvedDependencies.presenter.manualAuthUrl(authorizationUrl);
43
- },
44
- });
45
- const tokenResponse = await bootstrap.exchangeCodeForToken(code);
46
- const userId = tokenResponse.associated_user?.id?.toString();
47
- if (!userId) {
48
- throw new AbortError('Shopify did not return associated user information for the online access token.');
49
- }
50
- const now = Date.now();
51
- const expiresAt = tokenResponse.expires_in ? new Date(now + tokenResponse.expires_in * 1000).toISOString() : undefined;
52
- const result = {
53
- store,
54
- userId,
55
- scopes: resolveGrantedScopes(tokenResponse, validationScopes),
56
- acquiredAt: new Date(now).toISOString(),
57
- expiresAt,
58
- refreshTokenExpiresAt: tokenResponse.refresh_token_expires_in
59
- ? new Date(now + tokenResponse.refresh_token_expires_in * 1000).toISOString()
60
- : undefined,
61
- hasRefreshToken: !!tokenResponse.refresh_token,
62
- associatedUser: tokenResponse.associated_user
63
- ? {
64
- id: tokenResponse.associated_user.id,
65
- email: tokenResponse.associated_user.email,
66
- firstName: tokenResponse.associated_user.first_name,
67
- lastName: tokenResponse.associated_user.last_name,
68
- accountOwner: tokenResponse.associated_user.account_owner,
69
- }
70
- : undefined,
71
- };
72
- setStoredStoreAppSession({
73
- store,
74
- clientId: STORE_AUTH_APP_CLIENT_ID,
75
- userId,
76
- accessToken: tokenResponse.access_token,
77
- refreshToken: tokenResponse.refresh_token,
78
- scopes: result.scopes,
79
- acquiredAt: result.acquiredAt,
80
- expiresAt,
81
- refreshTokenExpiresAt: result.refreshTokenExpiresAt,
82
- associatedUser: result.associatedUser,
83
- });
84
- outputDebug(outputContent `Session persisted for ${outputToken.raw(store)} (user ${outputToken.raw(userId)}, expires ${outputToken.raw(expiresAt ?? 'unknown')})`);
85
- resolvedDependencies.presenter.success(result);
86
- return result;
87
- }
88
- //# sourceMappingURL=index.js.map
@@ -1,36 +0,0 @@
1
- import type { StoreTokenResponse } from './token-client.js';
2
- import type { WaitForAuthCodeOptions } from './callback.js';
3
- interface StoreAuthorizationContext {
4
- store: string;
5
- scopes: string[];
6
- state: string;
7
- port: number;
8
- redirectUri: string;
9
- authorizationUrl: string;
10
- codeVerifier: string;
11
- }
12
- interface StoreAuthBootstrap {
13
- authorization: StoreAuthorizationContext;
14
- waitForAuthCodeOptions: WaitForAuthCodeOptions;
15
- exchangeCodeForToken: (code: string) => Promise<StoreTokenResponse>;
16
- }
17
- export declare function generateCodeVerifier(): string;
18
- export declare function computeCodeChallenge(verifier: string): string;
19
- export declare function buildStoreAuthUrl(options: {
20
- store: string;
21
- scopes: string[];
22
- state: string;
23
- redirectUri: string;
24
- codeChallenge: string;
25
- }): string;
26
- export declare function createPkceBootstrap(options: {
27
- store: string;
28
- scopes: string[];
29
- exchangeCodeForToken: (options: {
30
- store: string;
31
- code: string;
32
- codeVerifier: string;
33
- redirectUri: string;
34
- }) => Promise<StoreTokenResponse>;
35
- }): StoreAuthBootstrap;
36
- export {};
@@ -1,49 +0,0 @@
1
- import { randomUUID } from '@shopify/cli-kit/node/crypto';
2
- import { outputContent, outputDebug, outputToken } from '@shopify/cli-kit/node/output';
3
- import { createHash, randomBytes } from 'crypto';
4
- import { DEFAULT_STORE_AUTH_PORT, STORE_AUTH_APP_CLIENT_ID, storeAuthRedirectUri } from './config.js';
5
- export function generateCodeVerifier() {
6
- return randomBytes(32).toString('base64url');
7
- }
8
- export function computeCodeChallenge(verifier) {
9
- return createHash('sha256').update(verifier).digest('base64url');
10
- }
11
- export function buildStoreAuthUrl(options) {
12
- const params = new URLSearchParams();
13
- params.set('client_id', STORE_AUTH_APP_CLIENT_ID);
14
- params.set('scope', options.scopes.join(','));
15
- params.set('redirect_uri', options.redirectUri);
16
- params.set('state', options.state);
17
- params.set('response_type', 'code');
18
- params.set('code_challenge', options.codeChallenge);
19
- params.set('code_challenge_method', 'S256');
20
- return `https://${options.store}/admin/oauth/authorize?${params.toString()}`;
21
- }
22
- export function createPkceBootstrap(options) {
23
- const { store, scopes, exchangeCodeForToken } = options;
24
- const port = DEFAULT_STORE_AUTH_PORT;
25
- const state = randomUUID();
26
- const redirectUri = storeAuthRedirectUri(port);
27
- const codeVerifier = generateCodeVerifier();
28
- const codeChallenge = computeCodeChallenge(codeVerifier);
29
- const authorizationUrl = buildStoreAuthUrl({ store, scopes, state, redirectUri, codeChallenge });
30
- outputDebug(outputContent `Starting PKCE auth for ${outputToken.raw(store)} with scopes ${outputToken.raw(scopes.join(','))} (redirect_uri=${outputToken.raw(redirectUri)})`);
31
- return {
32
- authorization: {
33
- store,
34
- scopes,
35
- state,
36
- port,
37
- redirectUri,
38
- authorizationUrl,
39
- codeVerifier,
40
- },
41
- waitForAuthCodeOptions: {
42
- store,
43
- state,
44
- port,
45
- },
46
- exchangeCodeForToken: (code) => exchangeCodeForToken({ store, code, codeVerifier, redirectUri }),
47
- };
48
- }
49
- //# sourceMappingURL=pkce.js.map
@@ -1,4 +0,0 @@
1
- import { AbortError } from '@shopify/cli-kit/node/error';
2
- export declare function createStoredStoreAuthError(store: string): AbortError;
3
- export declare function reauthenticateStoreAuthError(message: string, store: string, scopes: string): AbortError;
4
- export declare function retryStoreAuthWithPermanentDomainError(returnedStore: string): AbortError;
@@ -1,17 +0,0 @@
1
- import { AbortError } from '@shopify/cli-kit/node/error';
2
- function storeAuthCommand(store, scopes) {
3
- return { command: `shopify store auth --store ${store} --scopes ${scopes}` };
4
- }
5
- function storeAuthCommandNextSteps(store, scopes) {
6
- return [[storeAuthCommand(store, scopes)]];
7
- }
8
- export function createStoredStoreAuthError(store) {
9
- return new AbortError(`No stored app authentication found for ${store}.`, 'To create stored auth for this store, run:', storeAuthCommandNextSteps(store, '<comma-separated-scopes>'));
10
- }
11
- export function reauthenticateStoreAuthError(message, store, scopes) {
12
- return new AbortError(message, 'To re-authenticate, run:', storeAuthCommandNextSteps(store, scopes));
13
- }
14
- export function retryStoreAuthWithPermanentDomainError(returnedStore) {
15
- return new AbortError('OAuth callback store does not match the requested store.', `Shopify returned ${returnedStore} during authentication. Re-run using the permanent store domain:`, storeAuthCommandNextSteps(returnedStore, '<comma-separated-scopes>'));
16
- }
17
- //# sourceMappingURL=recovery.js.map
@@ -1,24 +0,0 @@
1
- export interface StoreAuthResult {
2
- store: string;
3
- userId: string;
4
- scopes: string[];
5
- acquiredAt: string;
6
- expiresAt?: string;
7
- refreshTokenExpiresAt?: string;
8
- hasRefreshToken: boolean;
9
- associatedUser?: {
10
- id: number;
11
- email?: string;
12
- firstName?: string;
13
- lastName?: string;
14
- accountOwner?: boolean;
15
- };
16
- }
17
- type StoreAuthOutputFormat = 'text' | 'json';
18
- export interface StoreAuthPresenter {
19
- openingBrowser: () => void;
20
- manualAuthUrl: (authorizationUrl: string) => void;
21
- success: (result: StoreAuthResult) => void;
22
- }
23
- export declare function createStoreAuthPresenter(format?: StoreAuthOutputFormat): StoreAuthPresenter;
24
- export {};
@@ -1,39 +0,0 @@
1
- import { outputCompleted, outputInfo, outputResult, outputToken, outputContent } from '@shopify/cli-kit/node/output';
2
- function serializeStoreAuthResult(result) {
3
- return JSON.stringify(result, null, 2);
4
- }
5
- function buildStoreAuthSuccessText(result) {
6
- const displayName = result.associatedUser?.email ? ` as ${result.associatedUser.email}` : '';
7
- return {
8
- completed: ['Logged in.', `Authenticated${displayName} against ${result.store}.`],
9
- info: ['', 'To verify that authentication worked, run:', `shopify store execute --store ${result.store} --query 'query { shop { name id } }'`],
10
- };
11
- }
12
- function displayStoreAuthOpeningBrowser() {
13
- outputInfo('Shopify CLI will open the app authorization page in your browser.');
14
- outputInfo('');
15
- }
16
- function displayStoreAuthManualAuthUrl(authorizationUrl) {
17
- outputInfo('Browser did not open automatically. Open this URL manually:');
18
- outputInfo(outputContent `${outputToken.link(authorizationUrl)}`);
19
- outputInfo('');
20
- }
21
- function displayStoreAuthResult(result, format = 'text') {
22
- if (format === 'json') {
23
- outputResult(serializeStoreAuthResult(result));
24
- return;
25
- }
26
- const text = buildStoreAuthSuccessText(result);
27
- text.completed.forEach((line) => outputCompleted(line));
28
- text.info.forEach((line) => outputInfo(line));
29
- }
30
- export function createStoreAuthPresenter(format = 'text') {
31
- return {
32
- openingBrowser: displayStoreAuthOpeningBrowser,
33
- manualAuthUrl: displayStoreAuthManualAuthUrl,
34
- success(result) {
35
- displayStoreAuthResult(result, format);
36
- },
37
- };
38
- }
39
- //# sourceMappingURL=result.js.map
@@ -1,4 +0,0 @@
1
- import type { StoreTokenResponse } from './token-client.js';
2
- export declare function parseStoreAuthScopes(input: string): string[];
3
- export declare function mergeRequestedAndStoredScopes(requestedScopes: string[], storedScopes: string[]): string[];
4
- export declare function resolveGrantedScopes(tokenResponse: StoreTokenResponse, requestedScopes: string[]): string[];
@@ -1,53 +0,0 @@
1
- import { AbortError } from '@shopify/cli-kit/node/error';
2
- import { outputContent, outputDebug } from '@shopify/cli-kit/node/output';
3
- export function parseStoreAuthScopes(input) {
4
- const scopes = input
5
- .split(',')
6
- .map((scope) => scope.trim())
7
- .filter(Boolean);
8
- if (scopes.length === 0) {
9
- throw new AbortError('At least one scope is required.', 'Pass --scopes as a comma-separated list.');
10
- }
11
- return [...new Set(scopes)];
12
- }
13
- function expandImpliedStoreScopes(scopes) {
14
- const expandedScopes = new Set(scopes);
15
- for (const scope of scopes) {
16
- const matches = scope.match(/^(unauthenticated_)?write_(.*)$/);
17
- if (matches) {
18
- expandedScopes.add(`${matches[1] ?? ''}read_${matches[2]}`);
19
- }
20
- }
21
- return expandedScopes;
22
- }
23
- export function mergeRequestedAndStoredScopes(requestedScopes, storedScopes) {
24
- const mergedScopes = [...storedScopes];
25
- const expandedScopes = expandImpliedStoreScopes(storedScopes);
26
- for (const scope of requestedScopes) {
27
- if (expandedScopes.has(scope))
28
- continue;
29
- mergedScopes.push(scope);
30
- for (const expandedScope of expandImpliedStoreScopes([scope])) {
31
- expandedScopes.add(expandedScope);
32
- }
33
- }
34
- return mergedScopes;
35
- }
36
- export function resolveGrantedScopes(tokenResponse, requestedScopes) {
37
- if (!tokenResponse.scope) {
38
- outputDebug(outputContent `Token response did not include scope; falling back to requested scopes`);
39
- return requestedScopes;
40
- }
41
- const grantedScopes = parseStoreAuthScopes(tokenResponse.scope);
42
- const expandedGrantedScopes = expandImpliedStoreScopes(grantedScopes);
43
- const missingScopes = requestedScopes.filter((scope) => !expandedGrantedScopes.has(scope));
44
- if (missingScopes.length > 0) {
45
- throw new AbortError('Shopify granted fewer scopes than were requested.', `Missing scopes: ${missingScopes.join(', ')}.`, [
46
- 'Update the app or store installation scopes.',
47
- 'See https://shopify.dev/app/scopes',
48
- 'Re-run shopify store auth.',
49
- ]);
50
- }
51
- return grantedScopes;
52
- }
53
- //# sourceMappingURL=scopes.js.map
@@ -1,3 +0,0 @@
1
- import type { StoredStoreAppSession } from './session-store.js';
2
- export declare function isSessionExpired(session: StoredStoreAppSession): boolean;
3
- export declare function loadStoredStoreSession(store: string): Promise<StoredStoreAppSession>;
@@ -1,69 +0,0 @@
1
- import { AbortError } from '@shopify/cli-kit/node/error';
2
- import { outputContent, outputDebug, outputToken } from '@shopify/cli-kit/node/output';
3
- import { maskToken } from './config.js';
4
- import { createStoredStoreAuthError, reauthenticateStoreAuthError } from './recovery.js';
5
- import { clearStoredStoreAppSession, getCurrentStoredStoreAppSession, setStoredStoreAppSession, } from './session-store.js';
6
- import { refreshStoreAccessToken } from './token-client.js';
7
- const EXPIRY_MARGIN_MS = 4 * 60 * 1000;
8
- export function isSessionExpired(session) {
9
- if (!session.expiresAt)
10
- return false;
11
- const expiresAtMs = new Date(session.expiresAt).getTime();
12
- if (Number.isNaN(expiresAtMs))
13
- return true;
14
- return expiresAtMs - EXPIRY_MARGIN_MS < Date.now();
15
- }
16
- function buildRefreshedStoredSession(session, refresh) {
17
- const now = Date.now();
18
- const expiresAt = refresh.expiresIn ? new Date(now + refresh.expiresIn * 1000).toISOString() : session.expiresAt;
19
- return {
20
- ...session,
21
- accessToken: refresh.accessToken,
22
- refreshToken: refresh.refreshToken ?? session.refreshToken,
23
- expiresAt,
24
- refreshTokenExpiresAt: refresh.refreshTokenExpiresIn
25
- ? new Date(now + refresh.refreshTokenExpiresIn * 1000).toISOString()
26
- : session.refreshTokenExpiresAt,
27
- acquiredAt: new Date(now).toISOString(),
28
- };
29
- }
30
- export async function loadStoredStoreSession(store) {
31
- let session = getCurrentStoredStoreAppSession(store);
32
- if (!session) {
33
- throw createStoredStoreAuthError(store);
34
- }
35
- outputDebug(outputContent `Loaded stored session for ${outputToken.raw(store)}: token=${outputToken.raw(maskToken(session.accessToken))}, expires=${outputToken.raw(session.expiresAt ?? 'unknown')}`);
36
- if (!isSessionExpired(session)) {
37
- return session;
38
- }
39
- if (!session.refreshToken) {
40
- throw reauthenticateStoreAuthError(`No refresh token stored for ${session.store}.`, session.store, session.scopes.join(','));
41
- }
42
- outputDebug(outputContent `Refreshing expired token for ${outputToken.raw(session.store)} (expired at ${outputToken.raw(session.expiresAt ?? 'unknown')}, refresh_token=${outputToken.raw(maskToken(session.refreshToken))})`);
43
- const previousAccessToken = session.accessToken;
44
- let refreshed;
45
- try {
46
- refreshed = await refreshStoreAccessToken({
47
- store: session.store,
48
- refreshToken: session.refreshToken,
49
- });
50
- }
51
- catch (error) {
52
- clearStoredStoreAppSession(session.store, session.userId);
53
- if (error instanceof AbortError && error.message.startsWith(`Token refresh failed for ${session.store} (HTTP `)) {
54
- throw reauthenticateStoreAuthError(error.message, session.store, session.scopes.join(','));
55
- }
56
- if (error instanceof AbortError && error.message === `Token refresh returned an invalid response for ${session.store}.`) {
57
- throw reauthenticateStoreAuthError(error.message, session.store, session.scopes.join(','));
58
- }
59
- if (error instanceof AbortError && error.message === 'Received an invalid refresh response from Shopify.') {
60
- throw error;
61
- }
62
- throw error;
63
- }
64
- session = buildRefreshedStoredSession(session, refreshed);
65
- outputDebug(outputContent `Token refresh succeeded for ${outputToken.raw(session.store)}: ${outputToken.raw(maskToken(previousAccessToken))} → ${outputToken.raw(maskToken(session.accessToken))}, new expiry ${outputToken.raw(session.expiresAt ?? 'unknown')}`);
66
- setStoredStoreAppSession(session);
67
- return session;
68
- }
69
- //# sourceMappingURL=session-lifecycle.js.map
@@ -1,32 +0,0 @@
1
- import { LocalStorage } from '@shopify/cli-kit/node/local-storage';
2
- export interface StoredStoreAppSession {
3
- store: string;
4
- clientId: string;
5
- userId: string;
6
- accessToken: string;
7
- refreshToken?: string;
8
- scopes: string[];
9
- acquiredAt: string;
10
- expiresAt?: string;
11
- refreshTokenExpiresAt?: string;
12
- associatedUser?: {
13
- id: number;
14
- email?: string;
15
- firstName?: string;
16
- lastName?: string;
17
- accountOwner?: boolean;
18
- };
19
- }
20
- interface StoredStoreAppSessionBucket {
21
- currentUserId: string;
22
- sessionsByUserId: {
23
- [userId: string]: StoredStoreAppSession;
24
- };
25
- }
26
- interface StoreSessionSchema {
27
- [key: string]: StoredStoreAppSessionBucket;
28
- }
29
- export declare function getCurrentStoredStoreAppSession(store: string, storage?: LocalStorage<StoreSessionSchema>): StoredStoreAppSession | undefined;
30
- export declare function setStoredStoreAppSession(session: StoredStoreAppSession, storage?: LocalStorage<StoreSessionSchema>): void;
31
- export declare function clearStoredStoreAppSession(store: string, userIdOrStorage?: string | LocalStorage<StoreSessionSchema>, maybeStorage?: LocalStorage<StoreSessionSchema>): void;
32
- export {};
@@ -1,127 +0,0 @@
1
- import { LocalStorage } from '@shopify/cli-kit/node/local-storage';
2
- import { storeAuthSessionKey } from './config.js';
3
- let _storeSessionStorage;
4
- function storeSessionStorage() {
5
- _storeSessionStorage ?? (_storeSessionStorage = new LocalStorage({ projectName: 'shopify-cli-store' }));
6
- return _storeSessionStorage;
7
- }
8
- function isString(value) {
9
- return typeof value === 'string';
10
- }
11
- function sanitizeAssociatedUser(value) {
12
- if (!value || typeof value !== 'object')
13
- return undefined;
14
- const associatedUser = value;
15
- if (typeof associatedUser.id !== 'number')
16
- return undefined;
17
- return {
18
- id: associatedUser.id,
19
- ...(isString(associatedUser.email) ? { email: associatedUser.email } : {}),
20
- ...(isString(associatedUser.firstName) ? { firstName: associatedUser.firstName } : {}),
21
- ...(isString(associatedUser.lastName) ? { lastName: associatedUser.lastName } : {}),
22
- ...(typeof associatedUser.accountOwner === 'boolean' ? { accountOwner: associatedUser.accountOwner } : {}),
23
- };
24
- }
25
- function sanitizeStoredStoreAppSession(value) {
26
- if (!value || typeof value !== 'object')
27
- return undefined;
28
- const session = value;
29
- if (!isString(session.store) ||
30
- !isString(session.clientId) ||
31
- !isString(session.userId) ||
32
- !isString(session.accessToken) ||
33
- !Array.isArray(session.scopes) ||
34
- !session.scopes.every(isString) ||
35
- !isString(session.acquiredAt)) {
36
- return undefined;
37
- }
38
- return {
39
- store: session.store,
40
- clientId: session.clientId,
41
- userId: session.userId,
42
- accessToken: session.accessToken,
43
- scopes: session.scopes,
44
- acquiredAt: session.acquiredAt,
45
- ...(isString(session.refreshToken) ? { refreshToken: session.refreshToken } : {}),
46
- ...(isString(session.expiresAt) ? { expiresAt: session.expiresAt } : {}),
47
- ...(isString(session.refreshTokenExpiresAt) ? { refreshTokenExpiresAt: session.refreshTokenExpiresAt } : {}),
48
- ...(sanitizeAssociatedUser(session.associatedUser) ? { associatedUser: sanitizeAssociatedUser(session.associatedUser) } : {}),
49
- };
50
- }
51
- function readStoredStoreAppSessionBucket(store, storage) {
52
- const key = storeAuthSessionKey(store);
53
- const storedBucket = storage.get(key);
54
- if (!storedBucket || typeof storedBucket !== 'object')
55
- return undefined;
56
- const { sessionsByUserId, currentUserId } = storedBucket;
57
- if (!sessionsByUserId || typeof sessionsByUserId !== 'object' || Array.isArray(sessionsByUserId) || typeof currentUserId !== 'string') {
58
- storage.delete(key);
59
- return undefined;
60
- }
61
- const sanitizedSessionsByUserId = Object.fromEntries(Object.entries(sessionsByUserId).flatMap(([userId, session]) => {
62
- const sanitizedSession = sanitizeStoredStoreAppSession(session);
63
- return sanitizedSession ? [[userId, sanitizedSession]] : [];
64
- }));
65
- if (Object.keys(sanitizedSessionsByUserId).length !== Object.keys(sessionsByUserId).length) {
66
- if (sanitizedSessionsByUserId[currentUserId]) {
67
- storage.set(key, {
68
- currentUserId,
69
- sessionsByUserId: sanitizedSessionsByUserId,
70
- });
71
- }
72
- else {
73
- storage.delete(key);
74
- return undefined;
75
- }
76
- }
77
- return {
78
- currentUserId,
79
- sessionsByUserId: sanitizedSessionsByUserId,
80
- };
81
- }
82
- export function getCurrentStoredStoreAppSession(store, storage = storeSessionStorage()) {
83
- const bucket = readStoredStoreAppSessionBucket(store, storage);
84
- if (!bucket)
85
- return undefined;
86
- const session = bucket.sessionsByUserId[bucket.currentUserId];
87
- if (!session) {
88
- storage.delete(storeAuthSessionKey(store));
89
- return undefined;
90
- }
91
- return session;
92
- }
93
- export function setStoredStoreAppSession(session, storage = storeSessionStorage()) {
94
- const key = storeAuthSessionKey(session.store);
95
- const existingBucket = readStoredStoreAppSessionBucket(session.store, storage);
96
- const nextBucket = {
97
- currentUserId: session.userId,
98
- sessionsByUserId: {
99
- ...(existingBucket?.sessionsByUserId ?? {}),
100
- [session.userId]: session,
101
- },
102
- };
103
- storage.set(key, nextBucket);
104
- }
105
- export function clearStoredStoreAppSession(store, userIdOrStorage, maybeStorage) {
106
- const userId = typeof userIdOrStorage === 'string' ? userIdOrStorage : undefined;
107
- const storage = (typeof userIdOrStorage === 'string' ? maybeStorage : userIdOrStorage) ?? storeSessionStorage();
108
- const key = storeAuthSessionKey(store);
109
- if (!userId) {
110
- storage.delete(key);
111
- return;
112
- }
113
- const existingBucket = readStoredStoreAppSessionBucket(store, storage);
114
- if (!existingBucket)
115
- return;
116
- const { [userId]: _removedSession, ...remainingSessions } = existingBucket.sessionsByUserId;
117
- const remainingUserIds = Object.keys(remainingSessions);
118
- if (remainingUserIds.length === 0) {
119
- storage.delete(key);
120
- return;
121
- }
122
- storage.set(key, {
123
- currentUserId: existingBucket.currentUserId === userId ? remainingUserIds[0] : existingBucket.currentUserId,
124
- sessionsByUserId: remainingSessions,
125
- });
126
- }
127
- //# sourceMappingURL=session-store.js.map
@@ -1,40 +0,0 @@
1
- export interface StoreTokenResponse {
2
- access_token: string;
3
- token_type?: string;
4
- scope?: string;
5
- expires_in?: number;
6
- refresh_token?: string;
7
- refresh_token_expires_in?: number;
8
- associated_user_scope?: string;
9
- associated_user?: {
10
- id: number;
11
- first_name?: string;
12
- last_name?: string;
13
- email?: string;
14
- account_owner?: boolean;
15
- locale?: string;
16
- collaborator?: boolean;
17
- email_verified?: boolean;
18
- };
19
- }
20
- interface StoreTokenRefreshPayload {
21
- accessToken: string;
22
- refreshToken?: string;
23
- expiresIn?: number;
24
- refreshTokenExpiresIn?: number;
25
- }
26
- export declare function exchangeStoreAuthCodeForToken(options: {
27
- store: string;
28
- code: string;
29
- codeVerifier: string;
30
- redirectUri: string;
31
- }): Promise<StoreTokenResponse>;
32
- export declare function refreshStoreAccessToken(options: {
33
- store: string;
34
- refreshToken: string;
35
- }): Promise<StoreTokenRefreshPayload>;
36
- export declare function fetchCurrentStoreAuthScopes(options: {
37
- store: string;
38
- accessToken: string;
39
- }): Promise<string[]>;
40
- export {};