Skip to content

Commit a8118f2

Browse files
authored
release(required): Amplify JS release (#14338)
2 parents 7c5acbd + 42f6332 commit a8118f2

File tree

35 files changed

+914
-1514
lines changed

35 files changed

+914
-1514
lines changed

.github/workflows/callable-docs-update.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,4 @@ jobs:
6363
run: |
6464
git checkout -b $TEMP_BRANCH_NAME
6565
git push origin $TEMP_BRANCH_NAME
66-
gh pr create -B main -H $TEMP_BRANCH_NAME --title 'chore: amplify-js api references update' --body 'Merge the api references changes from the most recent release.'
66+
gh pr create -B pre-prod/main -H $TEMP_BRANCH_NAME --title 'chore: amplify-js api references update' --body 'Merge the api references changes from the most recent release.'

.github/workflows/on-schedule-canary-test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
on:
2-
# Tests scheduled at 4pm(UTC) / 9am(PDT) everyday
2+
# Tests scheduled at 3pm(UTC) / 8am(PDT) everyday
33
# default supported timezone is UTC
44
schedule:
5-
- cron: '0 16 * * *'
5+
- cron: '0 15 * * *'
66

77
jobs:
88
canaries:

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ xcuserdata/
5050
!*.xcworkspace/contents.xcworkspacedata
5151
/*.gcno
5252
**/xcshareddata/WorkspaceSettings.xcsettings
53+
**/.xcode.env.local
5354

5455
### Coverage ###
5556
coverage/

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,4 +145,4 @@
145145
"tar": "6.2.1",
146146
"cross-spawn": "7.0.5"
147147
}
148-
}
148+
}

packages/adapter-nextjs/__tests__/auth/utils/createUrlSearchParams.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,23 @@ describe('createUrlSearchParamsForSignInSignUp', () => {
5454
'redirect_uri=https%3A%2F%2Fexample.com%2Fsignin&response_type=code&client_id=userPoolClientId&scope=openid&state=state&code_challenge=code_challenge&code_challenge_method=S256&identity_provider=Google',
5555
);
5656
});
57+
58+
it('returns URLSearchParams with the correct values when lang query parameter is supplied', () => {
59+
const url = 'https://example.com?lang=es';
60+
61+
const result = createUrlSearchParamsForSignInSignUp({
62+
url,
63+
oAuthConfig,
64+
userPoolClientId,
65+
state,
66+
origin,
67+
codeVerifier,
68+
});
69+
70+
expect(result.toString()).toBe(
71+
'redirect_uri=https%3A%2F%2Fexample.com%2Fsignin&response_type=code&client_id=userPoolClientId&scope=openid&state=state&code_challenge=code_challenge&code_challenge_method=S256&lang=es',
72+
);
73+
});
5774
});
5875

