Skip to content

Commit c918c17

Browse files
authored
release(required): Amplify JS release (#14108)
2 parents 9776ac0 + 9a73470 commit c918c17

File tree

29 files changed

+1820
-234
lines changed

29 files changed

+1820
-234
lines changed

.github/integ-config/integ-all.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,3 +1011,12 @@ tests:
10111011
browser: [chrome]
10121012
env:
10131013
NEXT_PUBLIC_BACKEND_CONFIG: pwl-webauthn
1014+
- test_name: integ_next_refresh_token_auth
1015+
desc: 'refresh token auth'
1016+
framework: next
1017+
category: auth
1018+
sample_name: [mfa]
1019+
spec: refresh-token-auth
1020+
browser: *minimal_browser_list
1021+
env:
1022+
NEXT_PUBLIC_BACKEND_CONFIG: misc-tokenref

packages/adapter-nextjs/src/api/generateServerClient.ts

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ import {
1212
V6ClientSSRRequest,
1313
} from '@aws-amplify/api-graphql';
1414
import {
15-
GraphQLAuthMode,
16-
parseAmplifyConfig,
17-
} from '@aws-amplify/core/internals/utils';
15+
CommonPublicClientOptions,
16+
DefaultCommonClientOptions,
17+
} from '@aws-amplify/api-graphql/internals';
18+
import { parseAmplifyConfig } from '@aws-amplify/core/internals/utils';
1819

1920
import { NextServer } from '../types';
2021

@@ -23,14 +24,10 @@ import { createServerRunnerForAPI } from './createServerRunnerForAPI';
2324
interface CookiesClientParams {
2425
cookies: NextServer.ServerComponentContext['cookies'];
2526
config: NextServer.CreateServerRunnerInput['config'];
26-
authMode?: GraphQLAuthMode;
27-
authToken?: string;
2827
}
2928

3029
interface ReqClientParams {
3130
config: NextServer.CreateServerRunnerInput['config'];
32-
authMode?: GraphQLAuthMode;
33-
authToken?: string;
3431
}
3532

