devframe 0.5.4 → 0.6.0-beta.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/{_shared-CUFqO4kJ.mjs → _shared-bWRzeSa0.mjs} +2 -3
- package/dist/adapters/build.d.mts +1 -1
- package/dist/adapters/build.mjs +7 -7
- package/dist/adapters/cli.d.mts +1 -1
- package/dist/adapters/cli.mjs +2 -2
- package/dist/adapters/dev.d.mts +8 -2
- package/dist/adapters/dev.mjs +1 -1
- package/dist/adapters/embedded.d.mts +1 -1
- package/dist/adapters/mcp.d.mts +1 -1
- package/dist/adapters/mcp.mjs +4 -4
- package/dist/client/index.d.mts +148 -6
- package/dist/client/index.mjs +257 -44
- package/dist/constants.d.mts +17 -1
- package/dist/constants.mjs +17 -1
- package/dist/context-3x_bgBgZ.mjs +48 -0
- package/dist/{context-DTRcO_UH.d.mts → context-BEVByy_Z.d.mts} +1 -1
- package/dist/{dev-Cv43GfqM.mjs → dev-BaX8fLH2.mjs} +39 -13
- package/dist/{devframe-BuR6n9ZD.d.mts → devframe-D-gr9sBx.d.mts} +365 -15
- package/dist/{diagnostics-GitRGKbr.mjs → diagnostics-BXwBQmoN.mjs} +1 -1
- package/dist/{dump-9lKIJTLh.mjs → dump-DoXkj4ku.mjs} +1 -1
- package/dist/helpers/vite.d.mts +1 -1
- package/dist/helpers/vite.mjs +11 -11
- package/dist/{host-h3-Dgpgr1Ul.mjs → host-h3-C5SZlk03.mjs} +134 -6
- package/dist/{index-C7M1hnvL.d.mts → index-CxaPKDXX.d.mts} +2 -2
- package/dist/{index-DH2sBIwd.d.mts → index-DXHWuwJk.d.mts} +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +1 -1
- package/dist/{launch-editor-BbNhtg7b.mjs → launch-editor-DPfltGA4.mjs} +88 -13
- package/dist/node/auth.d.mts +43 -23
- package/dist/node/auth.mjs +84 -37
- package/dist/node/hub-internals.d.mts +2 -2
- package/dist/node/hub-internals.mjs +2 -2
- package/dist/node/index.d.mts +22 -6
- package/dist/node/index.mjs +4 -4
- package/dist/recipes/open-helpers.d.mts +1 -1
- package/dist/recipes/open-helpers.mjs +3 -3
- package/dist/revoke-ENfxWkFK.mjs +79 -0
- package/dist/rpc/dump.d.mts +1 -1
- package/dist/rpc/dump.mjs +1 -1
- package/dist/rpc/index.d.mts +3 -3
- package/dist/rpc/index.mjs +4 -4
- package/dist/rpc/transports/ws-client.d.mts +1 -1
- package/dist/rpc/transports/ws-client.mjs +2 -2
- package/dist/rpc/transports/ws-server.d.mts +2 -2
- package/dist/rpc/transports/ws-server.mjs +154 -61
- package/dist/{serialization-BD_qXGjd.mjs → serialization-DpLXCy13.mjs} +1 -1
- package/dist/{server-BBaBJaUL.mjs → server-Dl6TU5LE.mjs} +19 -14
- package/dist/server-rX781kz-.d.mts +90 -0
- package/dist/{shared-state-u0y123fi.mjs → shared-state-D4PPieA0.mjs} +4 -4
- package/dist/{shared-state-BlBNYziY.mjs → storage-l2ezeend.mjs} +128 -6
- package/dist/types/index.d.mts +4 -4
- package/dist/{types-BkkQ0Txg.d.mts → types-DZEx4ffs.d.mts} +9 -1
- package/dist/utils/crypto-token.d.mts +24 -0
- package/dist/utils/crypto-token.mjs +45 -0
- package/dist/utils/events.d.mts +1 -1
- package/dist/utils/hash.mjs +1 -1
- package/dist/utils/launch-editor.mjs +1 -1
- package/dist/utils/open.mjs +1 -1
- package/dist/utils/scope.d.mts +11 -0
- package/dist/utils/scope.mjs +15 -0
- package/dist/utils/shared-state.d.mts +1 -1
- package/dist/utils/shared-state.mjs +1 -1
- package/dist/utils/streaming-channel.d.mts +1 -1
- package/dist/utils/structured-clone.mjs +1 -1
- package/dist/{ws-client-CVYX9niP.d.mts → ws-client-D0z0pOhn.d.mts} +1 -1
- package/dist/ws-server-Bc2wBHl-.d.mts +119 -0
- package/package.json +12 -7
- package/skills/devframe/SKILL.md +123 -23
- package/skills/devframe/templates/counter-devframe.ts +14 -4
- package/skills/devframe/templates/spa-devframe.ts +13 -3
- package/skills/devframe/templates/vite-client.ts +3 -2
- package/dist/context-DaKmhhHY.mjs +0 -164
- package/dist/revoke-CL0LSAN9.mjs +0 -803
- package/dist/server-wHlpcdZ9.d.mts +0 -55
- package/dist/utils/human-id.d.mts +0 -8
- package/dist/utils/human-id.mjs +0 -769
- package/dist/ws-server-C1LjmRnp.d.mts +0 -61
- /package/dist/{define-CW9gLnyG.mjs → define-BLWPsH6y.mjs} +0 -0
- /package/dist/{diagnostics-reporter-CBBZwoMv.mjs → diagnostics-reporter-CsIG85Q5.mjs} +0 -0
- /package/dist/{hash-bwOD8RgU.mjs → hash-DFc5WwhO.mjs} +0 -0
- /package/dist/{open-DiQn6zCH.mjs → open-Dusa2Zzd.mjs} +0 -0
- /package/dist/{structured-clone-PdCZwt7F.mjs → structured-clone-CeZOHvkd.mjs} +0 -0
- /package/dist/{structured-clone-jegjz0hM.mjs → structured-clone-XpHLZ8nr.mjs} +0 -0
- /package/dist/{transports-DTFoMUbE.mjs → transports-BmDVn4SF.mjs} +0 -0
package/dist/node/index.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { S as RpcFunctionsCollectorBase } from "../index-
|
|
4
|
-
import { t as DevframeNodeRpcSessionMeta } from "../ws-server-
|
|
5
|
-
import { n as StartedServer, r as startHttpAndWs, t as StartHttpAndWsOptions } from "../server-
|
|
1
|
+
import { G as DevframeScopedNodeContext, J as DevframeSettings, L as SharedState, S as RpcStreamingHost, _ as RpcFunctionsHost$1, _t as AgentToolInput, bt as EventEmitter, dt as AgentHandle, ft as AgentManifest, g as RpcBroadcastOptions, gt as AgentTool, h as DevframeNodeRpcSession, ht as AgentResourceInput, it as DevframeRpcServerFunctions, lt as DevframeDiagnosticsHost$1, m as DevframeNodeContext, mt as AgentResourceContent, nt as DevframeViewHost$1, ot as DevframeHost, pt as AgentResource, rt as DevframeRpcClientFunctions, ut as DevframeDiagnosticsLogger, vt as DevframeAgentHost$1, y as RpcSharedStateHost, yt as DevframeAgentHostEvents } from "../devframe-D-gr9sBx.mjs";
|
|
2
|
+
import { v as RpcFunctionDefinitionAny } from "../types-DZEx4ffs.mjs";
|
|
3
|
+
import { S as RpcFunctionsCollectorBase } from "../index-CxaPKDXX.mjs";
|
|
4
|
+
import { t as DevframeNodeRpcSessionMeta } from "../ws-server-Bc2wBHl-.mjs";
|
|
5
|
+
import { n as StartedServer, r as startHttpAndWs, t as StartHttpAndWsOptions } from "../server-rX781kz-.mjs";
|
|
6
6
|
import { BirpcGroup } from "birpc";
|
|
7
7
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
8
8
|
|
|
@@ -156,6 +156,22 @@ declare function createRpcSharedStateServerHost(rpc: RpcFunctionsHost$1): RpcSha
|
|
|
156
156
|
*/
|
|
157
157
|
declare function createRpcStreamingServerHost(rpc: RpcFunctionsHost$1): RpcStreamingHost;
|
|
158
158
|
//#endregion
|
|
159
|
+
//#region src/node/scope.d.ts
|
|
160
|
+
/**
|
|
161
|
+
* Build a namespace-scoped view of a {@link DevframeNodeContext}. Every
|
|
162
|
+
* RPC id, shared-state key, and streaming channel passed through the
|
|
163
|
+
* returned `rpc` surface is auto-namespaced with `<namespace>:`.
|
|
164
|
+
*/
|
|
165
|
+
declare function createScopedNodeContext<NS extends string = string>(context: DevframeNodeContext, namespace: NS): DevframeScopedNodeContext<NS>;
|
|
166
|
+
//#endregion
|
|
167
|
+
//#region src/node/settings.d.ts
|
|
168
|
+
/**
|
|
169
|
+
* Build the node-side `settings` surface for a scope namespace. `project`
|
|
170
|
+
* persists under the host's `workspace` storage dir, `global` under its
|
|
171
|
+
* `global` dir. Each is a file-backed, client-synced key-value store.
|
|
172
|
+
*/
|
|
173
|
+
declare function createNodeSettings<T extends Record<string, any> = Record<string, any>>(context: DevframeNodeContext, namespace: string): DevframeSettings<T>;
|
|
174
|
+
//#endregion
|
|
159
175
|
//#region src/node/storage.d.ts
|
|
160
176
|
interface CreateStorageOptions<T extends object> {
|
|
161
177
|
filepath: string;
|
|
@@ -169,4 +185,4 @@ declare function createStorage<T extends object>(options: CreateStorageOptions<T
|
|
|
169
185
|
declare function isObject(value: unknown): value is Record<string, any>;
|
|
170
186
|
declare function normalizeHttpServerUrl(host: string, port: number | string): string;
|
|
171
187
|
//#endregion
|
|
172
|
-
export { CreateH3DevframeHostOptions, CreateHostContextOptions, CreateStorageOptions, DevframeAgentHost, DevframeDiagnosticsHost, DevframeViewHost, RpcFunctionsHost, StartHttpAndWsOptions, StartedServer, createH3DevframeHost, createHostContext, createRpcSharedStateServerHost, createRpcStreamingServerHost, createStorage, isObject, normalizeHttpServerUrl, startHttpAndWs };
|
|
188
|
+
export { CreateH3DevframeHostOptions, CreateHostContextOptions, CreateStorageOptions, DevframeAgentHost, DevframeDiagnosticsHost, DevframeViewHost, RpcFunctionsHost, StartHttpAndWsOptions, StartedServer, createH3DevframeHost, createHostContext, createNodeSettings, createRpcSharedStateServerHost, createRpcStreamingServerHost, createScopedNodeContext, createStorage, isObject, normalizeHttpServerUrl, startHttpAndWs };
|
package/dist/node/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { r as
|
|
3
|
-
import { t as startHttpAndWs } from "../server-
|
|
1
|
+
import { t as createStorage } from "../storage-l2ezeend.mjs";
|
|
2
|
+
import { a as DevframeViewHost, c as createRpcSharedStateServerHost, i as createNodeSettings, l as DevframeDiagnosticsHost, n as createHostContext, o as RpcFunctionsHost, r as createScopedNodeContext, s as createRpcStreamingServerHost, t as createH3DevframeHost, u as DevframeAgentHost } from "../host-h3-C5SZlk03.mjs";
|
|
3
|
+
import { t as startHttpAndWs } from "../server-Dl6TU5LE.mjs";
|
|
4
4
|
import { isIP } from "node:net";
|
|
5
5
|
//#region src/node/utils.ts
|
|
6
6
|
function isObject(value) {
|
|
@@ -10,4 +10,4 @@ function normalizeHttpServerUrl(host, port) {
|
|
|
10
10
|
return `http://${host === "127.0.0.1" ? "localhost" : isIP(host) === 6 ? `[${host}]` : host}:${port}`;
|
|
11
11
|
}
|
|
12
12
|
//#endregion
|
|
13
|
-
export { DevframeAgentHost, DevframeDiagnosticsHost, DevframeViewHost, RpcFunctionsHost, createH3DevframeHost, createHostContext, createRpcSharedStateServerHost, createRpcStreamingServerHost, createStorage, isObject, normalizeHttpServerUrl, startHttpAndWs };
|
|
13
|
+
export { DevframeAgentHost, DevframeDiagnosticsHost, DevframeViewHost, RpcFunctionsHost, createH3DevframeHost, createHostContext, createNodeSettings, createRpcSharedStateServerHost, createRpcStreamingServerHost, createScopedNodeContext, createStorage, isObject, normalizeHttpServerUrl, startHttpAndWs };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { E as Thenable, S as RpcFunctionSetupResult, c as RpcDump, g as RpcFunctionAgentOptions } from "../types-DZEx4ffs.mjs";
|
|
2
2
|
import * as v from "valibot";
|
|
3
3
|
|
|
4
4
|
//#region src/recipes/open-helpers.d.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as launchEditor } from "../launch-editor-
|
|
2
|
-
import { n as defineRpcFunction } from "../define-
|
|
3
|
-
import { t as open } from "../open-
|
|
1
|
+
import { t as launchEditor } from "../launch-editor-DPfltGA4.mjs";
|
|
2
|
+
import { n as defineRpcFunction } from "../define-BLWPsH6y.mjs";
|
|
3
|
+
import { t as open } from "../open-Dusa2Zzd.mjs";
|
|
4
4
|
import * as v from "valibot";
|
|
5
5
|
//#region src/recipes/open-helpers.ts
|
|
6
6
|
/**
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
//#region src/utils/crypto-token.ts
|
|
2
|
+
const HEX = "0123456789abcdef";
|
|
3
|
+
/**
|
|
4
|
+
* Generate a high-entropy, URL-safe (hex) random token suitable for use as a
|
|
5
|
+
* bearer credential — e.g. the persistent client auth token or an ephemeral
|
|
6
|
+
* remote-dock token. Defaults to 16 bytes (128 bits) of entropy.
|
|
7
|
+
*/
|
|
8
|
+
function randomToken(byteLength = 16) {
|
|
9
|
+
const bytes = new Uint8Array(byteLength);
|
|
10
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
11
|
+
let out = "";
|
|
12
|
+
for (let i = 0; i < bytes.length; i++) out += HEX[bytes[i] >> 4] + HEX[bytes[i] & 15];
|
|
13
|
+
return out;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Generate a uniformly-distributed string of decimal digits using rejection
|
|
17
|
+
* sampling to avoid modulo bias. Intended for short, human-typed one-time
|
|
18
|
+
* codes (e.g. a 6-digit authentication code). Leading zeros are preserved.
|
|
19
|
+
*/
|
|
20
|
+
function randomDigits(length) {
|
|
21
|
+
const limit = 250;
|
|
22
|
+
const buf = new Uint8Array(1);
|
|
23
|
+
let out = "";
|
|
24
|
+
while (out.length < length) {
|
|
25
|
+
globalThis.crypto.getRandomValues(buf);
|
|
26
|
+
if (buf[0] < limit) out += String(buf[0] % 10);
|
|
27
|
+
}
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Constant-time string equality. Compares every character so the comparison
|
|
32
|
+
* time does not depend on the position of the first mismatch, mitigating
|
|
33
|
+
* timing side-channels when verifying secrets.
|
|
34
|
+
*
|
|
35
|
+
* Length is treated as public (it short-circuits on differing lengths), which
|
|
36
|
+
* is appropriate for fixed-length codes and tokens.
|
|
37
|
+
*/
|
|
38
|
+
function timingSafeEqual(a, b) {
|
|
39
|
+
if (a.length !== b.length) return false;
|
|
40
|
+
let mismatch = 0;
|
|
41
|
+
for (let i = 0; i < a.length; i++) mismatch |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
42
|
+
return mismatch === 0;
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/node/auth/revoke.ts
|
|
46
|
+
/**
|
|
47
|
+
* Flip `isTrusted` to false on any live WS clients connected with `token`
|
|
48
|
+
* and broadcast the `auth:revoked` event so they can react.
|
|
49
|
+
*
|
|
50
|
+
* Shared between persisted-auth revocation and remote-dock token revocation.
|
|
51
|
+
*/
|
|
52
|
+
async function revokeActiveConnectionsForToken(context, token) {
|
|
53
|
+
const rpcHost = context.rpc;
|
|
54
|
+
if (!rpcHost?._rpcGroup) return;
|
|
55
|
+
const affectedSessionIds = /* @__PURE__ */ new Set();
|
|
56
|
+
for (const client of rpcHost._rpcGroup.clients) if (client.$meta.clientAuthToken === token) {
|
|
57
|
+
affectedSessionIds.add(client.$meta.id);
|
|
58
|
+
client.$meta.isTrusted = false;
|
|
59
|
+
client.$meta.clientAuthToken = void 0;
|
|
60
|
+
}
|
|
61
|
+
if (affectedSessionIds.size === 0) return;
|
|
62
|
+
await rpcHost.broadcast({
|
|
63
|
+
method: "devframe:auth:revoked",
|
|
64
|
+
args: [],
|
|
65
|
+
filter: (client) => affectedSessionIds.has(client.$meta.id)
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Revoke an auth token: remove from storage and notify all connected clients
|
|
70
|
+
* using this token that they are no longer trusted.
|
|
71
|
+
*/
|
|
72
|
+
async function revokeAuthToken(context, storage, token) {
|
|
73
|
+
storage.mutate((state) => {
|
|
74
|
+
delete state.trusted[token];
|
|
75
|
+
});
|
|
76
|
+
await revokeActiveConnectionsForToken(context, token);
|
|
77
|
+
}
|
|
78
|
+
//#endregion
|
|
79
|
+
export { timingSafeEqual as a, randomToken as i, revokeAuthToken as n, randomDigits as r, revokeActiveConnectionsForToken as t };
|
package/dist/rpc/dump.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as getDefinitionsWithDumps, c as StaticRpcDumpManifest, d as StaticRpcDumpManifestValue, f as StaticRpcDumpSerialization, i as dumpFunctions, l as StaticRpcDumpManifestQueryEntry, n as serializeDumpError, o as StaticRpcDumpCollection, p as collectStaticRpcDump, r as createClientFromDump, s as StaticRpcDumpFile, t as reviveDumpError, u as StaticRpcDumpManifestStaticEntry } from "../index-
|
|
1
|
+
import { a as getDefinitionsWithDumps, c as StaticRpcDumpManifest, d as StaticRpcDumpManifestValue, f as StaticRpcDumpSerialization, i as dumpFunctions, l as StaticRpcDumpManifestQueryEntry, n as serializeDumpError, o as StaticRpcDumpCollection, p as collectStaticRpcDump, r as createClientFromDump, s as StaticRpcDumpFile, t as reviveDumpError, u as StaticRpcDumpManifestStaticEntry } from "../index-DXHWuwJk.mjs";
|
|
2
2
|
export { StaticRpcDumpCollection, StaticRpcDumpFile, StaticRpcDumpManifest, StaticRpcDumpManifestQueryEntry, StaticRpcDumpManifestStaticEntry, StaticRpcDumpManifestValue, StaticRpcDumpSerialization, collectStaticRpcDump, createClientFromDump, dumpFunctions, getDefinitionsWithDumps, reviveDumpError, serializeDumpError };
|
package/dist/rpc/dump.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as dumpFunctions, c as serializeDumpError, i as createClientFromDump, o as getDefinitionsWithDumps, s as reviveDumpError, t as collectStaticRpcDump } from "../dump-
|
|
1
|
+
import { a as dumpFunctions, c as serializeDumpError, i as createClientFromDump, o as getDefinitionsWithDumps, s as reviveDumpError, t as collectStaticRpcDump } from "../dump-DoXkj4ku.mjs";
|
|
2
2
|
export { collectStaticRpcDump, createClientFromDump, dumpFunctions, getDefinitionsWithDumps, reviveDumpError, serializeDumpError };
|
package/dist/rpc/index.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { C as
|
|
2
|
-
import { C as RpcCacheManager, S as RpcFunctionsCollectorBase, _ as strictJsonStringify, a as StaticRpcDumpManifestStaticEntry, b as createDefineWrapperWithContext, c as collectStaticRpcDump, d as getDefinitionsWithDumps, f as reviveDumpError, g as STRUCTURED_CLONE_PREFIX, h as validateDefinitions, i as StaticRpcDumpManifestQueryEntry, l as createClientFromDump, m as validateDefinition, n as StaticRpcDumpFile, o as StaticRpcDumpManifestValue, p as serializeDumpError, r as StaticRpcDumpManifest, s as StaticRpcDumpSerialization, t as StaticRpcDumpCollection, u as dumpFunctions, v as getRpcHandler, w as RpcCacheOptions, x as defineRpcFunction, y as getRpcResolvedSetupResult } from "../index-
|
|
3
|
-
export { BirpcFn, BirpcReturn, EntriesToObject, RpcArgsSchema, RpcCacheManager, RpcCacheOptions, RpcDefinitionsFilter, RpcDefinitionsToFunctions, RpcDump, RpcDumpClientOptions, RpcDumpCollectionOptions, RpcDumpDefinition, RpcDumpGetter, RpcDumpRecord, RpcDumpRecordError, RpcDumpStore, RpcFunctionAgentOptions, RpcFunctionDefinition, RpcFunctionDefinitionAny, RpcFunctionDefinitionAnyWithContext, RpcFunctionDefinitionBase, RpcFunctionDefinitionToFunction, RpcFunctionSetupResult, RpcFunctionType, RpcFunctionsCollector, RpcFunctionsCollectorBase, RpcReturnSchema, STRUCTURED_CLONE_PREFIX, StaticRpcDumpCollection, StaticRpcDumpFile, StaticRpcDumpManifest, StaticRpcDumpManifestQueryEntry, StaticRpcDumpManifestStaticEntry, StaticRpcDumpManifestValue, StaticRpcDumpSerialization, Thenable, collectStaticRpcDump, createClientFromDump, createDefineWrapperWithContext, defineRpcFunction, dumpFunctions, getDefinitionsWithDumps, getRpcHandler, getRpcResolvedSetupResult, reviveDumpError, serializeDumpError, strictJsonStringify, validateDefinition, validateDefinitions };
|
|
1
|
+
import { C as RpcFunctionType, E as Thenable, S as RpcFunctionSetupResult, T as RpcReturnSchema, _ as RpcFunctionDefinition, a as RpcDefinitionsFilter, b as RpcFunctionDefinitionBase, c as RpcDump, d as RpcDumpDefinition, f as RpcDumpGetter, g as RpcFunctionAgentOptions, h as RpcDumpStore, i as RpcArgsSchema, l as RpcDumpClientOptions, m as RpcDumpRecordError, n as BirpcReturn, o as RpcDefinitionsToFunctions, p as RpcDumpRecord, r as EntriesToObject, s as RpcDefinitionsToFunctionsWithNamespace, t as BirpcFn, u as RpcDumpCollectionOptions, v as RpcFunctionDefinitionAny, w as RpcFunctionsCollector, x as RpcFunctionDefinitionToFunction, y as RpcFunctionDefinitionAnyWithContext } from "../types-DZEx4ffs.mjs";
|
|
2
|
+
import { C as RpcCacheManager, S as RpcFunctionsCollectorBase, _ as strictJsonStringify, a as StaticRpcDumpManifestStaticEntry, b as createDefineWrapperWithContext, c as collectStaticRpcDump, d as getDefinitionsWithDumps, f as reviveDumpError, g as STRUCTURED_CLONE_PREFIX, h as validateDefinitions, i as StaticRpcDumpManifestQueryEntry, l as createClientFromDump, m as validateDefinition, n as StaticRpcDumpFile, o as StaticRpcDumpManifestValue, p as serializeDumpError, r as StaticRpcDumpManifest, s as StaticRpcDumpSerialization, t as StaticRpcDumpCollection, u as dumpFunctions, v as getRpcHandler, w as RpcCacheOptions, x as defineRpcFunction, y as getRpcResolvedSetupResult } from "../index-CxaPKDXX.mjs";
|
|
3
|
+
export { BirpcFn, BirpcReturn, EntriesToObject, RpcArgsSchema, RpcCacheManager, RpcCacheOptions, RpcDefinitionsFilter, RpcDefinitionsToFunctions, RpcDefinitionsToFunctionsWithNamespace, RpcDump, RpcDumpClientOptions, RpcDumpCollectionOptions, RpcDumpDefinition, RpcDumpGetter, RpcDumpRecord, RpcDumpRecordError, RpcDumpStore, RpcFunctionAgentOptions, RpcFunctionDefinition, RpcFunctionDefinitionAny, RpcFunctionDefinitionAnyWithContext, RpcFunctionDefinitionBase, RpcFunctionDefinitionToFunction, RpcFunctionSetupResult, RpcFunctionType, RpcFunctionsCollector, RpcFunctionsCollectorBase, RpcReturnSchema, STRUCTURED_CLONE_PREFIX, StaticRpcDumpCollection, StaticRpcDumpFile, StaticRpcDumpManifest, StaticRpcDumpManifestQueryEntry, StaticRpcDumpManifestStaticEntry, StaticRpcDumpManifestValue, StaticRpcDumpSerialization, Thenable, collectStaticRpcDump, createClientFromDump, createDefineWrapperWithContext, defineRpcFunction, dumpFunctions, getDefinitionsWithDumps, getRpcHandler, getRpcResolvedSetupResult, reviveDumpError, serializeDumpError, strictJsonStringify, validateDefinition, validateDefinitions };
|
package/dist/rpc/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { a as dumpFunctions$1, c as serializeDumpError$1, d as hash, i as createClientFromDump$1, l as validateDefinition, n as getRpcHandler, o as getDefinitionsWithDumps$1, r as getRpcResolvedSetupResult, s as reviveDumpError$1, t as collectStaticRpcDump$1, u as validateDefinitions } from "../dump-
|
|
2
|
-
import { t as diagnostics } from "../diagnostics-
|
|
3
|
-
import { n as defineRpcFunction, t as createDefineWrapperWithContext } from "../define-
|
|
4
|
-
import { n as strictJsonStringify, t as STRUCTURED_CLONE_PREFIX } from "../serialization-
|
|
1
|
+
import { a as dumpFunctions$1, c as serializeDumpError$1, d as hash, i as createClientFromDump$1, l as validateDefinition, n as getRpcHandler, o as getDefinitionsWithDumps$1, r as getRpcResolvedSetupResult, s as reviveDumpError$1, t as collectStaticRpcDump$1, u as validateDefinitions } from "../dump-DoXkj4ku.mjs";
|
|
2
|
+
import { t as diagnostics } from "../diagnostics-BXwBQmoN.mjs";
|
|
3
|
+
import { n as defineRpcFunction, t as createDefineWrapperWithContext } from "../define-BLWPsH6y.mjs";
|
|
4
|
+
import { n as strictJsonStringify, t as STRUCTURED_CLONE_PREFIX } from "../serialization-DpLXCy13.mjs";
|
|
5
5
|
//#region src/rpc/cache.ts
|
|
6
6
|
/**
|
|
7
7
|
* @experimental API is expected to change.
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as createWsRpcChannel, t as WsRpcChannelOptions } from "../../ws-client-
|
|
1
|
+
import { n as createWsRpcChannel, t as WsRpcChannelOptions } from "../../ws-client-D0z0pOhn.mjs";
|
|
2
2
|
export { WsRpcChannelOptions, createWsRpcChannel };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as strictJsonStringify } from "../../serialization-
|
|
2
|
-
import { n as structuredCloneStringify, t as structuredCloneParse } from "../../structured-clone-
|
|
1
|
+
import { n as strictJsonStringify } from "../../serialization-DpLXCy13.mjs";
|
|
2
|
+
import { n as structuredCloneStringify, t as structuredCloneParse } from "../../structured-clone-XpHLZ8nr.mjs";
|
|
3
3
|
//#region src/rpc/transports/ws-client.ts
|
|
4
4
|
function NOOP() {}
|
|
5
5
|
const EMPTY_DEFS = /* @__PURE__ */ new Map();
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as
|
|
2
|
-
export { DevframeNodeRpcSessionMeta, WsRpcTransportOptions, attachWsRpcTransport };
|
|
1
|
+
import { a as isAllowedOrigin, i as attachWsRpcTransport, n as WsRpcTransport, o as isLoopbackHostname, r as WsRpcTransportOptions, t as DevframeNodeRpcSessionMeta } from "../../ws-server-Bc2wBHl-.mjs";
|
|
2
|
+
export { DevframeNodeRpcSessionMeta, WsRpcTransport, WsRpcTransportOptions, attachWsRpcTransport, isAllowedOrigin, isLoopbackHostname };
|
|
@@ -1,74 +1,167 @@
|
|
|
1
|
-
import { n as strictJsonStringify } from "../../serialization-
|
|
2
|
-
import { n as structuredCloneStringify, t as structuredCloneParse } from "../../structured-clone-
|
|
3
|
-
import { createServer } from "node:
|
|
4
|
-
import {
|
|
1
|
+
import { n as strictJsonStringify } from "../../serialization-DpLXCy13.mjs";
|
|
2
|
+
import { n as structuredCloneStringify, t as structuredCloneParse } from "../../structured-clone-XpHLZ8nr.mjs";
|
|
3
|
+
import { createServer } from "node:http";
|
|
4
|
+
import { createServer as createServer$1 } from "node:https";
|
|
5
|
+
import crossws from "crossws/adapters/node";
|
|
5
6
|
//#region src/rpc/transports/ws-server.ts
|
|
6
7
|
let sessionId = 0;
|
|
7
8
|
const EMPTY_DEFS = /* @__PURE__ */ new Map();
|
|
8
9
|
function NOOP() {}
|
|
10
|
+
/** Compare two URL paths ignoring a trailing slash. */
|
|
11
|
+
function pathMatches(a, b) {
|
|
12
|
+
const strip = (p) => p.length > 1 && p.endsWith("/") ? p.slice(0, -1) : p;
|
|
13
|
+
return strip(a) === strip(b);
|
|
14
|
+
}
|
|
15
|
+
function isLoopbackHostname(hostname) {
|
|
16
|
+
const h = hostname.replace(/^\[|\]$/g, "");
|
|
17
|
+
return h === "localhost" || h === "127.0.0.1" || h === "::1" || h.endsWith(".localhost") || h.startsWith("127.");
|
|
18
|
+
}
|
|
9
19
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
20
|
+
* Default origin policy for a localhost dev tool: allow requests with no
|
|
21
|
+
* `Origin` header (native, non-browser clients), allow any loopback origin
|
|
22
|
+
* (so cross-port localhost dev setups keep working), and allow explicitly
|
|
23
|
+
* configured origins. Everything else — a real remote page in the dev's
|
|
24
|
+
* browser — is rejected.
|
|
13
25
|
*/
|
|
14
|
-
function
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
serialize: serializeOverride ?? ((msg) => {
|
|
43
|
-
let method;
|
|
44
|
-
if (msg.t === "q") method = msg.m;
|
|
45
|
-
else {
|
|
46
|
-
method = pendingRequestMethods.get(msg.i);
|
|
47
|
-
pendingRequestMethods.delete(msg.i);
|
|
26
|
+
function isAllowedOrigin(origin, allowedOrigins) {
|
|
27
|
+
if (!origin) return true;
|
|
28
|
+
if (allowedOrigins.includes(origin)) return true;
|
|
29
|
+
try {
|
|
30
|
+
return isLoopbackHostname(new URL(origin).hostname);
|
|
31
|
+
} catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Route `upgrade` events on a server to the crossws adapter, optionally
|
|
37
|
+
* filtered to a single `path`. Non-matching requests are left untouched so
|
|
38
|
+
* other upgrade listeners (e.g. a Vite dev server's HMR socket) can claim
|
|
39
|
+
* them, unless `destroyUnmatched` is set. Returns a detach function that
|
|
40
|
+
* removes the listener.
|
|
41
|
+
*/
|
|
42
|
+
function routeUpgrades(server, ws, path, destroyUnmatched, allowedOrigins) {
|
|
43
|
+
const listener = (req, socket, head) => {
|
|
44
|
+
socket.on("error", () => {});
|
|
45
|
+
if (path) {
|
|
46
|
+
let pathname = req.url ?? "/";
|
|
47
|
+
try {
|
|
48
|
+
pathname = new URL(req.url ?? "/", "http://localhost").pathname;
|
|
49
|
+
} catch {}
|
|
50
|
+
if (!pathMatches(pathname, path)) {
|
|
51
|
+
if (destroyUnmatched) {
|
|
52
|
+
socket.write("HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n");
|
|
53
|
+
socket.destroy();
|
|
48
54
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (allowedOrigins !== false && !isAllowedOrigin(req.headers.origin, allowedOrigins ?? [])) {
|
|
59
|
+
socket.write("HTTP/1.1 403 Forbidden\r\nConnection: close\r\n\r\n");
|
|
60
|
+
socket.destroy();
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
ws.handleUpgrade(req, socket, head);
|
|
64
|
+
};
|
|
65
|
+
server.on("upgrade", listener);
|
|
66
|
+
return () => server.off("upgrade", listener);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Attach a WebSocket transport to an existing RPC group, powered by
|
|
70
|
+
* [crossws](https://crossws.h3.dev). Either attach to an existing HTTP(S)
|
|
71
|
+
* `server` (sharing its port, optionally scoped to a `path`), or let this
|
|
72
|
+
* helper create a standalone server from `port` / `host` / `https`.
|
|
73
|
+
*
|
|
74
|
+
* Returns the crossws node adapter plus `detach` (remove the upgrade
|
|
75
|
+
* listener from a shared `server`) and `close` (full deterministic
|
|
76
|
+
* teardown).
|
|
77
|
+
*/
|
|
78
|
+
function attachWsRpcTransport(rpcGroup, options = {}) {
|
|
79
|
+
const { server, port, host = "localhost", path, destroyUnmatched = false, https, allowedOrigins, onConnected = NOOP, onDisconnected = NOOP, definitions = EMPTY_DEFS, serialize: serializeOverride, deserialize: deserializeOverride } = options;
|
|
80
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
81
|
+
const ws = crossws({ hooks: {
|
|
82
|
+
open: (peer) => {
|
|
83
|
+
const meta = {
|
|
84
|
+
id: sessionId++,
|
|
85
|
+
peer,
|
|
86
|
+
subscribedStates: /* @__PURE__ */ new Set()
|
|
87
|
+
};
|
|
88
|
+
const pendingRequestMethods = /* @__PURE__ */ new Map();
|
|
89
|
+
const state = {
|
|
90
|
+
meta,
|
|
91
|
+
channel: void 0
|
|
92
|
+
};
|
|
93
|
+
const channel = {
|
|
94
|
+
post: (data) => {
|
|
95
|
+
peer.send(data);
|
|
96
|
+
},
|
|
97
|
+
on: (fn) => {
|
|
98
|
+
state.onMessage = fn;
|
|
99
|
+
},
|
|
100
|
+
serialize: serializeOverride ?? ((msg) => {
|
|
101
|
+
let method;
|
|
102
|
+
if (msg.t === "q") method = msg.m;
|
|
103
|
+
else {
|
|
104
|
+
method = pendingRequestMethods.get(msg.i);
|
|
105
|
+
pendingRequestMethods.delete(msg.i);
|
|
106
|
+
}
|
|
107
|
+
if (!(msg.t === "s" && "e" in msg) && !!method && definitions.get(method)?.jsonSerializable === true) return strictJsonStringify(msg, method ?? "");
|
|
108
|
+
return `s:${structuredCloneStringify(msg)}`;
|
|
109
|
+
}),
|
|
110
|
+
deserialize: deserializeOverride ?? ((raw) => {
|
|
111
|
+
const msg = raw.startsWith("s:") ? structuredCloneParse(raw.slice(2)) : JSON.parse(raw);
|
|
112
|
+
if (msg.t === "q" && msg.i && msg.m) pendingRequestMethods.set(msg.i, msg.m);
|
|
113
|
+
return msg;
|
|
114
|
+
}),
|
|
115
|
+
meta
|
|
116
|
+
};
|
|
117
|
+
state.channel = channel;
|
|
118
|
+
states.set(peer, state);
|
|
63
119
|
rpcGroup.updateChannels((channels) => {
|
|
64
|
-
|
|
120
|
+
channels.push(channel);
|
|
121
|
+
});
|
|
122
|
+
onConnected(peer, meta);
|
|
123
|
+
},
|
|
124
|
+
message: (peer, message) => {
|
|
125
|
+
states.get(peer)?.onMessage?.(message.text());
|
|
126
|
+
},
|
|
127
|
+
close: (peer) => {
|
|
128
|
+
const state = states.get(peer);
|
|
129
|
+
if (!state) return;
|
|
130
|
+
states.delete(peer);
|
|
131
|
+
rpcGroup.updateChannels((channels) => {
|
|
132
|
+
const index = channels.indexOf(state.channel);
|
|
65
133
|
if (index >= 0) channels.splice(index, 1);
|
|
66
134
|
});
|
|
67
|
-
onDisconnected(
|
|
135
|
+
onDisconnected(peer, state.meta);
|
|
136
|
+
}
|
|
137
|
+
} });
|
|
138
|
+
let detach = NOOP;
|
|
139
|
+
let ownedServer;
|
|
140
|
+
if (server) detach = routeUpgrades(server, ws, path, destroyUnmatched, allowedOrigins);
|
|
141
|
+
else if (https) {
|
|
142
|
+
ownedServer = createServer$1(https);
|
|
143
|
+
detach = routeUpgrades(ownedServer, ws, path, true, allowedOrigins);
|
|
144
|
+
ownedServer.listen(port, host);
|
|
145
|
+
} else {
|
|
146
|
+
ownedServer = createServer((_req, res) => {
|
|
147
|
+
res.writeHead(426, { "content-type": "text/plain" });
|
|
148
|
+
res.end("Upgrade Required");
|
|
68
149
|
});
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
150
|
+
detach = routeUpgrades(ownedServer, ws, path, true, allowedOrigins);
|
|
151
|
+
ownedServer.listen(port, host);
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
ws,
|
|
155
|
+
detach,
|
|
156
|
+
async close() {
|
|
157
|
+
detach();
|
|
158
|
+
ws.closeAll(void 0, void 0, true);
|
|
159
|
+
if (ownedServer) {
|
|
160
|
+
const srv = ownedServer;
|
|
161
|
+
await new Promise((r) => srv.close(() => r()));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
};
|
|
72
165
|
}
|
|
73
166
|
//#endregion
|
|
74
|
-
export { attachWsRpcTransport };
|
|
167
|
+
export { attachWsRpcTransport, isAllowedOrigin, isLoopbackHostname };
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { createRpcServer } from "./rpc/server.mjs";
|
|
2
2
|
import { attachWsRpcTransport } from "./rpc/transports/ws-server.mjs";
|
|
3
|
-
import { t as getInternalContext } from "./context-
|
|
4
|
-
import { WebSocketServer } from "ws";
|
|
5
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
|
+
import { t as getInternalContext } from "./context-3x_bgBgZ.mjs";
|
|
6
4
|
import { createServer } from "node:http";
|
|
5
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
7
6
|
import { H3, toNodeHandler } from "h3";
|
|
8
7
|
//#region src/node/server.ts
|
|
9
8
|
/**
|
|
@@ -15,8 +14,8 @@ async function startHttpAndWs(options) {
|
|
|
15
14
|
const { context, port } = options;
|
|
16
15
|
const bindHost = options.host ?? "localhost";
|
|
17
16
|
const app = options.app ?? new H3();
|
|
18
|
-
const
|
|
19
|
-
const
|
|
17
|
+
const ownsHttpServer = !options.server;
|
|
18
|
+
const httpServer = options.server ?? createServer(toNodeHandler(app));
|
|
20
19
|
const rpcHost = context.rpc;
|
|
21
20
|
const asyncStorage = new AsyncLocalStorage();
|
|
22
21
|
const rpcGroup = createRpcServer(rpcHost.functions, { rpcOptions: { resolver(name, fn) {
|
|
@@ -31,9 +30,16 @@ async function startHttpAndWs(options) {
|
|
|
31
30
|
});
|
|
32
31
|
};
|
|
33
32
|
} } });
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
const separateWsPort = ownsHttpServer && options.wsPort != null && options.wsPort !== port ? options.wsPort : void 0;
|
|
34
|
+
const { ws, close: closeWs } = attachWsRpcTransport(rpcGroup, {
|
|
35
|
+
...separateWsPort != null ? {
|
|
36
|
+
port: separateWsPort,
|
|
37
|
+
host: bindHost
|
|
38
|
+
} : { server: httpServer },
|
|
39
|
+
path: options.path,
|
|
40
|
+
destroyUnmatched: ownsHttpServer,
|
|
41
|
+
allowedOrigins: options.allowedOrigins,
|
|
42
|
+
onDisconnected: (_peer, meta) => {
|
|
37
43
|
rpcHost._emitSessionDisconnected(meta);
|
|
38
44
|
}
|
|
39
45
|
});
|
|
@@ -49,14 +55,14 @@ async function startHttpAndWs(options) {
|
|
|
49
55
|
return { isTrusted: true };
|
|
50
56
|
}
|
|
51
57
|
});
|
|
52
|
-
await new Promise((resolveListen) => {
|
|
58
|
+
if (ownsHttpServer) await new Promise((resolveListen) => {
|
|
53
59
|
httpServer.listen(port, bindHost, () => resolveListen());
|
|
54
60
|
});
|
|
55
61
|
const address = httpServer.address();
|
|
56
62
|
const resolvedPort = typeof address === "object" && address ? address.port : port;
|
|
57
63
|
const origin = `http://${bindHost}:${resolvedPort}`;
|
|
58
64
|
const internal = getInternalContext(context);
|
|
59
|
-
const wsUrl =
|
|
65
|
+
const wsUrl = `ws://${bindHost}:${separateWsPort ?? resolvedPort}${options.path ?? ""}`;
|
|
60
66
|
internal.wsEndpoint = { url: wsUrl };
|
|
61
67
|
if (options.onReady) await options.onReady({
|
|
62
68
|
origin,
|
|
@@ -67,12 +73,11 @@ async function startHttpAndWs(options) {
|
|
|
67
73
|
origin,
|
|
68
74
|
port: resolvedPort,
|
|
69
75
|
app,
|
|
70
|
-
|
|
76
|
+
ws,
|
|
71
77
|
rpcGroup,
|
|
72
78
|
async close() {
|
|
73
|
-
|
|
74
|
-
await new Promise((r) =>
|
|
75
|
-
await new Promise((r) => httpServer.close(() => r()));
|
|
79
|
+
await closeWs();
|
|
80
|
+
if (ownsHttpServer) await new Promise((r) => httpServer.close(() => r()));
|
|
76
81
|
if (getInternalContext(context).wsEndpoint?.url === wsUrl) getInternalContext(context).wsEndpoint = void 0;
|
|
77
82
|
}
|
|
78
83
|
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { it as DevframeRpcServerFunctions, m as DevframeNodeContext, rt as DevframeRpcClientFunctions } from "./devframe-D-gr9sBx.mjs";
|
|
2
|
+
import { BirpcGroup } from "birpc";
|
|
3
|
+
import { NodeAdapter } from "crossws/adapters/node";
|
|
4
|
+
import { Server } from "node:http";
|
|
5
|
+
import { H3 } from "h3";
|
|
6
|
+
|
|
7
|
+
//#region src/node/server.d.ts
|
|
8
|
+
interface StartHttpAndWsOptions {
|
|
9
|
+
context: DevframeNodeContext;
|
|
10
|
+
host?: string;
|
|
11
|
+
port: number;
|
|
12
|
+
/**
|
|
13
|
+
* Optional h3 app to mount on. When omitted a fresh one is created;
|
|
14
|
+
* when provided, callers can add their own routes (static handlers,
|
|
15
|
+
* auth middleware, etc.) first.
|
|
16
|
+
*/
|
|
17
|
+
app?: H3;
|
|
18
|
+
/**
|
|
19
|
+
* Bind the WS endpoint to a single upgrade route (e.g. `/__devframe_ws`) instead of
|
|
20
|
+
* claiming every upgrade on the port. This lets the socket share a server
|
|
21
|
+
* with other upgrade handlers (Vite HMR, a host framework's own sockets)
|
|
22
|
+
* and is what the SPA's `__connection.json` points at. When omitted, the WS
|
|
23
|
+
* server handles every upgrade on the port (legacy behaviour).
|
|
24
|
+
*/
|
|
25
|
+
path?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Bind the WS endpoint on its own port instead of sharing the HTTP server's.
|
|
28
|
+
* The HTTP/SPA server still listens on `port`; the socket gets a dedicated
|
|
29
|
+
* `ws` server on `wsPort` (same `host`). Use this for the "different port"
|
|
30
|
+
* connection scenario. Ignored when a `server` is supplied.
|
|
31
|
+
*/
|
|
32
|
+
wsPort?: number;
|
|
33
|
+
/**
|
|
34
|
+
* Mount the WS endpoint onto an existing HTTP server, sharing its port,
|
|
35
|
+
* rather than creating and listening on a fresh one. Use this to embed
|
|
36
|
+
* devframe's RPC socket inside a host server (e.g. a Vite dev server) — pair
|
|
37
|
+
* it with `path` so it coexists with the host's routes. The caller owns the
|
|
38
|
+
* server's lifecycle: {@link StartedServer.close} detaches devframe's upgrade
|
|
39
|
+
* listener but leaves the host server running. When set, `host`/`port` are
|
|
40
|
+
* only used to report the resolved origin.
|
|
41
|
+
*/
|
|
42
|
+
server?: Server;
|
|
43
|
+
/**
|
|
44
|
+
* When `false`, the RPC server is started without a trust handshake.
|
|
45
|
+
* Intended for single-user localhost tools where an auth round-trip
|
|
46
|
+
* would only get in the way. The Vite-flavoured auth layer in
|
|
47
|
+
* `@vitejs/devtools` already honors the equivalent
|
|
48
|
+
* `devtools.clientAuth` setting; devframe records the intent here so
|
|
49
|
+
* future auth plumbing can consult it without another API change.
|
|
50
|
+
*
|
|
51
|
+
* Default: `true`.
|
|
52
|
+
*/
|
|
53
|
+
auth?: boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Extra origins to accept on the WS upgrade beyond the loopback default
|
|
56
|
+
* (`localhost`/`127.0.0.1`/`::1` and any `Origin`-less request from a
|
|
57
|
+
* native client). Add your LAN/tunnel origin here when reaching the tool
|
|
58
|
+
* from another host. Pass `false` to disable origin checking entirely
|
|
59
|
+
* (not recommended). Default: loopback-only.
|
|
60
|
+
*/
|
|
61
|
+
allowedOrigins?: readonly string[] | false;
|
|
62
|
+
/**
|
|
63
|
+
* Called once the WS server is bound so callers can mount static
|
|
64
|
+
* handlers whose origin depends on the resolved port, or print their
|
|
65
|
+
* own startup banner. Devframe does not print one itself.
|
|
66
|
+
*/
|
|
67
|
+
onReady?: (info: {
|
|
68
|
+
origin: string;
|
|
69
|
+
port: number;
|
|
70
|
+
app: H3;
|
|
71
|
+
}) => void | Promise<void>;
|
|
72
|
+
}
|
|
73
|
+
interface StartedServer {
|
|
74
|
+
/** Listening origin, e.g. `http://localhost:9999`. */
|
|
75
|
+
origin: string;
|
|
76
|
+
port: number;
|
|
77
|
+
app: H3;
|
|
78
|
+
/** The crossws node adapter driving the RPC socket (connected peers, pub/sub). */
|
|
79
|
+
ws: NodeAdapter;
|
|
80
|
+
rpcGroup: BirpcGroup<DevframeRpcClientFunctions, DevframeRpcServerFunctions, false>;
|
|
81
|
+
close: () => Promise<void>;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Compose an h3 + WebSocket server for a devframe context. The RPC
|
|
85
|
+
* group is bound to `context.rpc.functions`; the WS endpoint lives on
|
|
86
|
+
* the same port as the HTTP server.
|
|
87
|
+
*/
|
|
88
|
+
declare function startHttpAndWs(options: StartHttpAndWsOptions): Promise<StartedServer>;
|
|
89
|
+
//#endregion
|
|
90
|
+
export { StartedServer as n, startHttpAndWs as r, StartHttpAndWsOptions as t };
|