Skip to content

Commit

Permalink
feat: add before and after request methods to base service (#961)
Browse files Browse the repository at this point in the history
* testing with simple.ts

* what we want it to look like

* working

* passes tests

* docs: document new feature

* correctly call using req/res instead of metadata

* fix typing
  • Loading branch information
lukealvoeiro committed Nov 9, 2023
1 parent b4933e7 commit 19ba6a5
Show file tree
Hide file tree
Showing 13 changed files with 828 additions and 1 deletion.
4 changes: 4 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,10 @@ Generated code will be placed in the Gradle build directory.

- With `--ts_proto_opt=outputServices=false`, or `=none`, ts-proto will output NO service definitions.

- With `--ts_proto_opt=outputBeforeRequest=true`, ts-proto will add a function definition to the Rpc interface definition with the signature: `beforeRequest(request: <RequestType>)`. It will will also automatically set `outputTypeRegistry=true` and `outputServices=true`. Each of the Service's methods will call `beforeRequest` before performing it's request.

- With `--ts_proto_opt=outputAfterResponse=true`, ts-proto will add a function definition to the Rpc interface definition with the signature: `afterResponse(response: <ResponseType>)`. It will will also automatically set `outputTypeRegistry=true` and `outputServices=true`. Each of the Service's methods will call `afterResponse` before returning the response.

- With `--ts_proto_opt=useAbortSignal=true`, the generated services will accept an `AbortSignal` to cancel RPC calls.

- With `--ts_proto_opt=useAsyncIterable=true`, the generated services will use `AsyncIterable` instead of `Observable`.
Expand Down
47 changes: 47 additions & 0 deletions integration/before-after-request/before-after-request-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { FooServiceClientImpl, FooServiceCreateRequest, FooServiceCreateResponse } from "./simple";
import { MessageType } from "./typeRegistry";

interface Rpc {
request(service: string, method: string, data: Uint8Array): Promise<Uint8Array>;
beforeRequest?<T extends { [k in keyof T]: unknown }>(request: T): void;
afterResponse?<T extends { [k in keyof T]: unknown }>(response: T): void;
}

describe("before-after-request", () => {
const exampleData = {
kind: 1,
};
let rpc = {
request: jest.fn(() => Promise.resolve(new Uint8Array())),
};
let client = new FooServiceClientImpl(rpc);
const beforeRequest = jest.fn();
const afterResponse = jest.fn();

beforeEach(() => {
jest.clearAllMocks();
jest.spyOn(FooServiceCreateResponse, "decode").mockReturnValue(exampleData);
});

it("performs function before request if specified", async () => {
const req = FooServiceCreateRequest.create(exampleData);
client = new FooServiceClientImpl({ ...rpc, beforeRequest: beforeRequest });
await client.Create(req);
expect(beforeRequest).toHaveBeenCalledWith(req);
});

it("performs function after request if specified", async () => {
const req = FooServiceCreateRequest.create(exampleData);
client = new FooServiceClientImpl({ ...rpc, afterResponse: afterResponse });
await client.Create(req);
expect(afterResponse).toHaveBeenCalledWith(exampleData);
});

it("doesn't perform function before or after request if they are not specified", async () => {
const req = FooServiceCreateRequest.create(exampleData);
client = new FooServiceClientImpl({ ...rpc });
await client.Create(req);
expect(beforeRequest).not.toHaveBeenCalled();
expect(afterResponse).not.toHaveBeenCalled();
});
});
1 change: 1 addition & 0 deletions integration/before-after-request/parameters.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
outputBeforeRequest=true,outputAfterResponse=true
Binary file added integration/before-after-request/simple.bin
Binary file not shown.
37 changes: 37 additions & 0 deletions integration/before-after-request/simple.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
syntax = "proto3";
package simple;
import "simple2.proto";

enum SimpleEnum {
LOCAL_DEFAULT = 0;
LOCAL_FOO = 1;
LOCAL_BAR = 2;
}

message Simple {
string name = 1;
simple2.Simple otherSimple = 2;
}

message DifferentSimple {
string name = 1;
optional simple2.Simple otherOptionalSimple2 = 2;
}

message SimpleEnums {
SimpleEnum local_enum = 1;
simple2.SimpleEnum import_enum = 2;
}

message FooServiceCreateRequest {
simple2.FooService kind = 1;
}

message FooServiceCreateResponse {
simple2.FooService kind = 1;
}

service FooService {
rpc Create (FooServiceCreateRequest) returns (FooServiceCreateResponse);
}

Loading

0 comments on commit 19ba6a5

Please sign in to comment.