Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Revert getProperties API #11419

Merged
merged 2 commits into from
May 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/predictions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
"name": "Predictions (Identify provider)",
"path": "./lib-esm/index.js",
"import": "{ Amplify, Predictions, AmazonAIIdentifyPredictionsProvider }",
"limit": "105 kB"
"limit": "104.5 kB"
},
{
"name": "Predictions (Interpret provider)",
Expand Down
74 changes: 0 additions & 74 deletions packages/storage/__tests__/Storage-unit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,6 @@ class TestCustomProvider implements StorageProvider {
return Promise.resolve({ newKey: 'get' });
}

getProperties(key: string, options?: CustomProviderConfig) {
return Promise.resolve({ newKey: 'getProperties' });
}

put(key: string, object: any, config: CustomProviderConfig) {
return Promise.resolve({ newKey: 'put' });
}
Expand Down Expand Up @@ -618,76 +614,6 @@ describe('Storage', () => {
});
});

describe('getProperties test', () => {
let storage: StorageClass;
let provider: StorageProvider;
let getPropertiesSpy: jest.SpyInstance;

beforeEach(() => {
storage = new StorageClass();
provider = new AWSStorageProvider();
storage.addPluggable(provider);
storage.configure(options);
getPropertiesSpy = jest
.spyOn(AWSStorageProvider.prototype, 'getProperties')
.mockImplementation(() =>
Promise.resolve({
contentType: 'text/plain',
contentLength: 100,
eTag: 'etag',
lastModified: new Date('20 Oct 2023'),
metadata: { key: '' },
})
);
});

afterEach(() => {
jest.clearAllMocks();
});

describe('with default S3 provider', () => {
test('get properties of object successfully', async () => {
const result = await storage.getProperties('key');
expect(getPropertiesSpy).toBeCalled();
expect(result).toEqual({
contentType: 'text/plain',
contentLength: 100,
eTag: 'etag',
lastModified: new Date('20 Oct 2023'),
metadata: { key: '' },
});
getPropertiesSpy.mockClear();
});

test('get properties of object with available config', async () => {
await storage.getProperties('key', {
SSECustomerAlgorithm: 'aes256',
SSECustomerKey: 'key',
SSECustomerKeyMD5: 'md5',
});
});
});

test('get properties without provider', async () => {
const storage = new StorageClass();
try {
await storage.getProperties('key');
} catch (err) {
expect(err).toEqual(new Error('No plugin found with providerName'));
}
});

test('get properties with custom provider should work with no generic type provided', async () => {
const customProvider = new TestCustomProvider();
const customProviderGetSpy = jest.spyOn(customProvider, 'getProperties');
storage.addPluggable(customProvider);
await storage.getProperties('key', {
provider: 'customProvider',
});
expect(customProviderGetSpy).toBeCalled();
});
});

describe('put test', () => {
let storage: StorageClass;
let provider: StorageProvider;
Expand Down
72 changes: 5 additions & 67 deletions packages/storage/__tests__/providers/AWSS3Provider-unit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
ListObjectsV2Command,
CreateMultipartUploadCommand,
UploadPartCommand,
HeadObjectCommand,
} from '@aws-sdk/client-s3';
import { S3RequestPresigner } from '@aws-sdk/s3-request-presigner';

Expand Down Expand Up @@ -53,14 +52,6 @@ S3Client.prototype.send = jest.fn(async command => {
Contents: [resultObj],
IsTruncated: false,
};
} else if (command instanceof HeadObjectCommand) {
return {
ContentLength: '100',
ContentType: 'text/plain',
ETag: 'etag',
LastModified: 'lastmodified',
Metadata: { key: 'value' },
};
}
return 'data';
});
Expand Down Expand Up @@ -528,7 +519,6 @@ describe('StorageProvider test', () => {
return Promise.resolve(credentials);
});
});