5976
describe('createUrlSearchParamsForTokenExchange', () => {

packages/adapter-nextjs/src/auth/utils/createUrlSearchParams.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { generateCodeVerifier } from 'aws-amplify/adapter-core';
66

77
import { resolveIdentityProviderFromUrl } from './resolveIdentityProviderFromUrl';
88
import { resolveRedirectSignInUrl } from './resolveRedirectUrl';
9+
import { getSearchParamValueFromUrl } from './getSearchParamValueFromUrl';
910

1011
export const createUrlSearchParamsForSignInSignUp = ({
1112
url,
@@ -23,6 +24,7 @@ export const createUrlSearchParamsForSignInSignUp = ({
2324
codeVerifier: ReturnType<typeof generateCodeVerifier>;
2425
}): URLSearchParams => {
2526
const resolvedProvider = resolveIdentityProviderFromUrl(url);
27+
const lang = getSearchParamValueFromUrl(url, 'lang');
2628

2729
const redirectUrlSearchParams = new URLSearchParams({
2830
redirect_uri: resolveRedirectSignInUrl(origin, oAuthConfig),
@@ -38,6 +40,10 @@ export const createUrlSearchParamsForSignInSignUp = ({
3840
redirectUrlSearchParams.append('identity_provider', resolvedProvider);
3941
}
4042

43+
if (lang) {
44+
redirectUrlSearchParams.append('lang', lang);
45+
}
46+
4147
return redirectUrlSearchParams;
4248
};
4349

packages/api-graphql/__tests__/events.test.ts

Lines changed: 47 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,13 @@ describe('Events client', () => {
100100
});
101101
});
102102

103-
const authModes: GraphQLAuthMode[] = [
104-
'apiKey',
105-
'userPool',
106-
'oidc',
107-
'iam',
108-
'lambda',
109-
'none',
103+
const authModeConfigs: { authMode: GraphQLAuthMode, apiKey?: string, authToken?: string }[] = [
104+
{ authMode: 'apiKey', apiKey: 'testAPIKey' },
105+
{ authMode: 'userPool', authToken: 'userPoolToken' },
106+
{ authMode: 'oidc', authToken: 'oidcToken' },
107+
{ authMode: 'iam', authToken: 'iamToken' },
108+
{ authMode: 'lambda', authToken: 'lambdaToken' },
109+
{ authMode: 'none' },
110110
];
111111

112112
describe('channel', () => {
@@ -124,12 +124,16 @@ describe('Events client', () => {
124124
mockProvider = AppSyncEventProvider;
125125
});
126126

127-
for (const authMode of authModes) {
128-
test(`auth override: ${authMode}`, async () => {
129-
await events.connect('/', { authMode });
127+
for (const authConfig of authModeConfigs) {
128+
const {authMode: authenticationType, ...config} = authConfig
129+
test(`connect auth override: ${authConfig.authMode}`, async () => {
130+
const channel = await events.connect('/', authConfig);
130131

131132
expect(mockProvider.connect).toHaveBeenCalledWith(
132-
expect.objectContaining({ authenticationType: authMode }),
133+
expect.objectContaining({
134+
authenticationType,
135+
...config
136+
}),
133137
);
134138
});
135139
}
@@ -153,20 +157,24 @@ describe('Events client', () => {
153157
mockProvider = AppSyncEventProvider;
154158
});
155159

156-
for (const authMode of authModes) {
157-
test(`auth override: ${authMode}`, async () => {
158-
const channel = await events.connect('/');
160+
for (const authConfig of authModeConfigs) {
161+
const {authMode: authenticationType, ...config} = authConfig
159162

160-
channel.subscribe(
163+
test(`subscription auth override: ${authConfig.authMode}`, async () => {
164+
const channel = await events.connect('/');
165+
channel.subscribe(
161166
{
162167
next: data => void data,
163168
error: error => void error,
164169
},
165-
{ authMode },
166-
);
167-
168-
expect(mockSubscribeObservable).toHaveBeenCalledWith(
169-
expect.objectContaining({ authenticationType: authMode }),
170+
authConfig
171+
)
172+
173+
expect(mockProvider.subscribe).toHaveBeenCalledWith(
174+
expect.objectContaining({
175+
authenticationType,
176+
...config
177+
}),
170178
);
171179
});
172180
}
@@ -195,14 +203,21 @@ describe('Events client', () => {
195203
mockProvider = AppSyncEventProvider;
196204
});
197205

198-
for (const authMode of authModes) {
199-
test(`auth override: ${authMode}`, async () => {
200-
const channel = await events.connect('/');
206+
for (const authConfig of authModeConfigs) {
207+
const {authMode: authenticationType, ...config} = authConfig
201208

202-
channel.publish({ some: 'data' }, { authMode });
209+
test(`publish auth override: ${authConfig.authMode}`, async () => {
210+
const channel = await events.connect('/');
211+
channel.publish(
212+
"Test message",
213+
authConfig
214+
)
203215

204216
expect(mockProvider.publish).toHaveBeenCalledWith(
205-
expect.objectContaining({ authenticationType: authMode }),
217+
expect.objectContaining({
218+
authenticationType,
219+
...config
220+
}),
206221
);
207222
});
208223
}
@@ -230,16 +245,19 @@ describe('Events client', () => {
230245
);
231246
});
232247

233-
for (const authMode of authModes) {
234-
test(`auth override: ${authMode}`, async () => {
235-
await events.post('/', { test: 'data' }, { authMode });
248+
for (const authConfig of authModeConfigs) {
249+
const {authMode: authenticationType, ...config} = authConfig
250+
251+
test(`auth override: ${authenticationType}`, async () => {
252+
await events.post('/', { test: 'data' }, authConfig);
236253

237254
expect(mockReq).toHaveBeenCalledWith(
238255
Amplify,
239256
expect.objectContaining({
240257
query: '/',
241258
variables: ['{"test":"data"}'],
242-
authenticationType: authMode,
259+
authenticationType,
260+
...config
243261
}),
244262
{},
245263
abortController,

packages/api-graphql/src/internals/events/index.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { configure, normalizeAuth, serializeEvents } from './utils';
1212
import type {
1313
EventsChannel,
1414
EventsOptions,
15+
ProviderOptions,
1516
PublishResponse,
1617
PublishedEvent,
1718
SubscriptionObserver,
@@ -44,12 +45,14 @@ async function connect(
4445
channel: string,
4546
options?: EventsOptions,
4647
): Promise<EventsChannel> {
47-
const providerOptions = configure();
48+
const providerOptions: ProviderOptions = configure();
4849

4950
providerOptions.authenticationType = normalizeAuth(
5051
options?.authMode,
5152
providerOptions.authenticationType,
5253
);
54+
providerOptions.apiKey = options?.apiKey || providerOptions.apiKey;
55+
providerOptions.authToken = options?.authToken || providerOptions.authToken;
5356

5457
await eventProvider.connect(providerOptions);
5558

@@ -70,6 +73,9 @@ async function connect(
7073
subOptions?.authMode,
7174
subscribeOptions.authenticationType,
7275
);
76+
subscribeOptions.apiKey = subOptions?.apiKey || subscribeOptions.apiKey;
77+
subscribeOptions.authToken =
78+
subOptions?.authToken || subscribeOptions.authToken;
7379

7480
_subscription = eventProvider
7581
.subscribe(subscribeOptions)
@@ -94,6 +100,9 @@ async function connect(
94100
pubOptions?.authMode,
95101
publishOptions.authenticationType,
96102
);
103+
publishOptions.apiKey = pubOptions?.apiKey || publishOptions.apiKey;
104+
publishOptions.authToken =
105+
pubOptions?.authToken || publishOptions.authToken;
97106

98107
return eventProvider.publish(publishOptions);
99108
};
@@ -141,11 +150,13 @@ async function post(
141150
event: DocumentType | DocumentType[],
142151
options?: EventsOptions,
143152
): Promise<void | PublishedEvent[]> {
144-
const providerOptions = configure();
153+
const providerOptions: ProviderOptions = configure();
145154
providerOptions.authenticationType = normalizeAuth(
146155
options?.authMode,
147156
providerOptions.authenticationType,
148157
);
158+
providerOptions.apiKey = options?.apiKey || providerOptions.apiKey;
159+
providerOptions.authToken = options?.authToken || providerOptions.authToken;
149160

150161
// trailing slash required in publish
151162
const normalizedChannelName = channel[0] === '/' ? channel : `/${channel}`;
@@ -154,7 +165,6 @@ async function post(
154165
...providerOptions,
155166
query: normalizedChannelName,
156167
variables: serializeEvents(event),
157-
authToken: options?.authToken,
158168
};
159169

160170
const abortController = new AbortController();

packages/api-graphql/src/internals/events/types.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export type ResolvedGraphQLAuthModes = Exclude<GraphQLAuthMode, 'identityPool'>;
8484
export interface EventsOptions {
8585
authMode?: GraphQLAuthMode;
8686
authToken?: string;
87+
apiKey?: string;
8788
}
8889

8990
export interface PublishedEvent {
@@ -95,3 +96,14 @@ export interface PublishResponse {
9596
failed: PublishedEvent[];
9697
successful: PublishedEvent[];
9798
}
99+
100+
interface EventsConfigure {
101+
appSyncGraphqlEndpoint: string;
102+
region?: string;
103+
authenticationType: ResolvedGraphQLAuthModes;
104+
apiKey?: string;
105+
}
106+
107+
export type ProviderOptions = EventsConfigure & {
108+
authToken?: string;
109+
};

packages/aws-amplify/__tests__/initSingleton.test.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import {
1111
import { AmplifyOutputs } from '@aws-amplify/core/internals/utils';
1212

1313
import {
14+
CognitoAWSCredentialsAndIdentityIdProvider,
15+
DefaultIdentityIdStore,
1416
cognitoCredentialsProvider,
1517
cognitoUserPoolsTokenProvider,
1618
} from '../src/auth/cognito';
@@ -23,6 +25,8 @@ jest.mock('../src/auth/cognito', () => ({
2325
setKeyValueStorage: jest.fn(),
2426
},
2527
cognitoCredentialsProvider: jest.fn(),
28+
DefaultIdentityIdStore: jest.fn(),
29+
CognitoAWSCredentialsAndIdentityIdProvider: jest.fn(),
2630
}));
2731

2832
const mockCognitoUserPoolsTokenProviderSetAuthConfig =
@@ -32,6 +36,10 @@ const mockCognitoUserPoolsTokenProviderSetKeyValueStorage =
3236
const mockAmplifySingletonConfigure = AmplifySingleton.configure as jest.Mock;
3337
const mockAmplifySingletonGetConfig = AmplifySingleton.getConfig as jest.Mock;
3438
const MockCookieStorage = CookieStorage as jest.Mock;
39+
const MockDefaultIdentityIdStore = jest.mocked(DefaultIdentityIdStore);
40+
const MockCognitoAWSCredentialsAndIdentityIdProvider = jest.mocked(
41+
CognitoAWSCredentialsAndIdentityIdProvider,
42+
);
3543

3644
const mockResourceConfig: ResourcesConfig = {
3745
Auth: {
@@ -50,8 +58,16 @@ const mockResourceConfig: ResourcesConfig = {
5058

5159
describe('initSingleton (DefaultAmplify)', () => {
5260
const mockCookieStorageInstance = {};
61+
const mockCognitoAWSCredentialsAndIdentityIdProviderInstance = {} as any;
62+
const mockDefaultIdentityIdStoreInstance = {} as any;
5363
beforeAll(() => {
5464
MockCookieStorage.mockImplementation(() => mockCookieStorageInstance);
65+
MockDefaultIdentityIdStore.mockImplementation(
66+
() => mockDefaultIdentityIdStoreInstance,
67+
);
68+
MockCognitoAWSCredentialsAndIdentityIdProvider.mockImplementation(
69+
() => mockCognitoAWSCredentialsAndIdentityIdProviderInstance,
70+
);
5571
});
5672
beforeEach(() => {
5773
mockAmplifySingletonConfigure.mockImplementation((_, libraryOptions) => {
@@ -64,6 +80,8 @@ describe('initSingleton (DefaultAmplify)', () => {
6480

6581
afterEach(() => {
6682
MockCookieStorage.mockClear();
83+
MockCognitoAWSCredentialsAndIdentityIdProvider.mockClear();
84+
MockDefaultIdentityIdStore.mockClear();
6785
mockCognitoUserPoolsTokenProviderSetAuthConfig.mockReset();
6886
mockCognitoUserPoolsTokenProviderSetKeyValueStorage.mockReset();
6987
mockAmplifySingletonConfigure.mockReset();
@@ -252,13 +270,20 @@ describe('initSingleton (DefaultAmplify)', () => {
252270
expect(
253271
mockCognitoUserPoolsTokenProviderSetKeyValueStorage,
254272
).toHaveBeenCalledWith(mockCookieStorageInstance);
273+
expect(MockDefaultIdentityIdStore).toHaveBeenCalledWith(
274+
mockCookieStorageInstance,
275+
);
276+
expect(
277+
MockCognitoAWSCredentialsAndIdentityIdProvider,
278+
).toHaveBeenCalledWith(mockDefaultIdentityIdStoreInstance);
255279
expect(mockAmplifySingletonConfigure).toHaveBeenCalledWith(
256280
mockResourceConfig,
257281
{
258282
...libraryOptions,
259283
Auth: {
260284
tokenProvider: cognitoUserPoolsTokenProvider,
261-
credentialsProvider: cognitoCredentialsProvider,
285+
credentialsProvider:
286+
mockCognitoAWSCredentialsAndIdentityIdProviderInstance,
262287
},
263288
},
264289
);
@@ -345,7 +370,6 @@ describe('initSingleton (DefaultAmplify)', () => {
345370
expect(
346371
mockCognitoUserPoolsTokenProviderSetAuthConfig,
347372
).not.toHaveBeenCalled();
348-
expect(MockCookieStorage).not.toHaveBeenCalled();
349373
expect(
350374
mockCognitoUserPoolsTokenProviderSetKeyValueStorage,
351375
).not.toHaveBeenCalled();

0 commit comments

Comments
 (0)