Skip to content

Commit

Permalink
feat: Add file.exists
Browse files Browse the repository at this point in the history
  • Loading branch information
jyecusch committed Aug 7, 2023
2 parents 056f4f7 + e991f74 commit 8a7b82a
Show file tree
Hide file tree
Showing 7 changed files with 514 additions and 1 deletion.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@nitric/sdk",
"description": "Nitric NodeJS client sdk",
"nitric": "v0.32.0",
"nitric": "v0.33.0-rc.4",
"author": "Nitric <https://github.com/nitrictech>",
"repository": "https://github.com/nitrictech/node-sdk",
"main": "lib/index.js",
Expand Down
65 changes: 65 additions & 0 deletions src/api/storage/v0/storage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
StoragePreSignUrlRequest,
StorageListFilesResponse,
File,
StorageExistsResponse,
} from '@nitric/api/proto/storage/v1/storage_pb';
import { UnimplementedError } from '../../errors';
import {
Expand Down Expand Up @@ -162,6 +163,70 @@ describe('Storage Client Tests', () => {
expect(readMock).toBeCalledTimes(1);
});
});

describe('Given nitric.api.storage.StorageClient.Exists throws an error', () => {
const MOCK_ERROR = {
code: 2,
message: 'UNIMPLEMENTED',
};
let existsMock;

beforeAll(() => {
existsMock = jest
.spyOn(GrpcStorageClient.prototype, 'exists')
.mockImplementation((_, callback: any) => {
callback(MOCK_ERROR, null);

return null as any;
});
});

afterAll(() => {
jest.resetAllMocks();
});

test('Then StorageClient.exists should reject', async () => {
const storage = new Storage();
await expect(
storage.bucket('test_bucket').file('test/item').exists()
).rejects.toEqual(new UnimplementedError('UNIMPLEMENTED'));
});

test('The Grpc client for Storage.write should have been called exactly once', () => {
expect(existsMock).toBeCalledTimes(1);
});
});

describe('Given nitric.api.storage.StorageClient.Exists succeeds', () => {
let writeMock;
const MOCK_REPLY = new StorageExistsResponse();

beforeAll(() => {
writeMock = jest
.spyOn(GrpcStorageClient.prototype, 'exists')
.mockImplementation((_, callback: any) => {
callback(null, MOCK_REPLY);

return null as any;
});
});

afterAll(() => {
jest.resetAllMocks();
});

test('Then StorageClient.exists should resolve with success status', async () => {
const storage = new Storage();
await expect(
storage.bucket('test_bucket').file('test/item').exists()
).resolves.toBe(false);
});

test('The Grpc client for Storage.write should have been called exactly once', () => {
expect(writeMock).toBeCalledTimes(1);
});
});

describe('Given nitric.api.storage.StorageClient.Delete throws an error', () => {
const MOCK_ERROR = {
code: 2,
Expand Down
31 changes: 31 additions & 0 deletions src/api/storage/v0/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
StorageDeleteRequest,
StoragePreSignUrlRequest,
StorageListFilesRequest,
StorageExistsRequest,
} from '@nitric/api/proto/storage/v1/storage_pb';
import * as grpc from '@grpc/grpc-js';
import { fromGrpcError, InvalidArgumentError } from '../../errors';
Expand Down Expand Up @@ -314,6 +315,36 @@ export class File {
});
});
}

/**
* Determine if a file exists in a bucket.
*
* @returns A boolean promise.
*
* Example:
* ```typescript
* import { bucket } from "@nitric/sdk";
*
* const exampleBucket = bucket('exampleBucket').for('reading');
*
* const exists = await exampleBucket.file("my-item").exists();
* ```
*/
public async exists(): Promise<boolean> {
const request = new StorageExistsRequest();
request.setBucket(this.bucket.name);
request.setKey(this.name);

return new Promise((resolve, reject) => {
this.storage.StorageServiceClient.exists(request, (error, response) => {
if (error) {
reject(fromGrpcError(error));
} else {
resolve(response.getExists());
}
});
});
}
}

// Storage client singleton
Expand Down
5 changes: 5 additions & 0 deletions src/gen/proto/storage/v1/storage_grpc_pb.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ interface IStorageServiceService extends grpc.ServiceDefinition<grpc.UntypedServ
delete: grpc.MethodDefinition<proto_storage_v1_storage_pb.StorageDeleteRequest, proto_storage_v1_storage_pb.StorageDeleteResponse>;
preSignUrl: grpc.MethodDefinition<proto_storage_v1_storage_pb.StoragePreSignUrlRequest, proto_storage_v1_storage_pb.StoragePreSignUrlResponse>;
listFiles: grpc.MethodDefinition<proto_storage_v1_storage_pb.StorageListFilesRequest, proto_storage_v1_storage_pb.StorageListFilesResponse>;
exists: grpc.MethodDefinition<proto_storage_v1_storage_pb.StorageExistsRequest, proto_storage_v1_storage_pb.StorageExistsResponse>;
}

export const StorageServiceService: IStorageServiceService;
Expand All @@ -22,6 +23,7 @@ export interface IStorageServiceServer extends grpc.UntypedServiceImplementation
delete: grpc.handleUnaryCall<proto_storage_v1_storage_pb.StorageDeleteRequest, proto_storage_v1_storage_pb.StorageDeleteResponse>;
preSignUrl: grpc.handleUnaryCall<proto_storage_v1_storage_pb.StoragePreSignUrlRequest, proto_storage_v1_storage_pb.StoragePreSignUrlResponse>;
listFiles: grpc.handleUnaryCall<proto_storage_v1_storage_pb.StorageListFilesRequest, proto_storage_v1_storage_pb.StorageListFilesResponse>;
exists: grpc.handleUnaryCall<proto_storage_v1_storage_pb.StorageExistsRequest, proto_storage_v1_storage_pb.StorageExistsResponse>;
}

