Skip to content

Commit

Permalink
feat: dynamic resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 committed Feb 24, 2024
1 parent 1ef0585 commit cb6721c
Show file tree
Hide file tree
Showing 17 changed files with 145 additions and 134 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,13 @@
],
"scripts": {
"build": "unbuild",
"dev": "pnpm play:node",
"lint": "eslint --cache --ext .ts,.js,.mjs,.cjs . && prettier -c src",
"lint:fix": "eslint --cache --ext .ts,.js,.mjs,.cjs . --fix && prettier -c src -w",
"prepack": "pnpm run build",
"play:bun": "bun playground/bun.ts",
"play:cf": "wrangler dev --port 3001",
"play:deno": "deno run -A playground/deno.ts",
"play:deno": "deno run --unstable-sloppy-imports -A playground/deno.ts",
"play:node": "jiti playground/node.ts",
"play:uws": "jiti playground/uws.ts",
"release": "pnpm test && changelogen --release && npm publish && git push --follow-tags",
Expand Down
56 changes: 0 additions & 56 deletions playground/_common.ts

This file was deleted.

59 changes: 59 additions & 0 deletions playground/_shared.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import {
CrossWSOptions,
WebSocketAdapter,
defineWebSocketHooks,
} from "../src/index.ts";

export const getIndexHTML = (params) =>
import("../examples/h3/index.html.ts").then((r) => r.html(params));

export function createDemo<T extends WebSocketAdapter>(
adapter: T,
opts?: Parameters<T>[1],
): ReturnType<T> {
const hooks = defineWebSocketHooks({
$(name, peer, ...args) {
console.log(
`$ ${peer} ${name} (${args.map((arg) => stringify(arg)).join(", ")})`,
);
},
open(peer) {
peer.send(`Hello ${peer}`);
},
message(peer, message) {
if (message.text() === "ping") {
peer.send("pong");
}
},
});

const resolve: CrossWSOptions["resolve"] = (peer) => {
return {
open: () => {
peer.send(
JSON.stringify(
{
url: peer.url,
headers: peer.headers && Object.fromEntries(peer.headers),
},
undefined,
2,
),
);
},
};
};

return adapter(hooks, {
resolve,
...opts,
});
}

function stringify(val) {
const str = val.toString();
if (str === "[object Object]") {
return val.constructor?.name || "??";
}
return str;
}
2 changes: 1 addition & 1 deletion playground/bun.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// You can run this demo using `bun --bun ./bun.ts` or `npm run play:bun` in repo

import bunAdapter from "../src/adapters/bun";
import { createDemo, getIndexHTML } from "./_common";
import { createDemo, getIndexHTML } from "./_shared";

const adapter = createDemo(bunAdapter);

Expand Down
2 changes: 1 addition & 1 deletion playground/cloudflare.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// You can run this demo using `npm run play:cf` in repo
import type { Request, ExecutionContext } from "@cloudflare/workers-types";
import cloudflareAdapter from "../src/adapters/cloudflare";
import { createDemo, getIndexHTML } from "./_common.ts";
import { createDemo, getIndexHTML } from "./_shared.ts";

const { handleUpgrade } = createDemo(cloudflareAdapter);

Expand Down
4 changes: 2 additions & 2 deletions playground/deno.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// You can run this demo using `deno run -A ./deno.ts` or `npm run play:deno` in repo

import denoAdapter from "../dist/adapters/deno.mjs";
import denoAdapter from "../src/adapters/deno.ts";

// @ts-ignore
import type * as _Deno from "../types/lib.deno.d.ts";

import { createDemo, getIndexHTML } from "./_common.ts";
import { createDemo, getIndexHTML } from "./_shared.ts";

declare global {
const Deno: typeof import("@deno/types").Deno;
Expand Down
2 changes: 1 addition & 1 deletion playground/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { createServer } from "node:http";
import nodeAdapter from "../src/adapters/node";
import { createDemo, getIndexHTML } from "./_common";
import { createDemo, getIndexHTML } from "./_shared";

const adapter = createDemo(nodeAdapter);

Expand Down
4 changes: 2 additions & 2 deletions playground/uws.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// You can run this demo using `npm run play:node-uws` in repo

import { App } from "uWebSockets.js";
import uwsAdapter from "../src/adapters/uws.ts";
import { createDemo, getIndexHTML } from "./_common.ts";
import uwsAdapter from "../src/adapters/uws";
import { createDemo, getIndexHTML } from "./_shared.ts";

const adapter = createDemo(uwsAdapter);

Expand Down
6 changes: 3 additions & 3 deletions src/adapters/bun.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { WebSocketHandler, ServerWebSocket, Server } from "bun";

import { WebSocketMessage } from "../message";
import { WebSocketError } from "../error";
import { WebSocketPeerBase } from "../peer";
import { WebSocketPeer } from "../peer";
import { defineWebSocketAdapter } from "../adapter";
import { CrossWSOptions, createCrossWS } from "../crossws";

Expand All @@ -28,7 +28,7 @@ export default defineWebSocketAdapter<Adapter, AdapterOptions>(
if (ws.data?._peer) {
return ws.data._peer;
}
const peer = new WebSocketPeer({ bun: { ws } });
const peer = new BunPeer({ bun: { ws } });
ws.data = ws.data || {};
ws.data._peer = peer;
return peer;
Expand Down Expand Up @@ -79,7 +79,7 @@ export default defineWebSocketAdapter<Adapter, AdapterOptions>(
},
);

class WebSocketPeer extends WebSocketPeerBase<{
class BunPeer extends WebSocketPeer<{
bun: { ws: ServerWebSocket<ContextData> };
}> {
get id() {
Expand Down
8 changes: 4 additions & 4 deletions src/adapters/cloudflare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import type * as _cf from "@cloudflare/workers-types";

import { WebSocketPeerBase } from "../peer";
import { WebSocketPeer } from "../peer";
import { defineWebSocketAdapter } from "../adapter.js";
import { WebSocketMessage } from "../message";
import { WebSocketError } from "../error";
Expand Down Expand Up @@ -36,14 +36,14 @@ export default defineWebSocketAdapter<Adapter, AdapterOptions>(
const client = pair[0];
const server = pair[1];

const peer = new CloudflareWebSocketPeer({
const peer = new CloudflarePeer({
cloudflare: { client, server, req, env, context },
});

server.accept();

crossws.$("cloudflare:accept", peer);
hooks.open?.(peer);
crossws.open(peer);

server.addEventListener("message", (event) => {
crossws.$("cloudflare:message", peer, event);
Expand Down Expand Up @@ -73,7 +73,7 @@ export default defineWebSocketAdapter<Adapter, AdapterOptions>(
},
);

class CloudflareWebSocketPeer extends WebSocketPeerBase<{
class CloudflarePeer extends WebSocketPeer<{
cloudflare: {
client: _cf.WebSocket;
server: _cf.WebSocket;
Expand Down
8 changes: 4 additions & 4 deletions src/adapters/deno.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import { WebSocketMessage } from "../message";
import { WebSocketError } from "../error";
import { WebSocketPeerBase } from "../peer";
import { WebSocketPeer } from "../peer";
import { defineWebSocketAdapter } from "../adapter.js";
import { CrossWSOptions, createCrossWS } from "../crossws";

Expand All @@ -24,12 +24,12 @@ export default defineWebSocketAdapter<Adapter, AdapterOptions>(

const handleUpgrade = (req: Request) => {
const upgrade = Deno.upgradeWebSocket(req);
const peer = new DenoWebSocketPeer({
const peer = new DenoPeer({
deno: { ws: upgrade.socket, req },
});
upgrade.socket.addEventListener("open", () => {
crossws.$("deno:open", peer);
hooks.open?.(peer);
crossws.open(peer);
});
upgrade.socket.addEventListener("message", (event) => {
crossws.$("deno:message", peer, event);
Expand All @@ -52,7 +52,7 @@ export default defineWebSocketAdapter<Adapter, AdapterOptions>(
},
);

class DenoWebSocketPeer extends WebSocketPeerBase<{
class DenoPeer extends WebSocketPeer<{
deno: { ws: any; req: Request };
}> {
get id() {
Expand Down
33 changes: 17 additions & 16 deletions src/adapters/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type {
WebSocketServer,
WebSocket as WebSocketT,
} from "../../types/ws";
import { WebSocketPeerBase } from "../peer";
import { WebSocketPeer } from "../peer";
import { WebSocketMessage } from "../message";
import { WebSocketError } from "../error";
import { defineWebSocketAdapter } from "../adapter";
Expand All @@ -37,22 +37,23 @@ export default defineWebSocketAdapter<Adapter, AdapterOptions>(
}) as WebSocketServer);

// Unmanaged server-level events
wss.on("error", (error) => {
crossws.$("node:server-error", error);
});
wss.on("headers", (headers, request) => {
crossws.$("node:server-headers", headers, request);
});
wss.on("listening", () => {
crossws.$("node:server-listening");
});
wss.on("close", () => {
crossws.$("node:server-close");
});
// TODO: Expose with new API
// wss.on("error", (error) => {
// crossws.$("node:server-error", error);
// });
// wss.on("headers", (headers, request) => {
// crossws.$("node:server-headers", headers, request);
// });
// wss.on("listening", () => {
// crossws.$("node:server-listening");
// });
// wss.on("close", () => {
// crossws.$("node:server-close");
// });

wss.on("connection", (ws, req) => {
const peer = new NodeWebSocketPeer({ node: { ws, req, server: wss } });
hooks.open?.(peer);
const peer = new NodePeer({ node: { ws, req, server: wss } });
crossws.open(peer);

// Managed socket-level events
ws.on("message", (data: RawData, isBinary: boolean) => {
Expand Down Expand Up @@ -105,7 +106,7 @@ export default defineWebSocketAdapter<Adapter, AdapterOptions>(
},
);

class NodeWebSocketPeer extends WebSocketPeerBase<{
class NodePeer extends WebSocketPeer<{
node: {
server: WebSocketServer;
req: IncomingMessage;
Expand Down
15 changes: 9 additions & 6 deletions src/adapters/uws.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type {
HttpRequest,
HttpResponse,
} from "uWebSockets.js";
import { WebSocketPeerBase } from "../peer";
import { WebSocketPeer } from "../peer";
import { WebSocketMessage } from "../message";
import { defineWebSocketAdapter } from "../adapter";
import { CrossWSOptions, createCrossWS } from "../crossws";
Expand Down Expand Up @@ -48,7 +48,7 @@ export default defineWebSocketAdapter<Adapter, AdapterOptions>(
if (userData._peer) {
return userData._peer as WebSocketPeer;
}
const peer = new WebSocketPeer({ uws: { ws, userData } });
const peer = new UWSPeer({ uws: { ws, userData } });
userData._peer = peer;
return peer;
};
Expand All @@ -73,7 +73,7 @@ export default defineWebSocketAdapter<Adapter, AdapterOptions>(
open(ws) {
const peer = getPeer(ws);
crossws.$("uws:open", peer, ws);
hooks.open?.(peer);
crossws.open(peer);
},
ping(ws, message) {
const peer = getPeer(ws);
Expand Down Expand Up @@ -110,18 +110,21 @@ export default defineWebSocketAdapter<Adapter, AdapterOptions>(
},
);

class WebSocketPeer extends WebSocketPeerBase<{
class UWSPeer extends WebSocketPeer<{
uws: {
ws: WebSocket<UserData>;
userData: UserData;
};
}> {
_headers: Headers | undefined;
_decoder = new TextDecoder();

get id() {
try {
const addr = this.ctx.uws.ws?.getRemoteAddressAsText();
return new TextDecoder().decode(addr);
const addr = this._decoder.decode(
this.ctx.uws.ws?.getRemoteAddressAsText(),
);
return addr.replace(/(0000:)+/, "");
} catch {
// Error: Invalid access of closed uWS.WebSocket/SSLWebSocket.
}
Expand Down
Loading

0 comments on commit cb6721c

Please sign in to comment.