Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/prohazko2/deno-grpc

Very basic gRPC implementation for Deno
https://github.com/prohazko2/deno-grpc

deno grpc

Last synced: about 2 months ago
JSON representation

Very basic gRPC implementation for Deno

Awesome Lists containing this project

README

        

# `/x/grpc_basic`

- [latest](https://deno.land/x/grpc_basic)

⚠️ You probably should wait for more mature and standard aligned implementation beacuse:
1. This lib doesn't use Deno's 1.9 HTTP/2 native bindings, but relies on JS implementation roughly ported from [node-http2](https://github.com/molnarg/node-http2)
2. I'm not an expert in gRPC or HTTP/2, I just moved HTTP/2 frames around until it worked
3. It was never meant for production use, only for fun and some integration tests and scripts
4. I have no plans on implementing full gRPC spec

### goals - keep it simple

- [x] load proto files
- [x] `server` unary calls
- [x] `client` unary calls
- [x] multiplex calls
- [x] `server` server streams
- [x] `client` server streams
- [ ] auto reconnects (without retries)
- [ ] deadlines/cancellation with AbortController/AbortSignal
- [ ] call metadata
- [ ] logging interface

### non goals - gRPC bloat

- [x] no TLS
- [x] no client streams
- [x] no bidirectional streams
- [x] no client side load balancing

## hello world

### `greeter.proto`

```proto
syntax = "proto3";

package helloworld;

service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
rpc ShoutHello (HelloRequest) returns (stream HelloReply) {}
}

message HelloRequest {
string name = 1;
}

message HelloReply {
string message = 1;
}
```

### `greeter.d.ts`

Service typings are not essential, but it's nice to have them

```sh
$ deno run --allow-read https://deno.land/x/[email protected]/gen/dts.ts ./greeter.proto > ./greeter.d.ts
```

```ts
export interface Greeter {
SayHello(request: HelloRequest): Promise;
ShoutHello(request: HelloRequest): AsyncGenerator;
}

export interface HelloRequest {
name?: string;
}

export interface HelloReply {
message?: string;
}
```

### `server.ts`

```ts
import { GrpcServer } from "https://deno.land/x/[email protected]/server.ts";
import { Greeter } from "./greeter.d.ts";

const port = 50051;
const server = new GrpcServer();

const protoPath = new URL("./greeter.proto", import.meta.url);
const protoFile = await Deno.readTextFile(protoPath);

server.addService(protoFile, {

async SayHello({ name }) {
const message = `hello ${name || "stranger"}`;
return { message };
},

async *ShoutHello({ name }) {
for (const n of [0, 1, 2]) {
const message = `hello ${name || "stranger"} #${n}`;
yield { message };
}
}
});

console.log(`gonna listen on ${port} port`);
for await (const conn of Deno.listen({ port })) {
server.handle(conn);
}

```

### `client.ts`

```ts
import { getClient } from "https://deno.land/x/[email protected]/client.ts";
import { Greeter } from "./greeter.d.ts";

const protoPath = new URL("./greeter.proto", import.meta.url);
const protoFile = await Deno.readTextFile(protoPath);

const client = getClient({
port: 50051,
root: protoFile,
serviceName: "Greeter",
});

/* unary calls */
console.log(await client.SayHello({ name: "unary #1" }));
console.log(await client.SayHello({ name: "unary #2" }));

/* server stream */
for await (const reply of client.ShoutHello({ name: "streamed" })) {
console.log(reply);
}

client.close();
```