devframe 0.8.0 → 0.8.2
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/adapters/build.d.mts +1 -1
- package/dist/adapters/build.mjs +2 -2
- package/dist/adapters/cac.d.mts +1 -1
- package/dist/adapters/cac.mjs +1 -1
- package/dist/adapters/cli.d.mts +1 -1
- package/dist/adapters/cli.mjs +1 -1
- package/dist/adapters/dev.d.mts +15 -2
- package/dist/adapters/dev.mjs +1 -1
- package/dist/adapters/embedded.d.mts +1 -1
- package/dist/adapters/mcp.d.mts +11 -5
- package/dist/adapters/mcp.mjs +1 -1
- package/dist/{cac-B-R_tDGJ.mjs → cac-D4_9ok0z.mjs} +1 -1
- package/dist/cli/main.mjs +4 -3
- package/dist/client/index.d.mts +37 -8
- package/dist/client/index.mjs +41 -15
- package/dist/constants.d.mts +13 -6
- package/dist/constants.mjs +13 -6
- package/dist/{context-C9Cgm1hP.mjs → context-CBg8iRbQ.mjs} +3 -2
- package/dist/{context-7BbaIUSI.d.mts → context-DoSozfvx.d.mts} +1 -1
- package/dist/{revoke-BtQDKTp7.mjs → crypto-token-XCqTSMg9.mjs} +1 -35
- package/dist/{dev-D4M7Veo7.mjs → dev-Bc49u3qg.mjs} +7 -5
- package/dist/{devframe-Dsjn_Xtq.d.mts → devframe-mQ4qZAuo.d.mts} +10 -1
- package/dist/{diagnostics-B5-qHeqD.mjs → diagnostics-D7wM2cwM.mjs} +4 -0
- package/dist/{fetch-BZyK4v6W.mjs → fetch-BKaD0Vb3.mjs} +7 -6
- package/dist/helpers/vite.d.mts +15 -14
- package/dist/helpers/vite.mjs +8 -8
- package/dist/{host-h3-Kz7t5Xab.mjs → host-h3-D2hYZvDK.mjs} +2 -2
- package/dist/{http-BghOqfTD.mjs → http-C4T68YV6.mjs} +1 -1
- package/dist/{index-CeBbry0R.d.mts → index-b64Uuhy2.d.mts} +11 -6
- package/dist/index.d.mts +2 -2
- package/dist/{instance-registry-D6fxYu36.mjs → instance-registry-BnnA2Eoh.mjs} +1 -1
- package/dist/node/auth.d.mts +2 -2
- package/dist/node/auth.mjs +2 -2
- package/dist/node/hub-internals.d.mts +2 -2
- package/dist/node/hub-internals.mjs +1 -1
- package/dist/node/index.d.mts +23 -3
- package/dist/node/index.mjs +5 -5
- package/dist/recipes/common-rpc-functions.d.mts +1 -1
- package/dist/recipes/interactive-auth.d.mts +2 -2
- package/dist/recipes/interactive-auth.mjs +11 -3
- package/dist/revoke-DZbJ7Cl0.mjs +35 -0
- package/dist/rpc/transports/ws-server.d.mts +2 -2
- package/dist/rpc/transports/ws-server.mjs +75 -7
- package/dist/{server-CcAPxuoT.mjs → server-CD8XmBXl.mjs} +25 -6
- package/dist/{server-VLQJouOO.d.mts → server-UHWae43Q.d.mts} +21 -3
- package/dist/{state-WX3HT5a3.mjs → state-BeUHDDjk.mjs} +13 -6
- package/dist/{storage-Dzoc3NVC.mjs → storage-CTNVbuFB.mjs} +1 -1
- package/dist/types/index.d.mts +2 -2
- package/dist/utils/events.d.mts +1 -1
- package/dist/utils/shared-state.d.mts +1 -1
- package/dist/utils/streaming-channel.d.mts +1 -1
- package/dist/{ws-server-D_Vjtums.d.mts → ws-server-uKQcClcJ.d.mts} +36 -7
- package/package.json +2 -2
- package/skills/devframe/SKILL.md +3 -2
|
@@ -4,6 +4,7 @@ import { BirpcGroup, ChannelOptions } from "birpc";
|
|
|
4
4
|
import { NodeAdapter } from "crossws/adapters/node";
|
|
5
5
|
import { Server } from "node:http";
|
|
6
6
|
import { Server as Server$1, ServerOptions } from "node:https";
|
|
7
|
+
import { AddressInfo } from "node:net";
|
|
7
8
|
//#region src/rpc/transports/ws-server.d.ts
|
|
8
9
|
interface DevframeNodeRpcSessionMeta {
|
|
9
10
|
id: number;
|
|
@@ -34,9 +35,12 @@ interface WsRpcTransportOptions {
|
|
|
34
35
|
* this transport detaches the upgrade listener without closing the server.
|
|
35
36
|
*/
|
|
36
37
|
server?: Server | Server$1;
|
|
37
|
-
/**
|
|
38
|
+
/**
|
|
39
|
+
* Port for the standalone WebSocket server. Defaults to `0`, which lets the
|
|
40
|
+
* operating system assign an available port.
|
|
41
|
+
*/
|
|
38
42
|
port?: number;
|
|
39
|
-
/** Host for
|
|
43
|
+
/** Host for the standalone WebSocket server. Defaults to `localhost`. */
|
|
40
44
|
host?: string;
|
|
41
45
|
/**
|
|
42
46
|
* Restrict the WS endpoint to a single upgrade route (e.g. `/__devframe_ws`). When
|
|
@@ -62,7 +66,7 @@ interface WsRpcTransportOptions {
|
|
|
62
66
|
* Pass `false` to disable origin checking entirely (not recommended).
|
|
63
67
|
* Default: loopback-only.
|
|
64
68
|
*/
|
|
65
|
-
allowedOrigins?: readonly string[] | false;
|
|
69
|
+
allowedOrigins?: readonly string[] | WsOriginRegistry | false;
|
|
66
70
|
/**
|
|
67
71
|
* RPC function definitions, used by the per-call wire serializer to
|
|
68
72
|
* dispatch between strict-JSON and structured-clone encoding based
|
|
@@ -79,12 +83,37 @@ interface WsRpcTransportOptions {
|
|
|
79
83
|
/** Override the default per-call deserializer. Most callers should leave this unset. */
|
|
80
84
|
deserialize?: ChannelOptions['deserialize'];
|
|
81
85
|
}
|
|
86
|
+
interface CreateWsOriginRegistryOptions {
|
|
87
|
+
/** Origins allowed before any external viewers are registered. */
|
|
88
|
+
allowedOrigins?: readonly string[];
|
|
89
|
+
/** Additional validation to run after the registration token is verified. */
|
|
90
|
+
validateOrigin?: (origin: string) => boolean;
|
|
91
|
+
}
|
|
92
|
+
interface WsOriginRegistry {
|
|
93
|
+
/** Registration token to include in connection metadata. */
|
|
94
|
+
readonly token: string;
|
|
95
|
+
/** Read and register an origin from a connection bootstrap URL. */
|
|
96
|
+
registerFromUrl: (url: string) => string | undefined;
|
|
97
|
+
/** Check whether an origin is currently allowed. */
|
|
98
|
+
isAllowed: (origin: string | undefined) => boolean;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Create a live, token-protected origin allowlist for external browser
|
|
102
|
+
* viewers. Pass it to {@link WsRpcTransportOptions.allowedOrigins}, then use
|
|
103
|
+
* `registerFromUrl()` in the connection metadata handler to authorize a
|
|
104
|
+
* viewer without sharing a mutable array or disabling DNS-rebinding protection.
|
|
105
|
+
*/
|
|
106
|
+
declare function createWsOriginRegistry(options?: CreateWsOriginRegistryOptions): WsOriginRegistry;
|
|
82
107
|
interface WsRpcTransport {
|
|
83
108
|
/**
|
|
84
109
|
* The crossws node adapter driving the socket — exposes the connected
|
|
85
110
|
* `peers` and pub/sub. See https://crossws.h3.dev.
|
|
86
111
|
*/
|
|
87
112
|
ws: NodeAdapter;
|
|
113
|
+
/** Resolves when the transport-owned server is listening. */
|
|
114
|
+
ready: Promise<void>;
|
|
115
|
+
/** Returns the bound address, or `null` when the server is not listening. */
|
|
116
|
+
address: () => AddressInfo | string | null;
|
|
88
117
|
/** Remove the upgrade listener from a shared `server` (a no-op otherwise). */
|
|
89
118
|
detach: () => void;
|
|
90
119
|
/**
|
|
@@ -109,10 +138,10 @@ declare function isAllowedOrigin(origin: string | undefined, allowedOrigins: rea
|
|
|
109
138
|
* `server` (sharing its port, optionally scoped to a `path`), or let this
|
|
110
139
|
* helper create a standalone server from `port` / `host` / `https`.
|
|
111
140
|
*
|
|
112
|
-
* Returns the crossws node adapter
|
|
113
|
-
* listener from a shared `server`)
|
|
114
|
-
* teardown).
|
|
141
|
+
* Returns the crossws node adapter, standalone-server readiness/address
|
|
142
|
+
* accessors, `detach` (remove the upgrade listener from a shared `server`),
|
|
143
|
+
* and `close` (full deterministic teardown).
|
|
115
144
|
*/
|
|
116
145
|
declare function attachWsRpcTransport<ClientFunctions extends object, ServerFunctions extends object>(rpcGroup: BirpcGroup<ClientFunctions, ServerFunctions, false>, options?: WsRpcTransportOptions): WsRpcTransport;
|
|
117
146
|
//#endregion
|
|
118
|
-
export {
|
|
147
|
+
export { WsRpcTransportOptions as a, isAllowedOrigin as c, WsRpcTransport as i, isLoopbackHostname as l, DevframeNodeRpcSessionMeta as n, attachWsRpcTransport as o, WsOriginRegistry as r, createWsOriginRegistry as s, CreateWsOriginRegistryOptions as t };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "devframe",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.8.
|
|
4
|
+
"version": "0.8.2",
|
|
5
5
|
"description": "Framework for building generic devframes",
|
|
6
6
|
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -115,7 +115,7 @@
|
|
|
115
115
|
"ua-parser-modern": "^0.1.1",
|
|
116
116
|
"valibot": "^1.4.2",
|
|
117
117
|
"whenexpr": "^0.1.2",
|
|
118
|
-
"ws": "^8.21.
|
|
118
|
+
"ws": "^8.21.2"
|
|
119
119
|
},
|
|
120
120
|
"scripts": {
|
|
121
121
|
"build": "tsdown",
|
package/skills/devframe/SKILL.md
CHANGED
|
@@ -569,10 +569,11 @@ RPC handlers run with the full privileges of the host process, so the boundary t
|
|
|
569
569
|
- **`auth` defaults to `true`** — dev-mode connections must authenticate before calls are accepted. Devframe ships the node primitives (`exchangeTempAuthCode`, `verifyAuthToken` in `devframe/node/auth`); the host adapter (e.g. Vite DevTools) provides the interactive `devframe:anonymous:auth` + `devframe:auth:exchange` handlers and auth UI.
|
|
570
570
|
- **`auth: false` trusts every reachable connection.** Use it only for single-user `localhost` tools. Never combine it with a non-loopback bind host, a tunnel, or a shared/CI environment. The default bind host is already `localhost`.
|
|
571
571
|
- **Authentication** exchanges a 6-digit one-time code (shown in the developer's terminal) for a node-issued bearer token via `requestTrustWithCode(code)`. The code is single-use, expires in 5 min, compared in constant time, and rotates after repeated failures — show it only in the terminal, never over the network.
|
|
572
|
-
- **Magic-link (optional):** print `buildOtpAuthUrl(origin)` — `<origin
|
|
572
|
+
- **Magic-link (optional):** print `buildOtpAuthUrl(origin)` — `<origin>/#devframe_otp=<code>`. The code rides the URL **fragment**, which the browser never sends to the server, so it stays out of access logs and `Referer`. `connectDevframe` reads the code, exchanges it, and strips it from the URL. Integrations can opt out (`otpParam: false`) and drive it via the exposed `authenticateWithUrlOtp(rpc)` / `consumeOtpFromUrl()` client utilities. Only the single-use code rides the URL, never the bearer; treat the printed link like the code itself. The standalone CLI's `--open` does this automatically via `DevframeAuthHandler.buildOpenUrl` — the launched tab already carries the OTP, no prompt needed.
|
|
573
573
|
- **Tokens are secrets.** The bearer token rides the WS URL (`?devframe_auth_token=…`) — serve over `wss://`/`https://` beyond loopback. Never log the token or code, never bake them into build output. Revoke via `revokeAuthToken(...)`; clients drop to untrusted on `devframe:auth:revoked`.
|
|
574
574
|
- **Authorize handlers.** Any trusted client can call any registered function — validate inputs, and mark state-changing functions `type: 'destructive'` so MCP/agent clients prompt first.
|
|
575
|
-
- **Origin-lock remote docks** (`originLock
|
|
575
|
+
- **Origin-lock remote docks** (`originLock`, on by default) so a dock's session token is honored only on a connection whose `Origin` matches the dock — the connect-time gate enforces it.
|
|
576
|
+
- **The MCP route requires an Origin.** The route-based MCP server (`cli.mcp`, `viteDevBridge`/Next handler `mcp`, `createMcpFetchHandler`) rejects `Origin`-less requests — a request must carry a loopback (or allow-listed) `Origin`, so it isn't reachable by an arbitrary local process. `devframe connect` sends each instance's own loopback origin automatically.
|
|
576
577
|
|
|
577
578
|
See [Security](https://devfra.me/security) for the full reference.
|
|
578
579
|
|