Skip to content

Commit 9575398

Browse files
committed
feat(storage): migrate storage APIs to AmplifyContext
Thread AmplifyContext explicitly through the storage package instead of relying on the global Amplify singleton, mirroring the landed auth migration (#14836). - Public S3 APIs (copy, downloadData, getProperties, getUrl, list, remove, uploadData) gain (ctx, input) overloads with a global fallback via resolveCtxArgs - Internal workers, resolveS3ConfigAndInput, and access-grant internals take ctx: AmplifyContext; config via ctx.resourcesConfig and auth via ctx.fetchAuthSession - Server wrappers accept AmplifyContext | AmplifyServer.ContextSpec via new resolveServerContext, preserving adapter-nextjs compatibility - Tests migrated to a branded mock AmplifyContext (createMockAmplifyContext) Excludes the endpoint-provider feature (depends on unlanded core Storage types) and does not delete server impls (adapter-nextjs split not yet landed).
1 parent 9011273 commit 9575398

57 files changed

Lines changed: 770 additions & 461 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

packages/storage/__tests__/internals/apis/copy.test.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
3-
import { AmplifyClassV6 } from '@aws-amplify/core';
43

54
import { copy as advancedCopy } from '../../../src/internals';
65
import { copy as copyInternal } from '../../../src/providers/s3/apis/internal/copy';
6+
import { createMockAmplifyContext } from '../../testUtils/mockAmplifyContext';
77

88
jest.mock('../../../src/providers/s3/apis/internal/copy');
99
const mockedCopyInternal = jest.mocked(copyInternal);
10+
const mockCtx = createMockAmplifyContext();
1011

1112
describe('copy (internals)', () => {
1213
beforeEach(() => {
@@ -44,10 +45,10 @@ describe('copy (internals)', () => {
4445
customEndpoint,
4546
},
4647
};
47-
const result = await advancedCopy(copyInputWithAdvancedOptions);
48+
const result = await advancedCopy(mockCtx, copyInputWithAdvancedOptions);
4849
expect(mockedCopyInternal).toHaveBeenCalledTimes(1);
4950
expect(mockedCopyInternal).toHaveBeenCalledWith(
50-
expect.any(AmplifyClassV6),
51+
mockCtx,
5152
copyInputWithAdvancedOptions,
5253
);
5354
expect(result).toEqual({

packages/storage/__tests__/internals/apis/downloadData.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33

44
import { downloadData as advancedDownloadData } from '../../../src/internals';
55
import { downloadData as downloadDataInternal } from '../../../src/providers/s3/apis/internal/downloadData';
6+
import { createMockAmplifyContext } from '../../testUtils/mockAmplifyContext';
67

78
jest.mock('../../../src/providers/s3/apis/internal/downloadData');
89
const mockedDownloadDataInternal = jest.mocked(downloadDataInternal);
10+
const mockCtx = createMockAmplifyContext();
911

1012
describe('downloadData (internal)', () => {
1113
beforeEach(() => {
@@ -43,7 +45,7 @@ describe('downloadData (internal)', () => {
4345
const onProgress = jest.fn();
4446
const bytesRange = { start: 1024, end: 2048 };
4547

46-
const output = await advancedDownloadData({
48+
const output = await advancedDownloadData(mockCtx, {
4749
path: 'input/path/to/mock/object',
4850
options: {
4951
customEndpoint,
@@ -57,7 +59,7 @@ describe('downloadData (internal)', () => {
5759
});
5860

5961
expect(mockedDownloadDataInternal).toHaveBeenCalledTimes(1);
60-
expect(mockedDownloadDataInternal).toHaveBeenCalledWith({
62+
expect(mockedDownloadDataInternal).toHaveBeenCalledWith(mockCtx, {
6163
path: 'input/path/to/mock/object',
6264
options: {
6365
customEndpoint,

packages/storage/__tests__/internals/apis/getProperties.test.ts

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
3-
import { AmplifyClassV6 } from '@aws-amplify/core';
43

54
import { getProperties as advancedGetProperties } from '../../../src/internals';
65
import { getProperties as getPropertiesInternal } from '../../../src/providers/s3/apis/internal/getProperties';
6+
import { createMockAmplifyContext } from '../../testUtils/mockAmplifyContext';
77

88
jest.mock('../../../src/providers/s3/apis/internal/getProperties');
99
const mockedGetPropertiesInternal = jest.mocked(getPropertiesInternal);
10+
const mockCtx = createMockAmplifyContext();
1011

1112
describe('getProperties (internal)', () => {
1213
beforeEach(() => {
@@ -32,7 +33,7 @@ describe('getProperties (internal)', () => {
3233
expiration: new Date(),
3334
},
3435
});
35-
const result = await advancedGetProperties({
36+
const result = await advancedGetProperties(mockCtx, {
3637
path: 'input/path/to/mock/object',
3738
options: {
3839
customEndpoint,
@@ -43,19 +44,16 @@ describe('getProperties (internal)', () => {
4344
},
4445
});
4546
expect(mockedGetPropertiesInternal).toHaveBeenCalledTimes(1);
46-
expect(mockedGetPropertiesInternal).toHaveBeenCalledWith(
47-
expect.any(AmplifyClassV6),
48-
{
49-
path: 'input/path/to/mock/object',
50-
options: {
51-
customEndpoint,
52-
useAccelerateEndpoint,
53-
bucket,
54-
expectedBucketOwner,
55-
locationCredentialsProvider,
56-
},
47+
expect(mockedGetPropertiesInternal).toHaveBeenCalledWith(mockCtx, {
48+
path: 'input/path/to/mock/object',
49+
options: {
50+
customEndpoint,
51+
useAccelerateEndpoint,
52+
bucket,
53+
expectedBucketOwner,
54+
locationCredentialsProvider,
5755
},
58-
);
56+
});
5957
expect(result).toEqual({
6058
path: 'output/path/to/mock/object',
6159
});

packages/storage/__tests__/internals/apis/getUrl.test.ts

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
3-
import { AmplifyClassV6 } from '@aws-amplify/core';
43

54
import { getUrl as advancedGetUrl } from '../../../src/internals';
65
import { getUrl as getUrlInternal } from '../../../src/providers/s3/apis/internal/getUrl';
6+
import { createMockAmplifyContext } from '../../testUtils/mockAmplifyContext';
77

88
jest.mock('../../../src/providers/s3/apis/internal/getUrl');
99
const mockedGetUrlInternal = jest.mocked(getUrlInternal);
10+
const mockCtx = createMockAmplifyContext();
1011

1112
const MOCK_URL = new URL('https://s3.aws/mock-presigned-url');
1213
const MOCK_DATE = new Date();
@@ -41,7 +42,7 @@ describe('getUrl (internal)', () => {
4142
expiration: new Date(),
4243
},
4344
});
44-
const result = await advancedGetUrl({
45+
const result = await advancedGetUrl(mockCtx, {
4546
path: 'input/path/to/mock/object',
4647
options: {
4748
customEndpoint,
@@ -56,23 +57,20 @@ describe('getUrl (internal)', () => {
5657
},
5758
});
5859
expect(mockedGetUrlInternal).toHaveBeenCalledTimes(1);
59-
expect(mockedGetUrlInternal).toHaveBeenCalledWith(
60-
expect.any(AmplifyClassV6),
61-
{
62-
path: 'input/path/to/mock/object',
63-
options: {
64-
customEndpoint,
65-
useAccelerateEndpoint,
66-
bucket,
67-
validateObjectExistence,
68-
expiresIn,
69-
contentDisposition,
70-
contentType,
71-
expectedBucketOwner,
72-
locationCredentialsProvider,
73-
},
60+
expect(mockedGetUrlInternal).toHaveBeenCalledWith(mockCtx, {
61+
path: 'input/path/to/mock/object',
62+
options: {
63+
customEndpoint,
64+
useAccelerateEndpoint,
65+
bucket,
66+
validateObjectExistence,
67+
expiresIn,
68+
contentDisposition,
69+
contentType,
70+
expectedBucketOwner,
71+
locationCredentialsProvider,
7472
},
75-
);
73+
});
7674
expect(result).toEqual({
7775
url: MOCK_URL,
7876
expiresAt: MOCK_DATE,

packages/storage/__tests__/internals/apis/list.test.ts

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
3-
import { AmplifyClassV6 } from '@aws-amplify/core';
43

54
import { list as advancedList } from '../../../src/internals';
65
import { list as listInternal } from '../../../src/providers/s3/apis/internal/list';
6+
import { createMockAmplifyContext } from '../../testUtils/mockAmplifyContext';
77

88
jest.mock('../../../src/providers/s3/apis/internal/list');
99
const mockedListInternal = jest.mocked(listInternal);
10+
const mockCtx = createMockAmplifyContext();
1011

1112
describe('list (internals)', () => {
1213
beforeEach(() => {
@@ -29,7 +30,7 @@ describe('list (internals)', () => {
2930
expiration: new Date(),
3031
},
3132
});
32-
const result = await advancedList({
33+
const result = await advancedList(mockCtx, {
3334
path: 'input/path/to/mock/object',
3435
options: {
3536
customEndpoint,
@@ -40,19 +41,16 @@ describe('list (internals)', () => {
4041
},
4142
});
4243
expect(mockedListInternal).toHaveBeenCalledTimes(1);
43-
expect(mockedListInternal).toHaveBeenCalledWith(
44-
expect.any(AmplifyClassV6),
45-
{
46-
path: 'input/path/to/mock/object',
47-
options: {
48-
customEndpoint,
49-
useAccelerateEndpoint,
50-
bucket,
51-
expectedBucketOwner,
52-
locationCredentialsProvider,
53-
},
44+
expect(mockedListInternal).toHaveBeenCalledWith(mockCtx, {
45+
path: 'input/path/to/mock/object',
46+
options: {
47+
customEndpoint,
48+
useAccelerateEndpoint,
49+
bucket,
50+
expectedBucketOwner,
51+
locationCredentialsProvider,
5452
},
55-
);
53+
});
5654
expect(result).toEqual({
5755
items: [],
5856
});

packages/storage/__tests__/internals/apis/listPaths/listPaths.test.ts

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,12 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
import { Amplify, AuthTokens, fetchAuthSession } from '@aws-amplify/core';
4+
import { AmplifyContext, AuthTokens } from '@aws-amplify/core';
55

66
import { resolveLocationsForCurrentSession } from '../../../../src/internals/apis/listPaths/resolveLocationsForCurrentSession';
77
import { getHighestPrecedenceUserGroup } from '../../../../src/internals/apis/listPaths/getHighestPrecedenceUserGroup';
88
import { listPaths } from '../../../../src/internals';
99

10-
jest.mock('@aws-amplify/core', () => ({
11-
ConsoleLogger: jest.fn(),
12-
Amplify: {
13-
getConfig: jest.fn(),
14-
Auth: {
15-
getConfig: jest.fn(),
16-
fetchAuthSession: jest.fn(),
17-
},
18-
},
19-
fetchAuthSession: jest.fn(),
20-
}));
2110
jest.mock(
2211
'../../../../src/internals/apis/listPaths/resolveLocationsForCurrentSession',
2312
);
@@ -32,8 +21,20 @@ const credentials = {
3221
};
3322
const identityId = 'identityId';
3423

35-
const mockGetConfig = jest.mocked(Amplify.getConfig);
36-
const mockFetchAuthSession = jest.mocked(fetchAuthSession);
24+
const mockGetConfig = jest.fn();
25+
const mockFetchAuthSession = jest.fn();
26+
// listPaths now receives a required AmplifyContext. Back resourcesConfig with
27+
// a jest.fn so tests can vary config per-case, and expose fetchAuthSession as a
28+
// jest.fn for session/token control.
29+
const mockCtx: AmplifyContext = {
30+
get resourcesConfig() {
31+
return mockGetConfig();
32+
},
33+
libraryOptions: {},
34+
fetchAuthSession: mockFetchAuthSession,
35+
clearCredentials: jest.fn(),
36+
getTokens: jest.fn(),
37+
};
3738
const mockResolveLocationsFromCurrentSession =
3839
resolveLocationsForCurrentSession as jest.Mock;
3940
const mockGetHighestPrecedenceUserGroup = jest.mocked(
@@ -99,7 +100,7 @@ describe('listPaths', () => {
99100
Storage: { S3: { buckets: undefined } },
100101
});
101102

102-
const result = await listPaths();
103+
const result = await listPaths(mockCtx);
103104

104105
expect(result).toEqual({ locations: [] });
105106
});
@@ -118,7 +119,7 @@ describe('listPaths', () => {
118119
},
119120
]);
120121

121-
const result = await listPaths();
122+
const result = await listPaths(mockCtx);
122123

123124
expect(result).toEqual({
124125
locations: [
@@ -157,7 +158,7 @@ describe('listPaths', () => {
157158
prefix: '/path1',
158159
},
159160
});
160-
await listPaths();
161+
await listPaths(mockCtx);
161162

162163
expect(mockResolveLocationsFromCurrentSession).toHaveBeenCalled();
163164
expect(mockResolveLocationsFromCurrentSession).toHaveBeenCalledWith({
@@ -189,7 +190,7 @@ describe('listPaths', () => {
189190
});
190191
mockGetHighestPrecedenceUserGroup.mockReturnValue('admin');
191192

192-
await listPaths();
193+
await listPaths(mockCtx);
193194

194195
expect(mockResolveLocationsFromCurrentSession).toHaveBeenCalled();
195196
expect(mockResolveLocationsFromCurrentSession).toHaveBeenCalledWith({

packages/storage/__tests__/internals/apis/remove.test.ts

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
3-
import { AmplifyClassV6 } from '@aws-amplify/core';
43

54
import { remove as advancedRemove } from '../../../src/internals';
65
import { remove as removeInternal } from '../../../src/providers/s3/apis/internal/remove';
6+
import { createMockAmplifyContext } from '../../testUtils/mockAmplifyContext';
77

88
jest.mock('../../../src/providers/s3/apis/internal/remove');
99
const mockedRemoveInternal = jest.mocked(removeInternal);
10+
const mockCtx = createMockAmplifyContext();
1011

1112
describe('remove (internal)', () => {
1213
beforeEach(() => {
@@ -33,7 +34,7 @@ describe('remove (internal)', () => {
3334
},
3435
});
3536

36-
const result = await advancedRemove({
37+
const result = await advancedRemove(mockCtx, {
3738
path: 'input/path/to/mock/object',
3839
options: {
3940
customEndpoint,
@@ -45,19 +46,16 @@ describe('remove (internal)', () => {
4546
});
4647

4748
expect(mockedRemoveInternal).toHaveBeenCalledTimes(1);
48-
expect(mockedRemoveInternal).toHaveBeenCalledWith(
49-
expect.any(AmplifyClassV6),
50-
{
51-
path: 'input/path/to/mock/object',
52-
options: {
53-
customEndpoint,
54-
useAccelerateEndpoint,
55-
bucket,
56-
expectedBucketOwner,
57-
locationCredentialsProvider,
58-
},
49+
expect(mockedRemoveInternal).toHaveBeenCalledWith(mockCtx, {
50+
path: 'input/path/to/mock/object',
51+
options: {
52+
customEndpoint,
53+
useAccelerateEndpoint,
54+
bucket,
55+
expectedBucketOwner,
56+
locationCredentialsProvider,
5957
},
60-
);
58+
});
6159
expect(result).toEqual({
6260
path: 'output/path/to/mock/object',
6361
});

packages/storage/__tests__/internals/apis/uploadData.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
import { Amplify } from '@aws-amplify/core';
5-
64
import { uploadData as advancedUploadData } from '../../../src/internals';
75
import { uploadData as uploadDataInternal } from '../../../src/providers/s3/apis/internal/uploadData';
6+
import { createMockAmplifyContext } from '../../testUtils/mockAmplifyContext';
87

98
jest.mock('../../../src/providers/s3/apis/internal/uploadData');
109
const mockedUploadDataInternal = jest.mocked(uploadDataInternal);
1110
const mockedUploadTask = 'UPLOAD_TASK';
11+
const mockCtx = createMockAmplifyContext();
1212

1313
const expectedCtx = {
14-
amplify: Amplify,
14+
amplify: mockCtx,
1515
readFile: expect.any(Function),
1616
toBase64: expect.any(Function),
1717
};
@@ -43,7 +43,7 @@ describe('uploadData (internal)', () => {
4343
const onProgress = jest.fn();
4444
const metadata = { foo: 'bar' };
4545

46-
const result = advancedUploadData({
46+
const result = advancedUploadData(mockCtx, {
4747
path: 'input/path/to/mock/object',
4848
data: 'data',
4949
options: {

0 commit comments

Comments
 (0)