Skip to content

Commit 08458c0

Browse files
committed
Support binding gRPC services that are defined as object literals.
This commit allows binding gRPC services directly, in the following way: const greeter = { greet: (req) => TestResponse.create({ greeting: `Hello` }) };
1 parent bee23ae commit 08458c0

File tree

2 files changed

+54
-8
lines changed

2 files changed

+54
-8
lines changed

src/server/base_restate_server.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,22 @@ export abstract class BaseRestateServer {
221221
}
222222
}
223223

224+
/* eslint-disable @typescript-eslint/no-explicit-any */
225+
function indexProperties(instance: any): Map<string, string> {
226+
const names = new Map<string, string>();
227+
while (
228+
instance !== null &&
229+
instance !== undefined &&
230+
instance !== Object.prototype
231+
) {
232+
for (const property of Object.getOwnPropertyNames(instance)) {
233+
names.set(property.toLowerCase(), property);
234+
}
235+
instance = Object.getPrototypeOf(instance);
236+
}
237+
return names;
238+
}
239+
224240
// Given:
225241
// * an instance of a class that implements a gRPC TypeScript interface,
226242
// as generated by our protoc plugin, this method
@@ -263,14 +279,7 @@ export function parseService(
263279

264280
// index all the existing properties that `instance` has.
265281
// we index them by the lower case represention.
266-
const prototype = Object.getPrototypeOf(instance);
267-
const names = new Map<string, string>(
268-
Object.getOwnPropertyNames(prototype).map((name) => [
269-
name.toLowerCase(),
270-
name,
271-
])
272-
);
273-
282+
const names = indexProperties(instance);
274283
for (const serviceDescriptor of meta.fileDescriptor.service) {
275284
if (serviceName !== serviceDescriptor.name) {
276285
continue;

test/service_bind.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright (c) 2023 - Restate Software, Inc., Restate GmbH
3+
*
4+
* This file is part of the Restate SDK for Node.js/TypeScript,
5+
* which is released under the MIT license.
6+
*
7+
* You can find a copy of the license in file LICENSE in the root
8+
* directory of this repository or package, or at
9+
* https://github.com/restatedev/sdk-typescript/blob/main/LICENSE
10+
*/
11+
12+
import {
13+
TestGreeter,
14+
TestRequest,
15+
TestResponse,
16+
} from "../src/generated/proto/test";
17+
import * as restate from "../src/public_api";
18+
import { describe } from "@jest/globals";
19+
import { TestDriver } from "./testdriver";
20+
import { greetRequest, inputMessage, startMessage } from "./protoutils";
21+
22+
const greeter: TestGreeter = {
23+
/* eslint-disable @typescript-eslint/no-unused-vars */
24+
greet: async (req: TestRequest): Promise<TestResponse> => {
25+
restate.useContext(this);
26+
return TestResponse.create({ greeting: `Hello` });
27+
},
28+
};
29+
30+
describe("BindService", () => {
31+
it("should bind object literals", async () => {
32+
await new TestDriver(greeter, [
33+
startMessage(1),
34+
inputMessage(greetRequest("Pete")),
35+
]).run();
36+
});
37+
});

0 commit comments

Comments
 (0)