test('get existing object with validateObjectExistence option', async () => {
expect.assertions(5);
const options_with_validateObjectExistence = Object.assign(
Expand Down Expand Up @@ -566,6 +556,11 @@ describe('StorageProvider test', () => {

test('get non-existing object with validateObjectExistence option', async () => {
expect.assertions(2);
jest.spyOn(Credentials, 'get').mockImplementationOnce(() => {
return new Promise((res, rej) => {
res({});
});
});
const dispatchSpy = jest.spyOn(StorageUtils, 'dispatchStorageEvent');
jest
.spyOn(S3Client.prototype, 'send')
Expand All @@ -591,63 +586,6 @@ describe('StorageProvider test', () => {
});
});

describe('getProperties test', () => {
beforeEach(() => {
jest.spyOn(Credentials, 'get').mockImplementationOnce(() => {
return Promise.resolve(credentials);
});
});

test('getProperties successfully', async () => {
expect.assertions(4);
const spyon = jest.spyOn(S3Client.prototype, 'send');
const dispatchSpy = jest.spyOn(StorageUtils, 'dispatchStorageEvent');
const metadata = { key: 'value' };
expect(await storage.getProperties('key')).toEqual({
contentLength: '100',
contentType: 'text/plain',
eTag: 'etag',
lastModified: 'lastmodified',
metadata,
});
expect(dispatchSpy).toHaveBeenCalledTimes(1);
expect(dispatchSpy).toBeCalledWith(
false,
'getProperties',
{ method: 'getProperties', result: 'success' },
null,
'getProperties successful for key'
);
expect(spyon.mock.calls[0][0].input).toEqual({
Bucket: 'bucket',
Key: 'public/key',
});
spyon.mockClear();
});

test('get properties of non-existing object', async () => {
expect.assertions(2);
const dispatchSpy = jest.spyOn(StorageUtils, 'dispatchStorageEvent');
jest
.spyOn(S3Client.prototype, 'send')
.mockImplementationOnce(async params => {
throw { $metadata: { httpStatusCode: 404 }, name: 'NotFound' };
});
try {
await storage.getProperties('invalid_key');
} catch (error) {
expect(error.$metadata.httpStatusCode).toBe(404);
expect(dispatchSpy).toBeCalledWith(
false,
'getProperties',
{ method: 'getProperties', result: 'failed' },
null,
'invalid_key not found'
);
}
});
});

describe('put test', () => {
afterEach(() => {
jest.clearAllMocks();
Expand Down
2 changes: 1 addition & 1 deletion packages/storage/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
"name": "Storage (top-level class)",
"path": "./lib-esm/index.js",
"import": "{ Amplify, Storage }",
"limit": "87.02 kB"
"limit": "87 kB"
}
],
"jest": {
Expand Down
61 changes: 17 additions & 44 deletions packages/storage/src/Storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ import {
StorageListOutput,
StorageCopyOutput,
UploadTask,
StorageGetPropertiesConfig,
StorageGetPropertiesOutput,
} from './types';
import axios, { CancelTokenSource } from 'axios';
import { PutObjectCommandInput } from '@aws-sdk/client-s3';
Expand Down Expand Up @@ -248,22 +246,22 @@ export class Storage {
config?: StorageCopyConfig<T>
): StorageCopyOutput<T> {
const provider = config?.provider || DEFAULT_PROVIDER;
const plugin = this._pluggables.find(
const prov = this._pluggables.find(
pluggable => pluggable.getProviderName() === provider
);
if (plugin === undefined) {
if (prov === undefined) {
logger.debug('No plugin found with providerName', provider);
return Promise.reject(
'No plugin found in Storage for the provider'
) as StorageCopyOutput<T>;
}
const cancelTokenSource = this.getCancellableTokenSource();
if (typeof plugin.copy !== 'function') {
if (typeof prov.copy !== 'function') {
return Promise.reject(
`.copy is not implemented on provider ${plugin.getProviderName()}`
`.copy is not implemented on provider ${prov.getProviderName()}`
) as StorageCopyOutput<T>;
}
const responsePromise = plugin.copy(src, dest, {
const responsePromise = prov.copy(src, dest, {
...config,
cancelTokenSource,
});
Expand All @@ -287,17 +285,17 @@ export class Storage {
T extends StorageProvider | { [key: string]: any; download?: boolean }
>(key: string, config?: StorageGetConfig<T>): StorageGetOutput<T> {
const provider = config?.provider || DEFAULT_PROVIDER;
const plugin = this._pluggables.find(
const prov = this._pluggables.find(
pluggable => pluggable.getProviderName() === provider
);
if (plugin === undefined) {
if (prov === undefined) {
logger.debug('No plugin found with providerName', provider);
return Promise.reject(
'No plugin found in Storage for the provider'
) as StorageGetOutput<T>;
}
const cancelTokenSource = this.getCancellableTokenSource();
const responsePromise = plugin.get(key, {
const responsePromise = prov.get(key, {
...config,
cancelTokenSource,
});
Expand All @@ -309,31 +307,6 @@ export class Storage {
return axios.isCancel(error);
}

public getProperties<T extends StorageProvider | { [key: string]: any }>(
key: string,
config?: StorageGetPropertiesConfig<T>
): StorageGetPropertiesOutput<T> {
const provider = config?.provider || DEFAULT_PROVIDER;
const plugin = this._pluggables.find(
pluggable => pluggable.getProviderName() === provider
);
if (plugin === undefined) {
logger.debug('No plugin found with providerName', provider);
throw new Error('No plugin found with providerName');
}
const cancelTokenSource = this.getCancellableTokenSource();

if (typeof plugin.getProperties !== 'function') {
throw new Error(
`.getProperties is not implemented on provider ${plugin.getProviderName()}`
);
}
const responsePromise = plugin.getProperties(key, {
...config,
});
this.updateRequestToBeCancellable(responsePromise, cancelTokenSource);
return responsePromise as StorageGetPropertiesOutput<T>;
}
/**
* Put a file in storage bucket specified to configure method
* @param key - key of the object
Expand All @@ -353,17 +326,17 @@ export class Storage {
config?: StoragePutConfig<T>
): StoragePutOutput<T> {
const provider = config?.provider || DEFAULT_PROVIDER;
const plugin = this._pluggables.find(
const prov = this._pluggables.find(
pluggable => pluggable.getProviderName() === provider
);
if (plugin === undefined) {
if (prov === undefined) {
logger.debug('No plugin found with providerName', provider);
return Promise.reject(
'No plugin found in Storage for the provider'
) as StoragePutOutput<T>;
}
const cancelTokenSource = this.getCancellableTokenSource();
const response = plugin.put(key, object, {
const response = prov.put(key, object, {
...config,
cancelTokenSource,
});
Expand All @@ -388,16 +361,16 @@ export class Storage {
config?: StorageRemoveConfig<T>
): StorageRemoveOutput<T> {
const provider = config?.provider || DEFAULT_PROVIDER;
const plugin = this._pluggables.find(
const prov = this._pluggables.find(
pluggable => pluggable.getProviderName() === provider
);
if (plugin === undefined) {
if (prov === undefined) {
logger.debug('No plugin found with providerName', provider);
return Promise.reject(
'No plugin found in Storage for the provider'
) as StorageRemoveOutput<T>;
}
return plugin.remove(key, config) as StorageRemoveOutput<T>;
return prov.remove(key, config) as StorageRemoveOutput<T>;
}

/**
Expand All @@ -415,16 +388,16 @@ export class Storage {
config?: StorageListConfig<T>
): StorageListOutput<T> {
const provider = config?.provider || DEFAULT_PROVIDER;
const plugin = this._pluggables.find(
const prov = this._pluggables.find(
pluggable => pluggable.getProviderName() === provider
);
if (plugin === undefined) {
if (prov === undefined) {
logger.debug('No plugin found with providerName', provider);
return Promise.reject(
'No plugin found in Storage for the provider'
) as StorageListOutput<T>;
}
return plugin.list(path, config) as StorageListOutput<T>;
return prov.list(path, config) as StorageListOutput<T>;
}
}

Expand Down
Loading