Skip to content

Commit 53ddf89

Browse files
authored
Merge pull request #129 from tjholm/list-files
Storage: Add ability to list files in a bucket.
2 parents 942b107 + b5a462b commit 53ddf89

File tree

4 files changed

+101
-7
lines changed

4 files changed

+101
-7
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
],
2828
"dependencies": {
2929
"@grpc/grpc-js": "^1.5.9",
30-
"@nitric/api": "0.15.0",
30+
"@nitric/api": "0.16.0",
3131
"google-protobuf": "3.14.0",
3232
"tslib": "^2.1.0"
3333
},

src/api/storage/v0/storage.test.ts

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// limitations under the License.
1414
import { FileMode, Storage } from './storage';
1515
import { StorageServiceClient as GrpcStorageClient } from '@nitric/api/proto/storage/v1/storage_grpc_pb';
16-
import { StorageWriteResponse, StorageReadResponse, StorageDeleteResponse, StoragePreSignUrlResponse, StoragePreSignUrlRequest } from '@nitric/api/proto/storage/v1/storage_pb';
16+
import { StorageWriteResponse, StorageReadResponse, StorageDeleteResponse, StoragePreSignUrlResponse, StoragePreSignUrlRequest, StorageListFilesResponse, File } from '@nitric/api/proto/storage/v1/storage_pb';
1717
import { UnimplementedError } from '../../errors';
1818

1919
describe('Storage Client Tests', () => {
@@ -321,7 +321,7 @@ describe('Storage Client Tests', () => {
321321
preSignUrlMock.mockClear();
322322
const client = new Storage().bucket('test_bucket').file('test/item');
323323
signUrl = await client.getDownloadUrl()
324-
})
324+
});
325325

326326
test('Then file.signUrl should delete the bytes from the bucket', () => {
327327
expect(signUrl).toEqual("testingUrl");
@@ -341,4 +341,75 @@ describe('Storage Client Tests', () => {
341341
});
342342
});
343343
});
344+
345+
describe('Given nitric.api.storage.StorageClient.ListFiles throws an error', () => {
346+
const MOCK_ERROR = {
347+
code: 2,
348+
message: 'UNIMPLEMENTED',
349+
};
350+
351+
let listFilesMock;
352+
353+
beforeAll(() => {
354+
listFilesMock = jest
355+
.spyOn(GrpcStorageClient.prototype, 'listFiles')
356+
.mockImplementation((_, callback: any) => {
357+
callback(MOCK_ERROR, null);
358+
359+
return null as any;
360+
});
361+
});
362+
363+
afterAll(() => {
364+
jest.resetAllMocks();
365+
});
366+
367+
test('Then StorageClient.listFiles should reject', async () => {
368+
const client = new Storage();
369+
await expect(client.bucket('test').files()).rejects.toEqual(
370+
new UnimplementedError("UNIMPLEMENTED")
371+
);
372+
});
373+
374+
test('The Grpc client for Storage.listFiles should have been called exactly once', () => {
375+
expect(listFilesMock).toBeCalledTimes(1);
376+
});
377+
});
378+
379+
describe('Given nitric.api.storage.StorageClient.ListFiles succeeds', () => {
380+
const MOCK_REPLY = new StorageListFilesResponse();
381+
MOCK_REPLY.setFilesList(["test/test.txt"].map((k) => {
382+
const f = new File();
383+
f.setKey(k);
384+
return f;
385+
}));
386+
387+
let listFilesMock;
388+
389+
beforeAll(() => {
390+
listFilesMock = jest
391+
.spyOn(GrpcStorageClient.prototype, 'listFiles')
392+
.mockImplementation((_, callback: any) => {
393+
callback(null, MOCK_REPLY);
394+
395+
return null as any;
396+
});
397+
});
398+
399+
afterAll(() => {
400+
jest.resetAllMocks();
401+
});
402+
403+
test('Then StorageClient.listFiles should return files', async () => {
404+
const client = new Storage();
405+
const files = await client.bucket('test').files();
406+
407+
expect(files).toHaveLength(1);
408+
expect(files[0].name).toBe('test/test.txt')
409+
});
410+
411+
test('The Grpc client for Storage.listFiles should have been called exactly once', () => {
412+
expect(listFilesMock).toBeCalledTimes(1);
413+
});
414+
});
344415
});

src/api/storage/v0/storage.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
StorageReadRequest,
1919
StorageDeleteRequest,
2020
StoragePreSignUrlRequest,
21+
StorageListFilesRequest,
2122
} from '@nitric/api/proto/storage/v1/storage_pb';
2223
import * as grpc from '@grpc/grpc-js';
2324
import { fromGrpcError, InvalidArgumentError } from '../../errors';
@@ -63,6 +64,28 @@ export class Bucket {
6364
this.name = name;
6465
}
6566

67+
/**
68+
* Retrieve a list of files on the bucket
69+
* @returns An array of file references
70+
*/
71+
public async files(): Promise<File[]> {
72+
const request = new StorageListFilesRequest();
73+
74+
request.setBucketName(this.name);
75+
76+
return await new Promise<File[]>((res, rej) => {
77+
this.storage.StorageServiceClient.listFiles(request, (err, data) => {
78+
if (err) {
79+
rej(fromGrpcError(err));
80+
}
81+
82+
res(data.getFilesList().map(f => {
83+
return new File(this.storage, this, f.getKey());
84+
}));
85+
});
86+
});
87+
}
88+
6689
public file(name: string) {
6790
if (!name) {
6891
throw new InvalidArgumentError(

yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -531,10 +531,10 @@
531531
"@types/yargs" "^15.0.0"
532532
chalk "^4.0.0"
533533

534-
"@nitric/api@0.15.0":
535-
version "0.15.0"
536-
resolved "https://registry.yarnpkg.com/@nitric/api/-/api-0.15.0.tgz#4e8825dd0fda21437b477e6c81ab2bb1f15a22e6"
537-
integrity sha512-xxldlWIAZHhkrfHsueEcZ9zaoSLTSAtHlrrZaodF5bKIJigbXkI3GLhSLm1hOcFGerguUx1y8l+Pc/slPI+s6g==
534+
"@nitric/api@0.16.0":
535+
version "0.16.0"
536+
resolved "https://registry.yarnpkg.com/@nitric/api/-/api-0.16.0.tgz#233a1aa3cb4ef29188b5336c0e70d067e027cb26"
537+
integrity sha512-dXJfPlAe/G35nSVn4IIvjB0TqWYJPyYNOqu1TdjV14vy++L7ALkabVJtKULQQ94+71okvfmO4kMHQeKsYYS/Mw==
538538
dependencies:
539539
google-protobuf "3.14.0"
540540
tslib "^2.1.0"

0 commit comments

Comments
 (0)