Skip to content

Commit 9ede791

Browse files
isaacroldangonzaloriestra
authored andcommitted
Force all requests in app management to have an unauthorizedHandler
1 parent 5c11314 commit 9ede791

File tree

9 files changed

+232
-205
lines changed

9 files changed

+232
-205
lines changed

packages/app/src/cli/utilities/developer-platform-client/app-management-client.ts

Lines changed: 134 additions & 137 deletions
Large diffs are not rendered by default.

packages/cli-kit/src/public/node/api/admin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export async function adminRequestDoc<TResult, TVariables extends Variables>(
8080
}
8181
let unauthorizedHandler: UnauthorizedHandler | undefined
8282
if ('refresh' in session) {
83-
unauthorizedHandler = {type: 'simple', handler: session.refresh as () => Promise<void>}
83+
unauthorizedHandler = {type: 'token_refresh', handler: session.refresh as () => Promise<{token: string}>}
8484
}
8585
const result = graphqlRequestDoc<TResult, TVariables>({
8686
...opts,

packages/cli-kit/src/public/node/api/app-dev.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {appDevRequest} from './app-dev.js'
1+
import {appDevRequestDoc} from './app-dev.js'
22
import {graphqlRequestDoc} from './graphql.js'
33
import {serviceEnvironment, Environment} from '../../../private/node/context/service.js'
44
import {test, vi, expect, describe} from 'vitest'
@@ -33,7 +33,7 @@ describe('appDevRequest', () => {
3333
const query = 'query' as unknown as TypedDocumentNode<object, {variables: string}>
3434

3535
// When
36-
await appDevRequest(query, shopFqdn, mockedToken, {variables: 'variables'})
36+
await appDevRequestDoc(query, shopFqdn, mockedToken, {variables: 'variables'})
3737

3838
// Then
3939
expect(graphqlRequestDoc).toHaveBeenLastCalledWith({
@@ -51,7 +51,7 @@ describe('appDevRequest', () => {
5151
const query = 'query' as unknown as TypedDocumentNode<object, {variables: string}>
5252

5353
// When
54-
await appDevRequest(query, shopFqdn, mockedToken, {variables: 'variables'})
54+
await appDevRequestDoc(query, shopFqdn, mockedToken, {variables: 'variables'})
5555

5656
// Then
5757
expect(graphqlRequestDoc).toHaveBeenLastCalledWith({

packages/cli-kit/src/public/node/api/app-dev.ts

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {graphqlRequestDoc} from './graphql.js'
1+
import {graphqlRequestDoc, UnauthorizedHandler} from './graphql.js'
22
import {appDevFqdn, normalizeStoreFqdn} from '../context/fqdn.js'
33
import {serviceEnvironment} from '../../../private/node/context/service.js'
44
import Bottleneck from 'bottleneck'
@@ -14,36 +14,45 @@ const limiter = new Bottleneck({
1414
})
1515

1616
/**
17-
* Executes an org-scoped GraphQL query against the App Management API.
18-
* Uses typed documents.
19-
*
2017
* @param query - GraphQL query to execute.
2118
* @param shopFqdn - The shop fqdn.
2219
* @param token - Partners token.
2320
* @param variables - GraphQL variables to pass to the query.
21+
* @param unauthorizedHandler - Unauthorized handler to use.
22+
*/
23+
export interface AppDevRequestOptions<TResult, TVariables extends Variables> {
24+
query: TypedDocumentNode<TResult, TVariables>
25+
shopFqdn: string
26+
token: string
27+
unauthorizedHandler: UnauthorizedHandler
28+
variables?: TVariables
29+
}
30+
/**
31+
* Executes an org-scoped GraphQL query against the App Management API.
32+
* Uses typed documents.
33+
*
34+
* @param options - The options for the request.
2435
* @returns The response of the query of generic type <T>.
2536
*/
26-
export async function appDevRequest<TResult, TVariables extends Variables>(
27-
query: TypedDocumentNode<TResult, TVariables>,
28-
shopFqdn: string,
29-
token: string,
30-
variables?: TVariables,
37+
export async function appDevRequestDoc<TResult, TVariables extends Variables>(
38+
options: AppDevRequestOptions<TResult, TVariables>,
3139
): Promise<TResult> {
3240
const api = 'App Dev'
33-
const normalizedShopFqdn = await normalizeStoreFqdn(shopFqdn)
41+
const normalizedShopFqdn = await normalizeStoreFqdn(options.shopFqdn)
3442
const fqdn = await appDevFqdn(normalizedShopFqdn)
3543
const url = `https://${fqdn}/app_dev/unstable/graphql.json`
3644

3745
const addedHeaders = serviceEnvironment() === 'local' ? {'x-forwarded-host': normalizedShopFqdn} : undefined
3846

3947
const result = limiter.schedule<TResult>(() =>
4048
graphqlRequestDoc<TResult, TVariables>({
41-
query,
49+
query: options.query,
4250
api,
4351
url,
44-
token,
52+
token: options.token,
4553
addedHeaders,
46-
variables,
54+
variables: options.variables,
55+
unauthorizedHandler: options.unauthorizedHandler,
4756
}),
4857
)
4958

packages/cli-kit/src/public/node/api/app-management.ts

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -50,38 +50,45 @@ export interface RequestOptions {
5050
}
5151

5252
/**
53-
* Executes an org-scoped GraphQL query against the App Management API. Uses typed documents.
54-
*
5553
* @param orgId - The organization ID.
5654
* @param query - GraphQL query to execute.
5755
* @param token - Partners token.
5856
* @param variables - GraphQL variables to pass to the query.
5957
* @param cacheOptions - Cache options for the request. If not present, the request will not be cached.
6058
* @param requestOptions - Preferred behaviour for the request.
6159
* @param unauthorizedHandler - Optional handler for unauthorized requests.
60+
*/
61+
export interface AppManagementRequestOptions<TResult, TVariables extends Variables> {
62+
organizationId: string
63+
query: TypedDocumentNode<TResult, TVariables>
64+
token: string
65+
variables?: TVariables
66+
cacheOptions?: CacheOptions
67+
requestOptions?: RequestOptions
68+
unauthorizedHandler: UnauthorizedHandler
69+
}
70+
71+
/**
72+
* Executes an org-scoped GraphQL query against the App Management API. Uses typed documents.
73+
*
74+
* @param options - The options for the request.
6275
* @returns The response of the query of generic type <T>.
6376
*/
6477
export async function appManagementRequestDoc<TResult, TVariables extends Variables>(
65-
orgId: string,
66-
query: TypedDocumentNode<TResult, TVariables>,
67-
token: string,
68-
variables?: TVariables,
69-
cacheOptions?: CacheOptions,
70-
requestOptions?: RequestOptions,
71-
unauthorizedHandler?: UnauthorizedHandler,
78+
options: AppManagementRequestOptions<TResult, TVariables>,
7279
): Promise<TResult> {
7380
// For app management, we need to cache the response based on the orgId.
74-
const cacheExtraKey = (cacheOptions?.cacheExtraKey ?? '') + orgId
75-
const newCacheOptions = cacheOptions ? {...cacheOptions, cacheExtraKey} : undefined
81+
const cacheExtraKey = (options.cacheOptions?.cacheExtraKey ?? '') + options.organizationId
82+
const newCacheOptions = options.cacheOptions ? {...options.cacheOptions, cacheExtraKey} : undefined
7683

7784
const result = limiter.schedule<TResult>(async () =>
7885
graphqlRequestDoc<TResult, TVariables>({
79-
...(await setupRequest(orgId, token)),
80-
query,
81-
variables,
86+
...(await setupRequest(options.organizationId, options.token)),
87+
query: options.query,
88+
variables: options.variables,
8289
cacheOptions: newCacheOptions,
83-
preferredBehaviour: requestOptions?.requestMode,
84-
unauthorizedHandler,
90+
preferredBehaviour: options.requestOptions?.requestMode,
91+
unauthorizedHandler: options.unauthorizedHandler,
8592
}),
8693
)
8794

packages/cli-kit/src/public/node/api/business-platform.ts

Lines changed: 43 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {CacheOptions, Exact, GraphQLVariables, graphqlRequest, graphqlRequestDoc} from './graphql.js'
1+
import {CacheOptions, GraphQLVariables, UnauthorizedHandler, graphqlRequest, graphqlRequestDoc} from './graphql.js'
22
import {handleDeprecations} from './partners.js'
33
import {businessPlatformFqdn} from '../context/fqdn.js'
44
import {TypedDocumentNode} from '@graphql-typed-document-node/core'
@@ -45,25 +45,34 @@ export async function businessPlatformRequest<T>(
4545
}
4646

4747
/**
48-
* Executes a GraphQL query against the Business Platform Destinations API. Uses typed documents.
49-
*
5048
* @param query - GraphQL query to execute.
5149
* @param token - Business Platform token.
5250
* @param variables - GraphQL variables to pass to the query.
5351
* @param cacheOptions - Cache options for the request. If not present, the request will not be cached.
52+
*/
53+
export interface BusinessPlatformRequestOptions<TResult, TVariables extends Variables> {
54+
query: TypedDocumentNode<TResult, TVariables>
55+
token: string
56+
variables?: TVariables
57+
cacheOptions?: CacheOptions
58+
unauthorizedHandler: UnauthorizedHandler
59+
}
60+
61+
/**
62+
* Executes a GraphQL query against the Business Platform Destinations API. Uses typed documents.
63+
*
64+
* @param options - The options for the request.
5465
* @returns The response of the query of generic type <TResult>.
5566
*/
5667
export async function businessPlatformRequestDoc<TResult, TVariables extends Variables>(
57-
query: TypedDocumentNode<TResult, TVariables>,
58-
token: string,
59-
variables?: TVariables,
60-
cacheOptions?: CacheOptions,
68+
options: BusinessPlatformRequestOptions<TResult, TVariables>,
6169
): Promise<TResult> {
6270
return graphqlRequestDoc<TResult, TVariables>({
63-
...(await setupRequest(token)),
64-
query,
65-
variables,
66-
cacheOptions,
71+
...(await setupRequest(options.token)),
72+
query: options.query,
73+
variables: options.variables,
74+
cacheOptions: options.cacheOptions,
75+
unauthorizedHandler: options.unauthorizedHandler,
6776
})
6877
}
6978

@@ -85,46 +94,47 @@ async function setupOrganizationsRequest(token: string, organizationId: string)
8594
}
8695
}
8796

97+
export interface BusinessPlatformOrganizationsRequestNonTypedOptions {
98+
query: string
99+
token: string
100+
organizationId: string
101+
variables?: GraphQLVariables
102+
}
103+
88104
/**
89105
* Executes a GraphQL query against the Business Platform Organizations API.
90106
*
91-
* @param query - GraphQL query to execute.
92-
* @param token - Business Platform token.
93-
* @param organizationId - Organization ID as a numeric (non-GID) value.
94-
* @param variables - GraphQL variables to pass to the query.
107+
* @param options - The options for the request.
95108
* @returns The response of the query of generic type <T>.
96109
*/
97110
export async function businessPlatformOrganizationsRequest<T>(
98-
query: string,
99-
token: string,
100-
organizationId: string,
101-
variables?: GraphQLVariables,
111+
options: BusinessPlatformOrganizationsRequestNonTypedOptions,
102112
): Promise<T> {
103113
return graphqlRequest<T>({
104-
query,
105-
...(await setupOrganizationsRequest(token, organizationId)),
106-
variables,
114+
query: options.query,
115+
...(await setupOrganizationsRequest(options.token, options.organizationId)),
116+
variables: options.variables,
107117
})
108118
}
109119

120+
export interface BusinessPlatformOrganizationsRequestOptions<TResult, TVariables extends Variables>
121+
extends BusinessPlatformRequestOptions<TResult, TVariables> {
122+
organizationId: string
123+
}
124+
110125
/**
111126
* Executes a GraphQL query against the Business Platform Organizations API. Uses typed documents.
112127
*
113-
* @param query - GraphQL query to execute.
114-
* @param token - Business Platform token.
115-
* @param organizationId - Organization ID as a numeric value.
116-
* @param variables - GraphQL variables to pass to the query.
128+
* @param options - The options for the request.
117129
* @returns The response of the query of generic type <T>.
118130
*/
119131
export async function businessPlatformOrganizationsRequestDoc<TResult, TVariables extends Variables>(
120-
query: TypedDocumentNode<TResult, TVariables> | TypedDocumentNode<TResult, Exact<{[key: string]: never}>>,
121-
token: string,
122-
organizationId: string,
123-
variables?: TVariables,
132+
options: BusinessPlatformOrganizationsRequestOptions<TResult, TVariables>,
124133
): Promise<TResult> {
125134
return graphqlRequestDoc<TResult, TVariables>({
126-
query,
127-
...(await setupOrganizationsRequest(token, organizationId)),
128-
variables,
135+
query: options.query,
136+
...(await setupOrganizationsRequest(options.token, options.organizationId)),
137+
variables: options.variables,
138+
unauthorizedHandler: options.unauthorizedHandler,
129139
})
130140
}

packages/cli-kit/src/public/node/api/functions.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {graphqlRequestDoc} from './graphql.js'
1+
import {graphqlRequestDoc, UnauthorizedHandler} from './graphql.js'
22
import {handleDeprecations} from './app-management.js'
33
import {appManagementFqdn} from '../context/fqdn.js'
44
import {TypedDocumentNode} from '@graphql-typed-document-node/core'
@@ -42,6 +42,7 @@ async function setupRequest(orgId: string, token: string, appId: string) {
4242
* @param token - Authentication token.
4343
* @param appId - App identifier.
4444
* @param variables - Optional query variables.
45+
* @param unauthorizedHandler - Optional handler for unauthorized requests.
4546
* @returns Promise resolving to the typed query result.
4647
*/
4748
export async function functionsRequestDoc<TResult, TVariables extends Variables>(
@@ -50,12 +51,14 @@ export async function functionsRequestDoc<TResult, TVariables extends Variables>
5051
token: string,
5152
appId: string,
5253
variables?: TVariables,
54+
unauthorizedHandler?: UnauthorizedHandler,
5355
): Promise<TResult> {
5456
const result = await limiter.schedule<TResult>(async () => {
5557
return graphqlRequestDoc<TResult, TVariables>({
5658
...(await setupRequest(orgId, token, appId)),
5759
query,
5860
variables,
61+
unauthorizedHandler,
5962
})
6063
})
6164

packages/theme/src/cli/utilities/theme-environment/dev-server-session.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export async function initializeDevServerSession(
3232
session.refresh = async () => {
3333
outputDebug('Refreshing theme session...')
3434
const newSession = await fetchDevServerSession(themeId, adminSession, adminPassword, storefrontPassword)
35+
return newSession.token
3536
Object.assign(session, newSession)
3637
}
3738

packages/theme/src/cli/utilities/theme-environment/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export interface DevServerSession extends AdminSession {
4141
* Refreshes the current session, ensuring any tokens and session cookies
4242
* are up-to-date.
4343
*/
44-
refresh?: () => Promise<void>
44+
refresh?: () => Promise<string>
4545
}
4646

4747
/**

0 commit comments

Comments
 (0)