export class StorageServiceClient extends grpc.Client {
Expand All @@ -41,4 +43,7 @@ export class StorageServiceClient extends grpc.Client {
listFiles(argument: proto_storage_v1_storage_pb.StorageListFilesRequest, callback: grpc.requestCallback<proto_storage_v1_storage_pb.StorageListFilesResponse>): grpc.ClientUnaryCall;
listFiles(argument: proto_storage_v1_storage_pb.StorageListFilesRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback<proto_storage_v1_storage_pb.StorageListFilesResponse>): grpc.ClientUnaryCall;
listFiles(argument: proto_storage_v1_storage_pb.StorageListFilesRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback<proto_storage_v1_storage_pb.StorageListFilesResponse>): grpc.ClientUnaryCall;
exists(argument: proto_storage_v1_storage_pb.StorageExistsRequest, callback: grpc.requestCallback<proto_storage_v1_storage_pb.StorageExistsResponse>): grpc.ClientUnaryCall;
exists(argument: proto_storage_v1_storage_pb.StorageExistsRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback<proto_storage_v1_storage_pb.StorageExistsResponse>): grpc.ClientUnaryCall;
exists(argument: proto_storage_v1_storage_pb.StorageExistsRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback<proto_storage_v1_storage_pb.StorageExistsResponse>): grpc.ClientUnaryCall;
}
34 changes: 34 additions & 0 deletions src/gen/proto/storage/v1/storage_grpc_pb.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,28 @@ function deserialize_nitric_storage_v1_StorageDeleteResponse(buffer_arg) {
return proto_storage_v1_storage_pb.StorageDeleteResponse.deserializeBinary(new Uint8Array(buffer_arg));
}

function serialize_nitric_storage_v1_StorageExistsRequest(arg) {
if (!(arg instanceof proto_storage_v1_storage_pb.StorageExistsRequest)) {
throw new Error('Expected argument of type nitric.storage.v1.StorageExistsRequest');
}
return Buffer.from(arg.serializeBinary());
}

function deserialize_nitric_storage_v1_StorageExistsRequest(buffer_arg) {
return proto_storage_v1_storage_pb.StorageExistsRequest.deserializeBinary(new Uint8Array(buffer_arg));
}

function serialize_nitric_storage_v1_StorageExistsResponse(arg) {
if (!(arg instanceof proto_storage_v1_storage_pb.StorageExistsResponse)) {
throw new Error('Expected argument of type nitric.storage.v1.StorageExistsResponse');
}
return Buffer.from(arg.serializeBinary());
}

function deserialize_nitric_storage_v1_StorageExistsResponse(buffer_arg) {
return proto_storage_v1_storage_pb.StorageExistsResponse.deserializeBinary(new Uint8Array(buffer_arg));
}

function serialize_nitric_storage_v1_StorageListFilesRequest(arg) {
if (!(arg instanceof proto_storage_v1_storage_pb.StorageListFilesRequest)) {
throw new Error('Expected argument of type nitric.storage.v1.StorageListFilesRequest');
Expand Down Expand Up @@ -178,6 +200,18 @@ listFiles: {
responseSerialize: serialize_nitric_storage_v1_StorageListFilesResponse,
responseDeserialize: deserialize_nitric_storage_v1_StorageListFilesResponse,
},
// Determine is an object exists in a bucket
exists: {
path: '/nitric.storage.v1.StorageService/Exists',
requestStream: false,
responseStream: false,
requestType: proto_storage_v1_storage_pb.StorageExistsRequest,
responseType: proto_storage_v1_storage_pb.StorageExistsResponse,
requestSerialize: serialize_nitric_storage_v1_StorageExistsRequest,
requestDeserialize: deserialize_nitric_storage_v1_StorageExistsRequest,
responseSerialize: serialize_nitric_storage_v1_StorageExistsResponse,
responseDeserialize: deserialize_nitric_storage_v1_StorageExistsResponse,
},
};

exports.StorageServiceClient = grpc.makeGenericClientConstructor(StorageServiceService);
44 changes: 44 additions & 0 deletions src/gen/proto/storage/v1/storage_pb.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,3 +261,47 @@ export namespace StorageListFilesResponse {
}
}

export class StorageExistsRequest extends jspb.Message {
getBucket(): string;
setBucket(value: string): void;

getKey(): string;
setKey(value: string): void;

serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): StorageExistsRequest.AsObject;
static toObject(includeInstance: boolean, msg: StorageExistsRequest): StorageExistsRequest.AsObject;
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
static serializeBinaryToWriter(message: StorageExistsRequest, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): StorageExistsRequest;
static deserializeBinaryFromReader(message: StorageExistsRequest, reader: jspb.BinaryReader): StorageExistsRequest;
}

export namespace StorageExistsRequest {
export type AsObject = {
bucket: string,
key: string,
}
}

export class StorageExistsResponse extends jspb.Message {
getExists(): boolean;
setExists(value: boolean): void;

serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): StorageExistsResponse.AsObject;
static toObject(includeInstance: boolean, msg: StorageExistsResponse): StorageExistsResponse.AsObject;
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
static serializeBinaryToWriter(message: StorageExistsResponse, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): StorageExistsResponse;
static deserializeBinaryFromReader(message: StorageExistsResponse, reader: jspb.BinaryReader): StorageExistsResponse;
}

export namespace StorageExistsResponse {
export type AsObject = {
exists: boolean,
}
}

Loading

0 comments on commit 8a7b82a

Please sign in to comment.