3633
/**
@@ -44,13 +41,10 @@ interface ReqClientParams {
4441
*/
4542
export function generateServerClientUsingCookies<
4643
T extends Record<any, any> = never,
47-
>({
48-
config,
49-
cookies,
50-
authMode,
51-
authToken,
52-
}: CookiesClientParams): V6ClientSSRCookies<T> {
53-
if (typeof cookies !== 'function') {
44+
Options extends CommonPublicClientOptions &
45+
CookiesClientParams = DefaultCommonClientOptions & CookiesClientParams,
46+
>(options: Options): V6ClientSSRCookies<T, Options> {
47+
if (typeof options.cookies !== 'function') {
5448
throw new AmplifyServerContextError({
5549
message:
5650
'generateServerClientUsingCookies is only compatible with the `cookies` Dynamic Function available in Server Components.',
@@ -61,24 +55,25 @@ export function generateServerClientUsingCookies<
6155
}
6256

6357
const { runWithAmplifyServerContext, resourcesConfig } =
64-
createServerRunnerForAPI({ config });
58+
createServerRunnerForAPI({ config: options.config });
6559

6660
// This function reference gets passed down to InternalGraphQLAPI.ts.graphql
6761
// where this._graphql is passed in as the `fn` argument
6862
// causing it to always get invoked inside `runWithAmplifyServerContext`
6963
const getAmplify = (fn: (amplify: any) => Promise<any>) =>
7064
runWithAmplifyServerContext({
71-
nextServerContext: { cookies },
65+
nextServerContext: { cookies: options.cookies },
7266
operation: contextSpec =>
7367
fn(getAmplifyServerContext(contextSpec).amplify),
7468
});
7569

76-
return generateClientWithAmplifyInstance<T, V6ClientSSRCookies<T>>({
70+
const { cookies: _cookies, config: _config, ...params } = options;
71+
72+
return generateClientWithAmplifyInstance<T, V6ClientSSRCookies<T, Options>>({
7773
amplify: getAmplify,
7874
config: resourcesConfig,
79-
authMode,
80-
authToken,
81-
});
75+
...params,
76+
} as any); // TS can't narrow the type here.
8277
}
8378

8479
/**
@@ -99,12 +94,15 @@ export function generateServerClientUsingCookies<
9994
*/
10095
export function generateServerClientUsingReqRes<
10196
T extends Record<any, any> = never,
102-
>({ config, authMode, authToken }: ReqClientParams): V6ClientSSRRequest<T> {
103-
const amplifyConfig = parseAmplifyConfig(config);
97+
Options extends CommonPublicClientOptions &
98+
ReqClientParams = DefaultCommonClientOptions & ReqClientParams,
99+
>(options: Options): V6ClientSSRRequest<T, Options> {
100+
const amplifyConfig = parseAmplifyConfig(options.config);
101+
102+
const { config: _config, ...params } = options;
104103

105104
return generateClient<T>({
106105
config: amplifyConfig,
107-
authMode,
108-
authToken,
109-
});
106+
...params,
107+
}) as any;
110108
}

packages/api-graphql/__tests__/internals/generateClient.test.ts

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,14 @@ describe('generateClient', () => {
270270
const client = generateClient<Schema>({ amplify: Amplify });
271271

272272
const spy = jest.fn(() => from([graphqlMessage]));
273-
(raw.GraphQLAPI as any).appSyncRealTime = { subscribe: spy };
273+
(raw.GraphQLAPI as any).appSyncRealTime = {
274+
get() {
275+
return { subscribe: spy }
276+
},
277+
set() {
278+
// not needed for test mock
279+
}
280+
};
274281

275282
expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot();
276283

@@ -497,7 +504,14 @@ describe('generateClient', () => {
497504
const client = generateClient<Schema>({ amplify: Amplify });
498505

499506
const spy = jest.fn(() => from([graphqlMessage]));
500-
(raw.GraphQLAPI as any).appSyncRealTime = { subscribe: spy };
507+
(raw.GraphQLAPI as any).appSyncRealTime = {
508+
get() {
509+
return { subscribe: spy }
510+
},
511+
set() {
512+
// not needed for test mock
513+
}
514+
};
501515

502516
client.models.Note.onCreate({
503517
filter: graphqlVariables.filter,
@@ -531,7 +545,14 @@ describe('generateClient', () => {
531545
});
532546

533547
const spy = jest.fn(() => from([graphqlMessage]));
534-
(raw.GraphQLAPI as any).appSyncRealTime = { subscribe: spy };
548+
(raw.GraphQLAPI as any).appSyncRealTime = {
549+
get() {
550+
return { subscribe: spy }
551+
},
552+
set() {
553+
// not needed for test mock
554+
}
555+
};
535556

536557
client.models.Note.onCreate({
537558
filter: graphqlVariables.filter,
@@ -561,7 +582,14 @@ describe('generateClient', () => {
561582
const client = generateClient<Schema>({ amplify: Amplify });
562583

563584
const spy = jest.fn(() => from([graphqlMessage]));
564-
(raw.GraphQLAPI as any).appSyncRealTime = { subscribe: spy };
585+
(raw.GraphQLAPI as any).appSyncRealTime = {
586+
get() {
587+
return { subscribe: spy }
588+
},
589+
set() {
590+
// not needed for test mock
591+
}
592+
};
565593

566594
client.models.Note.onCreate({
567595
filter: graphqlVariables.filter,
@@ -583,7 +611,14 @@ describe('generateClient', () => {
583611
const client = generateClient<Schema>({ amplify: Amplify });
584612

585613
const spy = jest.fn(() => from([graphqlMessage]));
586-
(raw.GraphQLAPI as any).appSyncRealTime = { subscribe: spy };
614+
(raw.GraphQLAPI as any).appSyncRealTime = {
615+
get() {
616+
return { subscribe: spy }
617+
},
618+
set() {
619+
// not needed for test mock
620+
}
621+
};
587622

588623
client.models.Note.onCreate({
589624
filter: graphqlVariables.filter,
@@ -711,7 +746,14 @@ describe('generateClient', () => {
711746
const client = generateClient<Schema>({ amplify: Amplify });
712747

713748
const spy = jest.fn(() => from([graphqlMessage]));
714-
(raw.GraphQLAPI as any).appSyncRealTime = { subscribe: spy };
749+
(raw.GraphQLAPI as any).appSyncRealTime = {
750+
get() {
751+
return { subscribe: spy }
752+
},
753+
set() {
754+
// not needed for test mock
755+
}
756+
};
715757

716758
client.models.Note.onCreate({
717759
filter: graphqlVariables.filter,

packages/api-graphql/src/internals/InternalGraphQLAPI.ts

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export class InternalGraphQLAPIClass {
5252
/**
5353
* @private
5454
*/
55-
private appSyncRealTime = new AWSAppSyncRealTimeProvider();
55+
private appSyncRealTime = new Map<string, AWSAppSyncRealTimeProvider>();
5656

5757
private _api = {
5858
post,
@@ -88,7 +88,14 @@ export class InternalGraphQLAPIClass {
8888
amplify:
8989
| AmplifyClassV6
9090
| ((fn: (amplify: any) => Promise<any>) => Promise<AmplifyClassV6>),
91-
{ query: paramQuery, variables = {}, authMode, authToken }: GraphQLOptions,
91+
{
92+
query: paramQuery,
93+
variables = {},
94+
authMode,
95+
authToken,
96+
endpoint,
97+
apiKey,
98+
}: GraphQLOptions,
9299
additionalHeaders?: CustomHeaders,
93100
customUserAgentDetails?: CustomUserAgentDetails,
94101
): Observable<GraphQLResult<T>> | Promise<GraphQLResult<T>> {
@@ -115,7 +122,7 @@ export class InternalGraphQLAPIClass {
115122
if (isAmplifyInstance(amplify)) {
116123
responsePromise = this._graphql<T>(
117124
amplify,
118-
{ query, variables, authMode },
125+
{ query, variables, authMode, apiKey, endpoint },
119126
headers,
120127
abortController,
121128
customUserAgentDetails,
@@ -127,7 +134,7 @@ export class InternalGraphQLAPIClass {
127134
const wrapper = async (amplifyInstance: AmplifyClassV6) => {
128135
const result = await this._graphql<T>(
129136
amplifyInstance,
130-
{ query, variables, authMode },
137+
{ query, variables, authMode, apiKey, endpoint },
131138
headers,
132139
abortController,
133140
customUserAgentDetails,
@@ -152,7 +159,7 @@ export class InternalGraphQLAPIClass {
152159
case 'subscription':
153160
return this._graphqlSubscribe(
154161
amplify as AmplifyClassV6,
155-
{ query, variables, authMode },
162+
{ query, variables, authMode, apiKey, endpoint },
156163
headers,
157164
customUserAgentDetails,
158165
authToken,
@@ -164,7 +171,13 @@ export class InternalGraphQLAPIClass {
164171

165172
private async _graphql<T = any>(
166173
amplify: AmplifyClassV6,
167-
{ query, variables, authMode: explicitAuthMode }: GraphQLOptions,
174+
{
175+
query,
176+
variables,
177+
authMode: authModeOverride,
178+
endpoint: endpointOverride,
179+
apiKey: apiKeyOverride,
180+
}: GraphQLOptions,
168181
additionalHeaders: CustomHeaders = {},
169182
abortController: AbortController,
170183
customUserAgentDetails?: CustomUserAgentDetails,
@@ -179,7 +192,7 @@ export class InternalGraphQLAPIClass {
179192
defaultAuthMode,
180193
} = resolveConfig(amplify);
181194

182-
const initialAuthMode = explicitAuthMode || defaultAuthMode || 'iam';
195+
const initialAuthMode = authModeOverride || defaultAuthMode || 'iam';
183196
// identityPool is an alias for iam. TODO: remove 'iam' in v7
184197
const authMode =
185198
initialAuthMode === 'identityPool' ? 'iam' : initialAuthMode;
@@ -205,7 +218,7 @@ export class InternalGraphQLAPIClass {
205218
const requestOptions: RequestOptions = {
206219
method: 'POST',
207220
url: new AmplifyUrl(
208-
customEndpoint || appSyncGraphqlEndpoint || '',
221+
endpointOverride || customEndpoint || appSyncGraphqlEndpoint || '',
209222
).toString(),
210223
queryString: print(query as DocumentNode),
211224
};
@@ -226,7 +239,7 @@ export class InternalGraphQLAPIClass {
226239
const authHeaders = await headerBasedAuth(
227240
amplify,
228241
authMode,
229-
apiKey,
242+
apiKeyOverride ?? apiKey,
230243
additionalCustomHeaders,
231244
);
232245

@@ -282,7 +295,8 @@ export class InternalGraphQLAPIClass {
282295
};
283296
}
284297

285-
const endpoint = customEndpoint || appSyncGraphqlEndpoint;
298+
const endpoint =
299+
endpointOverride || customEndpoint || appSyncGraphqlEndpoint;
286300

287301
if (!endpoint) {
288302
throw createGraphQLResultWithError<T>(new GraphQLApiError(NO_ENDPOINT));
@@ -341,15 +355,21 @@ export class InternalGraphQLAPIClass {
341355

342356
private _graphqlSubscribe(
343357
amplify: AmplifyClassV6,
344-
{ query, variables, authMode: explicitAuthMode }: GraphQLOptions,
358+
{
359+
query,
360+
variables,
361+
authMode: authModeOverride,
362+
apiKey: apiKeyOverride,
363+
endpoint,
364+
}: GraphQLOptions,
345365
additionalHeaders: CustomHeaders = {},
346366
customUserAgentDetails?: CustomUserAgentDetails,
347367
authToken?: string,
348368
): Observable<any> {
349369
const config = resolveConfig(amplify);
350370

351371
const initialAuthMode =
352-
explicitAuthMode || config?.defaultAuthMode || 'iam';
372+
authModeOverride || config?.defaultAuthMode || 'iam';
353373
// identityPool is an alias for iam. TODO: remove 'iam' in v7
354374
const authMode =
355375
initialAuthMode === 'identityPool' ? 'iam' : initialAuthMode;
@@ -364,15 +384,26 @@ export class InternalGraphQLAPIClass {
364384
*/
365385
const { headers: libraryConfigHeaders } = resolveLibraryOptions(amplify);
366386

367-
return this.appSyncRealTime
387+
const appSyncGraphqlEndpoint = endpoint ?? config?.endpoint;
388+
389+
// TODO: This could probably be an exception. But, lots of tests rely on
390+
// attempting to connect to nowhere. So, I'm treating as the opposite of
391+
// a Chesterton's fence for now. (A fence I shouldn't build, because I don't
392+
// know why somethings depends on its absence!)
393+
const memoKey = appSyncGraphqlEndpoint ?? 'none';
394+
const realtimeProvider =
395+
this.appSyncRealTime.get(memoKey) ?? new AWSAppSyncRealTimeProvider();
396+
this.appSyncRealTime.set(memoKey, realtimeProvider);
397+
398+
return realtimeProvider
368399
.subscribe(
369400
{
370401
query: print(query as DocumentNode),
371402
variables,
372-
appSyncGraphqlEndpoint: config?.endpoint,
403+
appSyncGraphqlEndpoint,
373404
region: config?.region,
374405
authenticationType: authMode,
375-
apiKey: config?.apiKey,
406+
apiKey: apiKeyOverride ?? config?.apiKey,
376407
additionalHeaders,
377408
authToken,
378409
libraryConfigHeaders,

0 commit comments

Comments
 (0)