Skip to content

Commit

Permalink
feat: adding generic types for server/client
Browse files Browse the repository at this point in the history
  • Loading branch information
Sampaio Leal committed Jan 21, 2024
1 parent ef05345 commit 5f7757d
Show file tree
Hide file tree
Showing 11 changed files with 124 additions and 21 deletions.
12 changes: 7 additions & 5 deletions client.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { parseMessage, sendMessage } from "./messages.ts";
import { RPCClientOptions, RPCReply, RPCService } from "./types.ts";

export async function initializeClient(
export async function initializeClient<
Contracts extends Record<string, RPCService>,
>(
options: RPCClientOptions,
): Promise<Record<string, RPCService>> {
): Promise<Contracts> {
const ws = new WebSocket(options.host);
const call = (service: string, ...args: unknown[]) => {
const call = (service: string, ...args: never[]) => {
return new Promise<RPCReply>((resolve) => {
const controller = new AbortController();
const messageId = crypto.randomUUID();
Expand All @@ -27,7 +29,7 @@ export async function initializeClient(
});
};
const callService = (service: string) => {
return (...args: unknown[]) => {
return (...args: never[]) => {
return call(service, ...args);
};
};
Expand All @@ -51,5 +53,5 @@ export async function initializeClient(
};
});

return proxy;
return proxy as Contracts;
}
80 changes: 79 additions & 1 deletion deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions examples/contracts/service1.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { RPCReply } from "../../mod.ts";

type ServiceContracts = {
hello: (clientName: string) => Promise<RPCReply<void>>;
};

export default ServiceContracts;
7 changes: 7 additions & 0 deletions examples/contracts/service2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { RPCReply } from "../../mod.ts";

type ServiceContracts = {
hello: (clientName: string) => Promise<RPCReply<void>>;
};

export default ServiceContracts;
7 changes: 7 additions & 0 deletions examples/contracts/service3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { RPCReply } from "../../mod.ts";

type ServiceContracts = {
hello: (clientName: string) => Promise<RPCReply<void>>;
};

export default ServiceContracts;
6 changes: 4 additions & 2 deletions examples/service-1/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { initializeClient, initializeServer } from "../../mod.ts";
import Service2Contracts from "../contracts/service2.ts";
import Service3Contracts from "../contracts/service3.ts";

/**
* Services
Expand All @@ -20,11 +22,11 @@ initializeServer({
services,
});

const service2 = await initializeClient({
const service2 = await initializeClient<Service2Contracts>({
host: "ws://localhost:3002",
});

const service3 = await initializeClient({
const service3 = await initializeClient<Service3Contracts>({
host: "ws://localhost:3003",
});

Expand Down
7 changes: 4 additions & 3 deletions examples/service-2/main.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { initializeClient, initializeServer } from "../../mod.ts";

import Service1Contracts from "../contracts/service1.ts";
import Service3Contracts from "../contracts/service3.ts";
/**
* Services
*/
Expand All @@ -20,11 +21,11 @@ initializeServer({
services,
});

const service1 = await initializeClient({
const service1 = await initializeClient<Service1Contracts>({
host: "ws://localhost:3001",
});

const service3 = await initializeClient({
const service3 = await initializeClient<Service3Contracts>({
host: "ws://localhost:3003",
});

Expand Down
6 changes: 4 additions & 2 deletions examples/service-3/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { initializeClient, initializeServer } from "../../mod.ts";
import Service1Contracts from "../contracts/service1.ts";
import Service2Contracts from "../contracts/service2.ts";

/**
* Services
Expand All @@ -20,11 +22,11 @@ initializeServer({
services,
});

const service1 = await initializeClient({
const service1 = await initializeClient<Service1Contracts>({
host: "ws://localhost:3001",
});

const service2 = await initializeClient({
const service2 = await initializeClient<Service2Contracts>({
host: "ws://localhost:3002",
});

Expand Down
4 changes: 1 addition & 3 deletions messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,5 @@ export function sendMessage(socket: WebSocket, message: RPCMessage | RPCReply) {
}

export function parseMessage(message: string) {
return JSON.parse(
message,
) as RPCMessage | RPCReply;
return JSON.parse(message) as RPCMessage | RPCReply;
}
1 change: 0 additions & 1 deletion server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export function initializeServer(options: RPCServerOptions) {
const { socket, response } = Deno.upgradeWebSocket(req);

socket.addEventListener("message", async (event) => {
// TODO: handle parse errors
const message = parseMessage(event.data) as RPCMessage;
const service = options.services.get(message.service);

Expand Down
8 changes: 4 additions & 4 deletions types.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
export interface RPCMessage {
id: string;
service: string;
args: unknown[];
args: never[];
}

export interface RPCReply {
export interface RPCReply<T = unknown> {
id: string;
ok: boolean;
payload: unknown;
payload: T;
}

export type RPCService = <T extends RPCReply>(...args: unknown[]) => Promise<T>;
export type RPCService = (...args: never[]) => Promise<RPCReply>;

export interface RPCServerOptions extends Deno.ServeOptions {
port: number;
Expand Down

0 comments on commit 5f7757d

Please sign in to comment.