@canmi/seam-adapter-hono 0.4.4 → 0.4.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +14 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +32 -2
- package/dist/index.js.map +1 -1
- package/package.json +8 -7
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,26 @@
|
|
|
1
|
-
import { DefinitionMap, HttpHandler, Router, RpcHashMap } from "@canmi/seam-server";
|
|
1
|
+
import { ChannelWsOptions, DefinitionMap, HttpHandler, Router, RpcHashMap } from "@canmi/seam-server";
|
|
2
2
|
import { MiddlewareHandler } from "hono";
|
|
3
3
|
|
|
4
4
|
//#region src/index.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Hono-compatible upgradeWebSocket factory.
|
|
7
|
+
* Runtimes (Deno, Bun, Cloudflare) provide their own implementation;
|
|
8
|
+
* the user injects it via options so the adapter stays runtime-agnostic.
|
|
9
|
+
*/
|
|
10
|
+
type UpgradeWebSocket = (handler: (c: any) => {
|
|
11
|
+
onOpen?: (evt: any, ws: any) => void;
|
|
12
|
+
onMessage?: (evt: any, ws: any) => void;
|
|
13
|
+
onClose?: (evt: any, ws: any) => void;
|
|
14
|
+
}) => MiddlewareHandler;
|
|
5
15
|
interface SeamHonoOptions {
|
|
6
16
|
staticDir?: string;
|
|
7
17
|
fallback?: HttpHandler;
|
|
8
18
|
rpcHashMap?: RpcHashMap;
|
|
19
|
+
upgradeWebSocket?: UpgradeWebSocket;
|
|
20
|
+
wsOptions?: ChannelWsOptions;
|
|
9
21
|
}
|
|
10
22
|
/** Hono middleware that handles all /_seam/* routes via the seam router */
|
|
11
23
|
declare function seam<T extends DefinitionMap>(router: Router<T>, opts?: SeamHonoOptions): MiddlewareHandler;
|
|
12
24
|
//#endregion
|
|
13
|
-
export { SeamHonoOptions, seam };
|
|
25
|
+
export { SeamHonoOptions, UpgradeWebSocket, seam };
|
|
14
26
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;AAqBA;;;KAAY,gBAAA,IACV,OAAA,GAAU,CAAA;EACR,MAAA,IAAU,GAAA,OAAU,EAAA;EACpB,SAAA,IAAa,GAAA,OAAU,EAAA;EACvB,OAAA,IAAW,GAAA,OAAU,EAAA;AAAA,MAEpB,iBAAA;AAAA,UAIY,eAAA;EACf,SAAA;EACA,QAAA,GAAW,WAAA;EACX,UAAA,GAAa,UAAA;EACb,gBAAA,GAAmB,gBAAA;EACnB,SAAA,GAAY,gBAAA;AAAA;;iBAWE,IAAA,WAAe,aAAA,CAAA,CAC7B,MAAA,EAAQ,MAAA,CAAO,CAAA,GACf,IAAA,GAAO,eAAA,GACN,iBAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import { createHttpHandler, toWebResponse } from "@canmi/seam-server";
|
|
1
|
+
import { createHttpHandler, startChannelWs, toWebResponse } from "@canmi/seam-server";
|
|
2
2
|
|
|
3
3
|
//#region src/index.ts
|
|
4
4
|
const SEAM_PREFIX = "/_seam/";
|
|
5
|
+
const PROCEDURE_PREFIX = "/_seam/procedure/";
|
|
6
|
+
const EVENTS_SUFFIX = ".events";
|
|
7
|
+
const wsSessions = /* @__PURE__ */ new WeakMap();
|
|
5
8
|
/** Hono middleware that handles all /_seam/* routes via the seam router */
|
|
6
9
|
function seam(router, opts) {
|
|
7
10
|
const handlerOpts = {};
|
|
@@ -10,7 +13,34 @@ function seam(router, opts) {
|
|
|
10
13
|
if (opts?.rpcHashMap) handlerOpts.rpcHashMap = opts.rpcHashMap;
|
|
11
14
|
const handler = createHttpHandler(router, handlerOpts);
|
|
12
15
|
return async (c, next) => {
|
|
13
|
-
|
|
16
|
+
const url = new URL(c.req.url);
|
|
17
|
+
if (!url.pathname.startsWith(SEAM_PREFIX)) return next();
|
|
18
|
+
if (opts?.upgradeWebSocket && c.req.header("upgrade") === "websocket" && url.pathname.startsWith(PROCEDURE_PREFIX) && url.pathname.endsWith(EVENTS_SUFFIX)) {
|
|
19
|
+
const channelName = url.pathname.slice(17, -7);
|
|
20
|
+
const rawInput = url.searchParams.get("input");
|
|
21
|
+
let channelInput;
|
|
22
|
+
try {
|
|
23
|
+
channelInput = rawInput ? JSON.parse(rawInput) : {};
|
|
24
|
+
} catch {
|
|
25
|
+
return c.text("Invalid input query parameter", 400);
|
|
26
|
+
}
|
|
27
|
+
return opts.upgradeWebSocket(() => ({
|
|
28
|
+
onOpen(_evt, ws) {
|
|
29
|
+
const wsObj = ws;
|
|
30
|
+
const session = startChannelWs(router, channelName, channelInput, { send: (data) => ws.send(data) }, opts.wsOptions);
|
|
31
|
+
wsSessions.set(wsObj, session);
|
|
32
|
+
},
|
|
33
|
+
onMessage(evt, ws) {
|
|
34
|
+
const session = wsSessions.get(ws);
|
|
35
|
+
const text = typeof evt.data === "string" ? evt.data : String(evt.data);
|
|
36
|
+
session?.onMessage(text);
|
|
37
|
+
},
|
|
38
|
+
onClose(_evt, ws) {
|
|
39
|
+
wsSessions.get(ws)?.close();
|
|
40
|
+
wsSessions.delete(ws);
|
|
41
|
+
}
|
|
42
|
+
}))(c, next);
|
|
43
|
+
}
|
|
14
44
|
const raw = c.req.raw;
|
|
15
45
|
return toWebResponse(await handler({
|
|
16
46
|
method: raw.method,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/*
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/* src/server/adapter/hono/src/index.ts */\n\nimport { createHttpHandler, toWebResponse, startChannelWs } from \"@canmi/seam-server\";\nimport type {\n DefinitionMap,\n Router,\n HttpHandler,\n HttpHandlerOptions,\n RpcHashMap,\n ChannelWsOptions,\n ChannelWsSession,\n} from \"@canmi/seam-server\";\nimport type { MiddlewareHandler } from \"hono\";\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/**\n * Hono-compatible upgradeWebSocket factory.\n * Runtimes (Deno, Bun, Cloudflare) provide their own implementation;\n * the user injects it via options so the adapter stays runtime-agnostic.\n */\nexport type UpgradeWebSocket = (\n handler: (c: any) => {\n onOpen?: (evt: any, ws: any) => void;\n onMessage?: (evt: any, ws: any) => void;\n onClose?: (evt: any, ws: any) => void;\n },\n) => MiddlewareHandler;\n\n/* eslint-enable @typescript-eslint/no-explicit-any */\n\nexport interface SeamHonoOptions {\n staticDir?: string;\n fallback?: HttpHandler;\n rpcHashMap?: RpcHashMap;\n upgradeWebSocket?: UpgradeWebSocket;\n wsOptions?: ChannelWsOptions;\n}\n\nconst SEAM_PREFIX = \"/_seam/\";\nconst PROCEDURE_PREFIX = \"/_seam/procedure/\";\nconst EVENTS_SUFFIX = \".events\";\n\n// Track WS sessions without patching the ws object\nconst wsSessions = new WeakMap<object, ChannelWsSession>();\n\n/** Hono middleware that handles all /_seam/* routes via the seam router */\nexport function seam<T extends DefinitionMap>(\n router: Router<T>,\n opts?: SeamHonoOptions,\n): MiddlewareHandler {\n const handlerOpts: HttpHandlerOptions = {};\n if (opts?.staticDir) handlerOpts.staticDir = opts.staticDir;\n if (opts?.fallback) handlerOpts.fallback = opts.fallback;\n if (opts?.rpcHashMap) handlerOpts.rpcHashMap = opts.rpcHashMap;\n\n const handler = createHttpHandler(router, handlerOpts);\n\n return async (c, next) => {\n const url = new URL(c.req.url);\n\n if (!url.pathname.startsWith(SEAM_PREFIX)) {\n return next();\n }\n\n // WebSocket upgrade for channel paths\n if (\n opts?.upgradeWebSocket &&\n c.req.header(\"upgrade\") === \"websocket\" &&\n url.pathname.startsWith(PROCEDURE_PREFIX) &&\n url.pathname.endsWith(EVENTS_SUFFIX)\n ) {\n const channelName = url.pathname.slice(PROCEDURE_PREFIX.length, -EVENTS_SUFFIX.length);\n const rawInput = url.searchParams.get(\"input\");\n let channelInput: unknown;\n try {\n channelInput = rawInput ? JSON.parse(rawInput) : {};\n } catch {\n return c.text(\"Invalid input query parameter\", 400);\n }\n\n const wsHandler = opts.upgradeWebSocket(() => ({\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onOpen(_evt: any, ws: any) {\n const wsObj = ws as object;\n const session = startChannelWs(\n router,\n channelName,\n channelInput,\n { send: (data: string) => (ws as { send: (d: string) => void }).send(data) },\n opts.wsOptions,\n );\n wsSessions.set(wsObj, session);\n },\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onMessage(evt: any, ws: any) {\n const session = wsSessions.get(ws as object);\n const text =\n typeof (evt as { data: unknown }).data === \"string\"\n ? (evt as { data: string }).data\n : String((evt as { data: unknown }).data);\n session?.onMessage(text);\n },\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onClose(_evt: any, ws: any) {\n const session = wsSessions.get(ws as object);\n session?.close();\n wsSessions.delete(ws as object);\n },\n }));\n return wsHandler(c, next);\n }\n\n const raw = c.req.raw;\n const result = await handler({\n method: raw.method,\n url: raw.url,\n body: () => raw.json(),\n header: (name) => raw.headers.get(name),\n });\n\n return toWebResponse(result);\n };\n}\n"],"mappings":";;;AAuCA,MAAM,cAAc;AACpB,MAAM,mBAAmB;AACzB,MAAM,gBAAgB;AAGtB,MAAM,6BAAa,IAAI,SAAmC;;AAG1D,SAAgB,KACd,QACA,MACmB;CACnB,MAAM,cAAkC,EAAE;AAC1C,KAAI,MAAM,UAAW,aAAY,YAAY,KAAK;AAClD,KAAI,MAAM,SAAU,aAAY,WAAW,KAAK;AAChD,KAAI,MAAM,WAAY,aAAY,aAAa,KAAK;CAEpD,MAAM,UAAU,kBAAkB,QAAQ,YAAY;AAEtD,QAAO,OAAO,GAAG,SAAS;EACxB,MAAM,MAAM,IAAI,IAAI,EAAE,IAAI,IAAI;AAE9B,MAAI,CAAC,IAAI,SAAS,WAAW,YAAY,CACvC,QAAO,MAAM;AAIf,MACE,MAAM,oBACN,EAAE,IAAI,OAAO,UAAU,KAAK,eAC5B,IAAI,SAAS,WAAW,iBAAiB,IACzC,IAAI,SAAS,SAAS,cAAc,EACpC;GACA,MAAM,cAAc,IAAI,SAAS,MAAM,IAAyB,GAAsB;GACtF,MAAM,WAAW,IAAI,aAAa,IAAI,QAAQ;GAC9C,IAAI;AACJ,OAAI;AACF,mBAAe,WAAW,KAAK,MAAM,SAAS,GAAG,EAAE;WAC7C;AACN,WAAO,EAAE,KAAK,iCAAiC,IAAI;;AAgCrD,UA7BkB,KAAK,wBAAwB;IAE7C,OAAO,MAAW,IAAS;KACzB,MAAM,QAAQ;KACd,MAAM,UAAU,eACd,QACA,aACA,cACA,EAAE,OAAO,SAAkB,GAAqC,KAAK,KAAK,EAAE,EAC5E,KAAK,UACN;AACD,gBAAW,IAAI,OAAO,QAAQ;;IAGhC,UAAU,KAAU,IAAS;KAC3B,MAAM,UAAU,WAAW,IAAI,GAAa;KAC5C,MAAM,OACJ,OAAQ,IAA0B,SAAS,WACtC,IAAyB,OAC1B,OAAQ,IAA0B,KAAK;AAC7C,cAAS,UAAU,KAAK;;IAG1B,QAAQ,MAAW,IAAS;AAE1B,KADgB,WAAW,IAAI,GAAa,EACnC,OAAO;AAChB,gBAAW,OAAO,GAAa;;IAElC,EAAE,CACc,GAAG,KAAK;;EAG3B,MAAM,MAAM,EAAE,IAAI;AAQlB,SAAO,cAPQ,MAAM,QAAQ;GAC3B,QAAQ,IAAI;GACZ,KAAK,IAAI;GACT,YAAY,IAAI,MAAM;GACtB,SAAS,SAAS,IAAI,QAAQ,IAAI,KAAK;GACxC,CAAC,CAE0B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canmi/seam-adapter-hono",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.11",
|
|
4
|
+
"license": "MIT",
|
|
4
5
|
"files": [
|
|
5
6
|
"dist"
|
|
6
7
|
],
|
|
@@ -16,14 +17,14 @@
|
|
|
16
17
|
"test": "vitest run"
|
|
17
18
|
},
|
|
18
19
|
"devDependencies": {
|
|
19
|
-
"@canmi/seam-server": "0.4.
|
|
20
|
-
"hono": "^4.
|
|
21
|
-
"tsdown": "^0.20.
|
|
22
|
-
"typescript": "^5.
|
|
23
|
-
"vitest": "^
|
|
20
|
+
"@canmi/seam-server": "0.4.11",
|
|
21
|
+
"hono": "^4.12.3",
|
|
22
|
+
"tsdown": "^0.20.3",
|
|
23
|
+
"typescript": "^5.9.3",
|
|
24
|
+
"vitest": "^4.0.18"
|
|
24
25
|
},
|
|
25
26
|
"peerDependencies": {
|
|
26
|
-
"@canmi/seam-server": "0.4.
|
|
27
|
+
"@canmi/seam-server": "0.4.11",
|
|
27
28
|
"hono": "^4.0.0"
|
|
28
29
|
}
|
|
29
30
|
}
|