devframe 0.8.2 → 0.9.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-CttmCMBi.mjs +70 -0
- package/dist/_shared-DmpWW-HH.d.mts +43 -0
- package/dist/adapters/build.d.mts +1 -1
- package/dist/adapters/build.mjs +6 -5
- package/dist/adapters/cac.d.mts +1 -1
- package/dist/adapters/cac.mjs +157 -1
- package/dist/adapters/dev.d.mts +20 -42
- package/dist/adapters/dev.mjs +2 -1
- package/dist/adapters/embedded.d.mts +1 -1
- package/dist/adapters/initiate.d.mts +223 -0
- package/dist/adapters/initiate.mjs +2 -0
- package/dist/adapters/mcp.d.mts +26 -2
- package/dist/adapters/mcp.mjs +2 -2
- package/dist/cli/main.mjs +2 -2
- package/dist/client/index.d.mts +70 -6
- package/dist/client/index.mjs +743 -408
- package/dist/constants.d.mts +19 -6
- package/dist/constants.mjs +19 -6
- package/dist/{context-CBg8iRbQ.mjs → context-C33rR7n0.mjs} +1 -1
- package/dist/{context-DoSozfvx.d.mts → context-CSCwoABx.d.mts} +1 -1
- package/dist/{host-h3-D2hYZvDK.mjs → context-Du11TLcO.mjs} +5 -255
- package/dist/dev-BEveeA5H.mjs +233 -0
- package/dist/{devframe-mQ4qZAuo.d.mts → devframe-Bdd9YXTy.d.mts} +88 -25
- package/dist/{diagnostics-D7wM2cwM.mjs → diagnostics-DLYH5oD3.mjs} +16 -0
- package/dist/dist-D8jAMwxU.mjs +227 -0
- package/dist/helpers/vite.d.mts +43 -39
- package/dist/helpers/vite.mjs +26 -38
- package/dist/host-agent-CpbAoqBx.mjs +230 -0
- package/dist/host-h3-CzCZwtuV.mjs +26 -0
- package/dist/{fetch-BKaD0Vb3.mjs → http-DLr_cJZ7.mjs} +42 -4
- package/dist/{index-b64Uuhy2.d.mts → index-CZRd2K1C.d.mts} +2 -2
- package/dist/{index-Dbw1p5ch.d.mts → index-DSCq4M4q.d.mts} +2 -31
- package/dist/index.d.mts +9 -4
- package/dist/index.mjs +8 -1
- package/dist/{instance-registry-BnnA2Eoh.mjs → instance-registry-BQqGoDO9.mjs} +9 -2
- package/dist/instance-shell-DBTXTSjN.d.mts +264 -0
- package/dist/instance-shell-KRdee1QF.mjs +485 -0
- package/dist/internal/index.d.mts +150 -0
- package/dist/internal/index.mjs +7 -0
- package/dist/node/auth.d.mts +2 -2
- package/dist/node/hub-internals.d.mts +2 -14
- package/dist/node/hub-internals.mjs +2 -2
- package/dist/node/index.d.mts +3 -267
- package/dist/node/index.mjs +3 -5
- package/dist/recipes/common-rpc-functions.d.mts +3 -3
- package/dist/recipes/interactive-auth.d.mts +3 -3
- package/dist/recipes/interactive-auth.mjs +6 -6
- package/dist/rolldown-runtime-JspESFgx.mjs +35 -0
- package/dist/rpc/dump.d.mts +77 -1
- package/dist/rpc/dump.mjs +1 -1
- package/dist/rpc/index.d.mts +2 -2
- package/dist/rpc/index.mjs +3 -17
- package/dist/rpc/transports/sse-client.d.mts +2 -0
- package/dist/rpc/transports/sse-client.mjs +142 -0
- package/dist/rpc/transports/sse-server.d.mts +61 -0
- package/dist/rpc/transports/sse-server.mjs +209 -0
- package/dist/rpc/transports/ws-bun.d.mts +35 -0
- package/dist/rpc/transports/ws-bun.mjs +31 -0
- package/dist/rpc/transports/ws-client.d.mts +1 -1
- package/dist/rpc/transports/ws-client.mjs +10 -18
- package/dist/rpc/transports/ws-server.d.mts +2 -2
- package/dist/rpc/transports/ws-server.mjs +2 -235
- package/dist/rpc-core-CGctXToO.d.mts +48 -0
- package/dist/rpc-core-CqcJkAu9.mjs +81 -0
- package/dist/{serialization-C8Mnw9hK.mjs → serialization-BHY8M5NQ.mjs} +1 -1
- package/dist/{shared-state-6kHolYZy.mjs → shared-state-fRRbRUtD.mjs} +1 -1
- package/dist/sse-client-BsIK3hMD.d.mts +37 -0
- package/dist/{dump-CgZShDRB.mjs → static-CvjkO8QE.mjs} +2 -265
- package/dist/{storage-CTNVbuFB.mjs → storage-BcmVEJRc.mjs} +2 -2
- package/dist/types/index.d.mts +3 -3
- package/dist/types/index.mjs +1 -6
- package/dist/utils/events.d.mts +1 -1
- package/dist/utils/launch-editor.mjs +1 -25
- package/dist/utils/open.mjs +1 -1
- package/dist/utils/serve-static.mjs +1 -1
- package/dist/utils/shared-state.d.mts +1 -1
- package/dist/utils/shared-state.mjs +1 -1
- package/dist/utils/simple-schema.d.mts +101 -1
- package/dist/utils/streaming-channel.d.mts +1 -1
- package/dist/validation-BiuDXTKW.mjs +266 -0
- package/dist/wire-codec-9VhIKnyp.mjs +58 -0
- package/dist/{ws-client-B6Tnr0ic.d.mts → ws-client-CdNuATYa.d.mts} +6 -1
- package/dist/ws-server-Bk1hOG3X.mjs +267 -0
- package/dist/{ws-server-uKQcClcJ.d.mts → ws-server-Ces08fjP.d.mts} +89 -8
- package/package.json +10 -9
- package/skills/devframe/SKILL.md +84 -85
- package/dist/_shared-bWRzeSa0.mjs +0 -19
- package/dist/adapters/cli.d.mts +0 -11
- package/dist/adapters/cli.mjs +0 -6
- package/dist/cac-D4_9ok0z.mjs +0 -157
- package/dist/dev-Bc49u3qg.mjs +0 -439
- package/dist/http-C4T68YV6.mjs +0 -38
- package/dist/index-vAX6bYuc.d.mts +0 -78
- package/dist/recipes/open-helpers.d.mts +0 -6
- package/dist/recipes/open-helpers.mjs +0 -6
- package/dist/server-CD8XmBXl.mjs +0 -167
- package/dist/server-UHWae43Q.d.mts +0 -149
- package/dist/simple-schema-BDzLeJDk.d.mts +0 -102
- package/dist/utils/promise.d.mts +0 -8
- package/dist/utils/promise.mjs +0 -15
- package/dist/utils/scope.d.mts +0 -11
- package/dist/utils/scope.mjs +0 -15
- package/dist/{open-Deb5xmIT.mjs → open-Dz4V4irZ.mjs} +1 -1
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { h as RpcDumpStore, l as RpcDumpClientOptions, m as RpcDumpRecordError, n as BirpcReturn, o as RpcDefinitionsToFunctions, u as RpcDumpCollectionOptions, v as RpcFunctionDefinitionAny } from "./types-CnJSgRVa.mjs";
|
|
2
|
-
//#region src/rpc/dump/static.d.ts
|
|
3
|
-
type StaticRpcDumpSerialization = 'json' | 'structured-clone';
|
|
4
|
-
interface StaticRpcDumpManifestStaticEntry {
|
|
5
|
-
type: 'static';
|
|
6
|
-
path: string;
|
|
7
|
-
/** Encoder used when this entry's file was written. Default: `'json'`. */
|
|
8
|
-
serialization?: StaticRpcDumpSerialization;
|
|
9
|
-
}
|
|
10
|
-
interface StaticRpcDumpManifestQueryEntry {
|
|
11
|
-
type: 'query';
|
|
12
|
-
records: Record<string, string>;
|
|
13
|
-
fallback?: string;
|
|
14
|
-
/** Encoder used when each record/fallback file was written. Default: `'json'`. */
|
|
15
|
-
serialization?: StaticRpcDumpSerialization;
|
|
16
|
-
}
|
|
17
|
-
type StaticRpcDumpManifestValue = StaticRpcDumpManifestStaticEntry | StaticRpcDumpManifestQueryEntry | any;
|
|
18
|
-
type StaticRpcDumpManifest = Record<string, StaticRpcDumpManifestValue>;
|
|
19
|
-
interface StaticRpcDumpFile {
|
|
20
|
-
/** Whether this file was written via `JSON.stringify` or `structured-clone-es.stringify`. */
|
|
21
|
-
serialization: StaticRpcDumpSerialization;
|
|
22
|
-
/** Function name the file belongs to — used to scope `DF0019` errors during write. */
|
|
23
|
-
fnName: string;
|
|
24
|
-
/** Payload to encode. */
|
|
25
|
-
data: unknown;
|
|
26
|
-
}
|
|
27
|
-
interface StaticRpcDumpCollection {
|
|
28
|
-
manifest: StaticRpcDumpManifest;
|
|
29
|
-
files: Record<string, StaticRpcDumpFile>;
|
|
30
|
-
}
|
|
31
|
-
declare function collectStaticRpcDump(definitions: Iterable<RpcFunctionDefinitionAny>, context: any): Promise<StaticRpcDumpCollection>;
|
|
32
|
-
//#endregion
|
|
33
|
-
//#region src/rpc/dump/collect.d.ts
|
|
34
|
-
/**
|
|
35
|
-
* Collects pre-computed dumps by executing functions with their defined input combinations.
|
|
36
|
-
* Static functions without dump config automatically get `{ inputs: [[]] }`.
|
|
37
|
-
*
|
|
38
|
-
* @example
|
|
39
|
-
* ```ts
|
|
40
|
-
* const store = await dumpFunctions([greet], context, { concurrency: 10 })
|
|
41
|
-
* ```
|
|
42
|
-
*/
|
|
43
|
-
declare function dumpFunctions<T extends readonly RpcFunctionDefinitionAny[]>(definitions: T, context?: any, options?: RpcDumpCollectionOptions): Promise<RpcDumpStore<RpcDefinitionsToFunctions<T>>>;
|
|
44
|
-
/**
|
|
45
|
-
* Creates a client that serves pre-computed results from a dump store.
|
|
46
|
-
* Uses argument hashing to match calls to stored records.
|
|
47
|
-
*
|
|
48
|
-
* @example
|
|
49
|
-
* ```ts
|
|
50
|
-
* const client = createClientFromDump(store)
|
|
51
|
-
* await client.greet('Alice')
|
|
52
|
-
* ```
|
|
53
|
-
*/
|
|
54
|
-
declare function createClientFromDump<T extends Record<string, any>>(store: RpcDumpStore<T>, options?: RpcDumpClientOptions): BirpcReturn<T>;
|
|
55
|
-
/**
|
|
56
|
-
* Filters function definitions to only those with dump definitions.
|
|
57
|
-
* Note: Only checks the definition itself, not setup results.
|
|
58
|
-
*/
|
|
59
|
-
declare function getDefinitionsWithDumps<T extends readonly RpcFunctionDefinitionAny[]>(definitions: T): RpcFunctionDefinitionAny[];
|
|
60
|
-
//#endregion
|
|
61
|
-
//#region src/rpc/dump/error.d.ts
|
|
62
|
-
/**
|
|
63
|
-
* Normalize a thrown value into a plain object suitable for storage in
|
|
64
|
-
* a dump record. Preserves `message`, `name`, `cause`, and any own
|
|
65
|
-
* enumerable properties of an `Error` so consumers reading the dump can
|
|
66
|
-
* reconstruct a richer Error than just `{ message, name }`.
|
|
67
|
-
*
|
|
68
|
-
* Non-`Error` throws are wrapped as `{ name: 'Error', message: String(thrown) }`.
|
|
69
|
-
*/
|
|
70
|
-
declare function serializeDumpError(error: unknown): RpcDumpRecordError;
|
|
71
|
-
/**
|
|
72
|
-
* Inverse of {@link serializeDumpError}: rebuild a thrown `Error` from
|
|
73
|
-
* the plain object stored in a dump record. Preserves `cause`, restores
|
|
74
|
-
* the original `name`, and re-attaches any custom own properties.
|
|
75
|
-
*/
|
|
76
|
-
declare function reviveDumpError(stored: RpcDumpRecordError): Error;
|
|
77
|
-
//#endregion
|
|
78
|
-
export { getDefinitionsWithDumps as a, StaticRpcDumpManifest as c, StaticRpcDumpManifestValue as d, StaticRpcDumpSerialization as f, dumpFunctions as i, StaticRpcDumpManifestQueryEntry as l, serializeDumpError as n, StaticRpcDumpCollection as o, collectStaticRpcDump as p, createClientFromDump as r, StaticRpcDumpFile as s, reviveDumpError as t, StaticRpcDumpManifestStaticEntry as u };
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { commonRpcFunctions, openInEditor, openInFinder } from "./common-rpc-functions.mjs";
|
|
2
|
-
//#region src/recipes/open-helpers.d.ts
|
|
3
|
-
/** @deprecated Use `commonRpcFunctions` from `devframe/recipes/common-rpc-functions` instead. */
|
|
4
|
-
declare const openHelpers: typeof commonRpcFunctions;
|
|
5
|
-
//#endregion
|
|
6
|
-
export { openHelpers, openInEditor, openInFinder };
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { commonRpcFunctions, openInEditor, openInFinder } from "./common-rpc-functions.mjs";
|
|
2
|
-
//#region src/recipes/open-helpers.ts
|
|
3
|
-
/** @deprecated Use `commonRpcFunctions` from `devframe/recipes/common-rpc-functions` instead. */
|
|
4
|
-
const openHelpers = commonRpcFunctions;
|
|
5
|
-
//#endregion
|
|
6
|
-
export { openHelpers, openInEditor, openInFinder };
|
package/dist/server-CD8XmBXl.mjs
DELETED
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import { createRpcServer } from "./rpc/server.mjs";
|
|
2
|
-
import { attachWsRpcTransport } from "./rpc/transports/ws-server.mjs";
|
|
3
|
-
import { t as diagnostics } from "./diagnostics-D7wM2cwM.mjs";
|
|
4
|
-
import { t as getInternalContext } from "./context-CBg8iRbQ.mjs";
|
|
5
|
-
import { createServer } from "node:http";
|
|
6
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
7
|
-
import { H3, toNodeHandler } from "h3";
|
|
8
|
-
import { isIP } from "node:net";
|
|
9
|
-
//#region src/node/utils.ts
|
|
10
|
-
function isObject(value) {
|
|
11
|
-
return Object.prototype.toString.call(value) === "[object Object]";
|
|
12
|
-
}
|
|
13
|
-
const NON_DIALABLE_HOSTS = /* @__PURE__ */ new Set([
|
|
14
|
-
"0.0.0.0",
|
|
15
|
-
"127.0.0.1",
|
|
16
|
-
"::",
|
|
17
|
-
"0000:0000:0000:0000:0000:0000:0000:0000",
|
|
18
|
-
""
|
|
19
|
-
]);
|
|
20
|
-
/** Map a bind host to a host a client can actually connect to. */
|
|
21
|
-
function toDialableHost(host) {
|
|
22
|
-
return NON_DIALABLE_HOSTS.has(host) ? "localhost" : host;
|
|
23
|
-
}
|
|
24
|
-
/** Format a bind host for use in a URL authority (dialable, IPv6-bracketed). */
|
|
25
|
-
function formatHostForUrl(host) {
|
|
26
|
-
const dialable = toDialableHost(host);
|
|
27
|
-
return isIP(dialable) === 6 ? `[${dialable}]` : dialable;
|
|
28
|
-
}
|
|
29
|
-
function normalizeHttpServerUrl(host, port) {
|
|
30
|
-
return `http://${formatHostForUrl(host)}:${port}`;
|
|
31
|
-
}
|
|
32
|
-
//#endregion
|
|
33
|
-
//#region src/node/server.ts
|
|
34
|
-
/**
|
|
35
|
-
* Compose an h3 + WebSocket server for a devframe context. The RPC
|
|
36
|
-
* group is bound to `context.rpc.functions`; the WS endpoint lives on
|
|
37
|
-
* the same port as the HTTP server.
|
|
38
|
-
*/
|
|
39
|
-
async function startHttpAndWs(options) {
|
|
40
|
-
const { context, port } = options;
|
|
41
|
-
const bindHost = options.host ?? "localhost";
|
|
42
|
-
const app = options.app ?? new H3();
|
|
43
|
-
const ownsHttpServer = !options.server;
|
|
44
|
-
const httpServer = options.server ?? createServer(toNodeHandler(app));
|
|
45
|
-
const rpcHost = context.rpc;
|
|
46
|
-
const asyncStorage = new AsyncLocalStorage();
|
|
47
|
-
const authHandler = typeof options.auth === "object" ? options.auth : void 0;
|
|
48
|
-
const effectiveAuthorize = options.authorize ?? authHandler?.authorize;
|
|
49
|
-
if (authHandler) {
|
|
50
|
-
for (const fn of authHandler.rpcFunctions) if (!rpcHost.definitions.has(fn.name)) rpcHost.register(fn);
|
|
51
|
-
}
|
|
52
|
-
const rpcGroup = createRpcServer(rpcHost.functions, { rpcOptions: {
|
|
53
|
-
onFunctionError: options.rpcOptions?.onFunctionError,
|
|
54
|
-
onGeneralError: options.rpcOptions?.onGeneralError,
|
|
55
|
-
resolver(name, fn) {
|
|
56
|
-
const rpc = this;
|
|
57
|
-
if (!fn) return void 0;
|
|
58
|
-
return async function(...args) {
|
|
59
|
-
const meta = rpc.$meta;
|
|
60
|
-
if (effectiveAuthorize && !effectiveAuthorize(name, {
|
|
61
|
-
meta,
|
|
62
|
-
rpc
|
|
63
|
-
})) throw diagnostics.DF0036({ name });
|
|
64
|
-
return await asyncStorage.run({
|
|
65
|
-
rpc,
|
|
66
|
-
meta
|
|
67
|
-
}, async () => {
|
|
68
|
-
return (await fn).apply(this, args);
|
|
69
|
-
});
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
} });
|
|
73
|
-
const separateWsPort = ownsHttpServer && options.wsPort != null && options.wsPort !== port ? options.wsPort : void 0;
|
|
74
|
-
const { ws, close: closeWs } = attachWsRpcTransport(rpcGroup, {
|
|
75
|
-
...separateWsPort != null ? {
|
|
76
|
-
port: separateWsPort,
|
|
77
|
-
host: bindHost
|
|
78
|
-
} : { server: httpServer },
|
|
79
|
-
path: options.path,
|
|
80
|
-
destroyUnmatched: ownsHttpServer,
|
|
81
|
-
allowedOrigins: options.allowedOrigins,
|
|
82
|
-
onConnected: authHandler || options.onPeerConnect ? (peer, meta) => {
|
|
83
|
-
const session = {
|
|
84
|
-
meta,
|
|
85
|
-
rpc: rpcGroup.clients.find((client) => client.$meta === meta)
|
|
86
|
-
};
|
|
87
|
-
authHandler?.onConnect(peer, session);
|
|
88
|
-
options.onPeerConnect?.(peer, session);
|
|
89
|
-
} : void 0,
|
|
90
|
-
onDisconnected: (peer, meta) => {
|
|
91
|
-
options.onPeerDisconnect?.(peer, meta);
|
|
92
|
-
rpcHost._emitSessionDisconnected(meta);
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
rpcHost._rpcGroup = rpcGroup;
|
|
96
|
-
rpcHost._asyncStorage = asyncStorage;
|
|
97
|
-
rpcHost._authDisabled = options.auth === false;
|
|
98
|
-
if (options.auth === false && !rpcHost.definitions.has("anonymous:devframe:auth")) rpcHost.register({
|
|
99
|
-
name: "anonymous:devframe:auth",
|
|
100
|
-
type: "action",
|
|
101
|
-
handler: () => {
|
|
102
|
-
const session = rpcHost.getCurrentRpcSession();
|
|
103
|
-
if (session) session.meta.isTrusted = true;
|
|
104
|
-
return { isTrusted: true };
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
if (ownsHttpServer) {
|
|
108
|
-
try {
|
|
109
|
-
await new Promise((resolve, reject) => {
|
|
110
|
-
const onError = (error) => reject(error);
|
|
111
|
-
httpServer.once("error", onError);
|
|
112
|
-
httpServer.listen(port, bindHost, () => {
|
|
113
|
-
httpServer.removeListener("error", onError);
|
|
114
|
-
resolve();
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
} catch (error) {
|
|
118
|
-
await closeWs().catch(() => {});
|
|
119
|
-
throw diagnostics.DF0052({
|
|
120
|
-
host: bindHost,
|
|
121
|
-
port,
|
|
122
|
-
reason: error instanceof Error ? error.message : String(error),
|
|
123
|
-
cause: error
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
if (options.onServerError) httpServer.on("error", options.onServerError);
|
|
127
|
-
}
|
|
128
|
-
const address = httpServer.address();
|
|
129
|
-
const resolvedPort = typeof address === "object" && address ? address.port : port;
|
|
130
|
-
const origin = normalizeHttpServerUrl(bindHost, resolvedPort);
|
|
131
|
-
const internal = getInternalContext(context);
|
|
132
|
-
const wsPortForUrl = separateWsPort ?? resolvedPort;
|
|
133
|
-
const wsUrl = `ws://${formatHostForUrl(bindHost)}:${wsPortForUrl}${options.path ?? ""}`;
|
|
134
|
-
internal.wsEndpoint = { url: wsUrl };
|
|
135
|
-
if (options.onReady) await options.onReady({
|
|
136
|
-
origin,
|
|
137
|
-
port: resolvedPort,
|
|
138
|
-
app
|
|
139
|
-
});
|
|
140
|
-
function connectionMeta() {
|
|
141
|
-
const jsonSerializableMethods = [];
|
|
142
|
-
for (const def of rpcHost.definitions.values()) if (def.jsonSerializable === true) jsonSerializableMethods.push(def.name);
|
|
143
|
-
return {
|
|
144
|
-
backend: "websocket",
|
|
145
|
-
websocket: separateWsPort != null ? {
|
|
146
|
-
port: separateWsPort,
|
|
147
|
-
path: options.path
|
|
148
|
-
} : { path: options.path },
|
|
149
|
-
jsonSerializableMethods
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
return {
|
|
153
|
-
origin,
|
|
154
|
-
port: resolvedPort,
|
|
155
|
-
app,
|
|
156
|
-
ws,
|
|
157
|
-
rpcGroup,
|
|
158
|
-
connectionMeta,
|
|
159
|
-
async close() {
|
|
160
|
-
await closeWs();
|
|
161
|
-
if (ownsHttpServer) await new Promise((r) => httpServer.close(() => r()));
|
|
162
|
-
if (getInternalContext(context).wsEndpoint?.url === wsUrl) getInternalContext(context).wsEndpoint = void 0;
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
//#endregion
|
|
167
|
-
export { toDialableHost as a, normalizeHttpServerUrl as i, formatHostForUrl as n, isObject as r, startHttpAndWs as t };
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import { $ as DevframeRpcServerFunctions, Q as DevframeRpcClientFunctions, W as DevframeNodeRpcSession, _ as ConnectionMeta, b as DevframeNodeContext, p as DevframeAuthHandler } from "./devframe-mQ4qZAuo.mjs";
|
|
2
|
-
import { n as DevframeNodeRpcSessionMeta, r as WsOriginRegistry } from "./ws-server-uKQcClcJ.mjs";
|
|
3
|
-
import "./index-b64Uuhy2.mjs";
|
|
4
|
-
import { Peer } from "crossws";
|
|
5
|
-
import { BirpcGroup, EventOptions } from "birpc";
|
|
6
|
-
import { NodeAdapter } from "crossws/adapters/node";
|
|
7
|
-
import { Server } from "node:http";
|
|
8
|
-
import { H3 } from "h3";
|
|
9
|
-
//#region src/node/server.d.ts
|
|
10
|
-
interface StartHttpAndWsOptions {
|
|
11
|
-
context: DevframeNodeContext;
|
|
12
|
-
host?: string;
|
|
13
|
-
port: number;
|
|
14
|
-
/**
|
|
15
|
-
* Optional h3 app to mount on. When omitted a fresh one is created;
|
|
16
|
-
* when provided, callers can add their own routes (static handlers,
|
|
17
|
-
* auth middleware, etc.) first.
|
|
18
|
-
*/
|
|
19
|
-
app?: H3;
|
|
20
|
-
/**
|
|
21
|
-
* Bind the WS endpoint to a single upgrade route (e.g. `/__devframe_ws`) instead of
|
|
22
|
-
* claiming every upgrade on the port. This lets the socket share a server
|
|
23
|
-
* with other upgrade handlers (Vite HMR, a host framework's own sockets)
|
|
24
|
-
* and is what the SPA's `__connection.json` points at. When omitted, the WS
|
|
25
|
-
* server handles every upgrade on the port (legacy behaviour).
|
|
26
|
-
*/
|
|
27
|
-
path?: string;
|
|
28
|
-
/**
|
|
29
|
-
* Bind the WS endpoint on its own port instead of sharing the HTTP server's.
|
|
30
|
-
* The HTTP/SPA server still listens on `port`; the socket gets a dedicated
|
|
31
|
-
* `ws` server on `wsPort` (same `host`). Use this for the "different port"
|
|
32
|
-
* connection scenario. Ignored when a `server` is supplied.
|
|
33
|
-
*/
|
|
34
|
-
wsPort?: number;
|
|
35
|
-
/**
|
|
36
|
-
* Mount the WS endpoint onto an existing HTTP server, sharing its port,
|
|
37
|
-
* rather than creating and listening on a fresh one. Use this to embed
|
|
38
|
-
* devframe's RPC socket inside a host server (e.g. a Vite dev server) — pair
|
|
39
|
-
* it with `path` so it coexists with the host's routes. The caller owns the
|
|
40
|
-
* server's lifecycle: {@link StartedServer.close} detaches devframe's upgrade
|
|
41
|
-
* listener but leaves the host server running. When set, `host`/`port` are
|
|
42
|
-
* only used to report the resolved origin.
|
|
43
|
-
*/
|
|
44
|
-
server?: Server;
|
|
45
|
-
/**
|
|
46
|
-
* Authentication for the server:
|
|
47
|
-
*
|
|
48
|
-
* - `true` (default) — no gate; every registered method is callable
|
|
49
|
-
* regardless of trust (today's behavior, unchanged).
|
|
50
|
-
* - `false` — the RPC server is started without a trust handshake.
|
|
51
|
-
* Intended for single-user localhost tools where an auth round-trip
|
|
52
|
-
* would only get in the way. A noop `anonymous:devframe:auth` handler
|
|
53
|
-
* is registered so the browser client's unconditional handshake call
|
|
54
|
-
* succeeds and auto-trusts.
|
|
55
|
-
* - A {@link DevframeAuthHandler} (e.g. from
|
|
56
|
-
* `devframe/recipes/interactive-auth`'s `createInteractiveAuth`) —
|
|
57
|
-
* registers its `rpcFunctions`, wires its `authorize` as the resolver
|
|
58
|
-
* gate, and wires its `onConnect` on every new peer. This is the
|
|
59
|
-
* fully-authenticated server: an untrusted caller can only reach
|
|
60
|
-
* `anonymous:`-prefixed methods (see `isAnonymousRpcMethod`).
|
|
61
|
-
*/
|
|
62
|
-
auth?: boolean | DevframeAuthHandler;
|
|
63
|
-
/**
|
|
64
|
-
* Lower-level escape hatch: gate individual RPC calls by method name and
|
|
65
|
-
* session without a full {@link DevframeAuthHandler}. Ignored when `auth`
|
|
66
|
-
* is a handler object (its own `authorize` is used); combine with `auth:
|
|
67
|
-
* true` to layer a custom policy on top of an otherwise ungated server.
|
|
68
|
-
*/
|
|
69
|
-
authorize?: (methodName: string, session: DevframeNodeRpcSession) => boolean;
|
|
70
|
-
/**
|
|
71
|
-
* Called once per new WS connection, right after its session is created
|
|
72
|
-
* (before any RPC call is dispatched). Runs after the auth handler's own
|
|
73
|
-
* `onConnect` (when `auth` is a {@link DevframeAuthHandler}), so it can
|
|
74
|
-
* observe — but not override — the connect-time trust decision.
|
|
75
|
-
*/
|
|
76
|
-
onPeerConnect?: (peer: Peer, session: DevframeNodeRpcSession) => void;
|
|
77
|
-
/**
|
|
78
|
-
* Called once per closed WS connection, right after the transport's own
|
|
79
|
-
* disconnect bookkeeping runs. Unlike {@link onPeerConnect} this receives
|
|
80
|
-
* the raw session meta, not a wrapped session — by the time a peer
|
|
81
|
-
* disconnects there is no live RPC client left to attach.
|
|
82
|
-
*/
|
|
83
|
-
onPeerDisconnect?: (peer: Peer, meta: DevframeNodeRpcSessionMeta) => void;
|
|
84
|
-
/**
|
|
85
|
-
* Forwarded verbatim to the internal `createRpcServer`'s birpc
|
|
86
|
-
* `rpcOptions`, alongside the resolver `startHttpAndWs` installs for
|
|
87
|
-
* auth/session wiring. Use this so a host that owns its own structured
|
|
88
|
-
* diagnostics (e.g. a coded error reporter) keeps seeing RPC failures
|
|
89
|
-
* instead of them being silently absorbed by delegating to
|
|
90
|
-
* `startHttpAndWs`. Returning `true` from either callback suppresses
|
|
91
|
-
* birpc's own error response to the caller — see birpc's
|
|
92
|
-
* `EventOptions` for the full contract.
|
|
93
|
-
*/
|
|
94
|
-
rpcOptions?: Pick<EventOptions<DevframeRpcClientFunctions, DevframeRpcServerFunctions, false>, 'onFunctionError' | 'onGeneralError'>;
|
|
95
|
-
/**
|
|
96
|
-
* Extra origins to accept on the WS upgrade beyond the loopback default
|
|
97
|
-
* (`localhost`/`127.0.0.1`/`::1` and any `Origin`-less request from a
|
|
98
|
-
* native client). Add your LAN/tunnel origin here when reaching the tool
|
|
99
|
-
* from another host. Pass `false` to disable origin checking entirely
|
|
100
|
-
* (not recommended). Default: loopback-only.
|
|
101
|
-
*/
|
|
102
|
-
allowedOrigins?: readonly string[] | WsOriginRegistry | false;
|
|
103
|
-
/**
|
|
104
|
-
* Called once the WS server is bound so callers can mount static
|
|
105
|
-
* handlers whose origin depends on the resolved port, or print their
|
|
106
|
-
* own startup banner. Devframe does not print one itself.
|
|
107
|
-
*/
|
|
108
|
-
onReady?: (info: {
|
|
109
|
-
origin: string;
|
|
110
|
-
port: number;
|
|
111
|
-
app: H3;
|
|
112
|
-
}) => void | Promise<void>;
|
|
113
|
-
/**
|
|
114
|
-
* Called for any error the HTTP server devframe owns emits after it starts
|
|
115
|
-
* listening — e.g. a transient `EMFILE` while accepting a connection.
|
|
116
|
-
* Without it such an error has no listener and crashes the process.
|
|
117
|
-
*
|
|
118
|
-
* Applies only to a server devframe created itself. When `server` is
|
|
119
|
-
* supplied the caller owns that object and attaches to it directly, so
|
|
120
|
-
* devframe leaves its error handling alone.
|
|
121
|
-
*/
|
|
122
|
-
onServerError?: (error: Error) => void;
|
|
123
|
-
}
|
|
124
|
-
interface StartedServer {
|
|
125
|
-
/** Listening origin, e.g. `http://localhost:9999`. */
|
|
126
|
-
origin: string;
|
|
127
|
-
port: number;
|
|
128
|
-
app: H3;
|
|
129
|
-
/** The crossws node adapter driving the RPC socket (connected peers, pub/sub). */
|
|
130
|
-
ws: NodeAdapter;
|
|
131
|
-
rpcGroup: BirpcGroup<DevframeRpcClientFunctions, DevframeRpcServerFunctions, false>;
|
|
132
|
-
/**
|
|
133
|
-
* The {@link ConnectionMeta} descriptor for this server — the same shape
|
|
134
|
-
* a `__connection.json` route should serve so a devframe client's
|
|
135
|
-
* `resolveWsUrl` can dial back in. Reflects the `path` / `wsPort` this
|
|
136
|
-
* server was started with and the `jsonSerializable` methods currently
|
|
137
|
-
* registered on `context.rpc`.
|
|
138
|
-
*/
|
|
139
|
-
connectionMeta: () => ConnectionMeta;
|
|
140
|
-
close: () => Promise<void>;
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* Compose an h3 + WebSocket server for a devframe context. The RPC
|
|
144
|
-
* group is bound to `context.rpc.functions`; the WS endpoint lives on
|
|
145
|
-
* the same port as the HTTP server.
|
|
146
|
-
*/
|
|
147
|
-
declare function startHttpAndWs(options: StartHttpAndWsOptions): Promise<StartedServer>;
|
|
148
|
-
//#endregion
|
|
149
|
-
export { StartedServer as n, startHttpAndWs as r, StartHttpAndWsOptions as t };
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
|
-
//#region src/utils/simple-schema.d.ts
|
|
3
|
-
/**
|
|
4
|
-
* A tiny, zero-dependency [Standard Schema](https://standardschema.dev/)
|
|
5
|
-
* builder.
|
|
6
|
-
*
|
|
7
|
-
* ⚠️ **Discouraged for app code.** This is a deliberately minimal,
|
|
8
|
-
* best-effort validator that exists only so devframe's own first-party
|
|
9
|
-
* packages (recipes, built-in plugins) can declare `args`/`returns`/flag
|
|
10
|
-
* schemas without taking on a validator dependency. It implements a small
|
|
11
|
-
* subset of primitives and approximates refinements — it is not a
|
|
12
|
-
* general-purpose validator.
|
|
13
|
-
*
|
|
14
|
-
* For your own code, prefer a real Standard Schema validator — **valibot**,
|
|
15
|
-
* **zod**, or **arktype**. Devframe's RPC and CLI-flag layers accept any of
|
|
16
|
-
* them; install the one you like and use it directly:
|
|
17
|
-
*
|
|
18
|
-
* ```ts
|
|
19
|
-
* import * as v from 'valibot' // npm i valibot
|
|
20
|
-
*
|
|
21
|
-
* defineRpcFunction({
|
|
22
|
-
* name: 'greet',
|
|
23
|
-
* args: [v.object({ name: v.string() })],
|
|
24
|
-
* returns: v.string(),
|
|
25
|
-
* handler: ({ name }) => `hi ${name}`,
|
|
26
|
-
* })
|
|
27
|
-
* ```
|
|
28
|
-
*/
|
|
29
|
-
/**
|
|
30
|
-
* A Standard Schema produced by the {@link s} builder. It carries a
|
|
31
|
-
* duck-typed `type` marker (and `wrapped` for wrappers) alongside the
|
|
32
|
-
* standard `~standard` prop so the CLI-flags adapter can introspect the
|
|
33
|
-
* schema kind without importing any validator.
|
|
34
|
-
*/
|
|
35
|
-
interface SimpleSchema<Input, Output = Input> extends StandardSchemaV1<Input, Output> {
|
|
36
|
-
/** Schema kind marker, e.g. `'string'`, `'boolean'`, `'optional'`. */
|
|
37
|
-
readonly type: string;
|
|
38
|
-
/** Inner schema for wrapper kinds (`optional` / `nullable`). */
|
|
39
|
-
readonly wrapped?: StandardSchemaV1;
|
|
40
|
-
/** Optional human description (surfaced as CLI option help). */
|
|
41
|
-
readonly description?: string;
|
|
42
|
-
}
|
|
43
|
-
/** Any string. */
|
|
44
|
-
declare function string(): SimpleSchema<string>;
|
|
45
|
-
/** A finite number (rejects `NaN`). */
|
|
46
|
-
declare function number(): SimpleSchema<number>;
|
|
47
|
-
/** A boolean. */
|
|
48
|
-
declare function boolean(): SimpleSchema<boolean>;
|
|
49
|
-
/** `undefined` — mirrors valibot's `void`. */
|
|
50
|
-
declare function voidType(): SimpleSchema<void>;
|
|
51
|
-
/** `null`. */
|
|
52
|
-
declare function nullType(): SimpleSchema<null>;
|
|
53
|
-
/** One of a fixed set of literal values. */
|
|
54
|
-
declare function picklist<const T extends readonly (string | number | boolean)[]>(values: T): SimpleSchema<T[number]>;
|
|
55
|
-
/** A single literal value (string / number / boolean). */
|
|
56
|
-
declare function literal<const T extends string | number | boolean>(value: T): SimpleSchema<T>;
|
|
57
|
-
/** A value matching any one of the given schemas. */
|
|
58
|
-
declare function union<const T extends readonly StandardSchemaV1[]>(options: T): SimpleSchema<StandardSchemaV1.InferInput<T[number]>, StandardSchemaV1.InferOutput<T[number]>>;
|
|
59
|
-
/** A record with string keys whose values each satisfy the value schema. */
|
|
60
|
-
declare function record<V extends StandardSchemaV1>(_key: StandardSchemaV1, value: V): SimpleSchema<Record<string, StandardSchemaV1.InferInput<V>>, Record<string, StandardSchemaV1.InferOutput<V>>>;
|
|
61
|
-
/** An array whose every element satisfies the item schema. */
|
|
62
|
-
declare function array<T extends StandardSchemaV1>(item: T): SimpleSchema<StandardSchemaV1.InferInput<T>[], StandardSchemaV1.InferOutput<T>[]>;
|
|
63
|
-
/** Flatten an intersection into a single object literal for readable types. */
|
|
64
|
-
type Prettify<T> = { [K in keyof T]: T[K]; } & {};
|
|
65
|
-
/**
|
|
66
|
-
* Map a shape to its object type, turning fields whose type includes
|
|
67
|
-
* `undefined` (i.e. `optional()`) into optional keys — mirroring how
|
|
68
|
-
* valibot/zod render `optional` object entries.
|
|
69
|
-
*/
|
|
70
|
-
type InferField<T extends StandardSchemaV1, Mode extends 'input' | 'output'> = Mode extends 'input' ? StandardSchemaV1.InferInput<T> : StandardSchemaV1.InferOutput<T>;
|
|
71
|
-
type InferObject<T extends Record<string, StandardSchemaV1>, Mode extends 'input' | 'output'> = Prettify<{ [K in keyof T as undefined extends InferField<T[K], Mode> ? never : K]: InferField<T[K], Mode>; } & { [K in keyof T as undefined extends InferField<T[K], Mode> ? K : never]?: InferField<T[K], Mode>; }>;
|
|
72
|
-
/** An object whose known keys each satisfy their schema (extra keys are kept). */
|
|
73
|
-
declare function object<T extends Record<string, StandardSchemaV1>>(shape: T): SimpleSchema<InferObject<T, 'input'>, InferObject<T, 'output'>>;
|
|
74
|
-
/** Allow `undefined` in addition to the inner schema. */
|
|
75
|
-
declare function optional<T extends StandardSchemaV1>(inner: T): SimpleSchema<StandardSchemaV1.InferInput<T> | undefined, StandardSchemaV1.InferOutput<T> | undefined>;
|
|
76
|
-
/** Allow `null` in addition to the inner schema. */
|
|
77
|
-
declare function nullable<T extends StandardSchemaV1>(inner: T): SimpleSchema<StandardSchemaV1.InferInput<T> | null, StandardSchemaV1.InferOutput<T> | null>;
|
|
78
|
-
/** Attach a human-readable description (used for CLI option help). */
|
|
79
|
-
declare function describe<T extends SimpleSchema<any, any>>(schema: T, description: string): T;
|
|
80
|
-
/**
|
|
81
|
-
* Grouped access to every builder — `s.string()`, `s.object({ ... })`,
|
|
82
|
-
* `s.void()`, etc. Handy for a valibot-like `import { s } from
|
|
83
|
-
* 'devframe/utils/simple-schema'` call site.
|
|
84
|
-
*/
|
|
85
|
-
declare const s: {
|
|
86
|
-
readonly string: typeof string;
|
|
87
|
-
readonly number: typeof number;
|
|
88
|
-
readonly boolean: typeof boolean;
|
|
89
|
-
readonly void: typeof voidType;
|
|
90
|
-
readonly null: typeof nullType;
|
|
91
|
-
readonly literal: typeof literal;
|
|
92
|
-
readonly picklist: typeof picklist;
|
|
93
|
-
readonly union: typeof union;
|
|
94
|
-
readonly record: typeof record;
|
|
95
|
-
readonly array: typeof array;
|
|
96
|
-
readonly object: typeof object;
|
|
97
|
-
readonly optional: typeof optional;
|
|
98
|
-
readonly nullable: typeof nullable;
|
|
99
|
-
readonly describe: typeof describe;
|
|
100
|
-
};
|
|
101
|
-
//#endregion
|
|
102
|
-
export { literal as a, number as c, picklist as d, record as f, voidType as g, union as h, describe as i, object as l, string as m, array as n, nullType as o, s as p, boolean as r, nullable as s, SimpleSchema as t, optional as u };
|
package/dist/utils/promise.d.mts
DELETED
package/dist/utils/promise.mjs
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
//#region src/utils/promise.ts
|
|
2
|
-
function promiseWithResolver() {
|
|
3
|
-
let resolve;
|
|
4
|
-
let reject;
|
|
5
|
-
return {
|
|
6
|
-
promise: new Promise((_resolve, _reject) => {
|
|
7
|
-
resolve = _resolve;
|
|
8
|
-
reject = _reject;
|
|
9
|
-
}),
|
|
10
|
-
resolve,
|
|
11
|
-
reject
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
//#endregion
|
|
15
|
-
export { promiseWithResolver };
|
package/dist/utils/scope.d.mts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
//#region src/utils/scope.d.ts
|
|
2
|
-
/** Whether a name is already namespaced (contains a `:` separator). */
|
|
3
|
-
declare function isQualifiedName(name: string): boolean;
|
|
4
|
-
/**
|
|
5
|
-
* Prefix a bare name with `<namespace>:`. Names that already contain a
|
|
6
|
-
* `:` are returned unchanged, so callers can reference another scope's
|
|
7
|
-
* ids explicitly (e.g. `ctx.rpc.call('other-plugin:fn')`).
|
|
8
|
-
*/
|
|
9
|
-
declare function qualifyName(namespace: string, name: string): string;
|
|
10
|
-
//#endregion
|
|
11
|
-
export { isQualifiedName, qualifyName };
|
package/dist/utils/scope.mjs
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
//#region src/utils/scope.ts
|
|
2
|
-
/** Whether a name is already namespaced (contains a `:` separator). */
|
|
3
|
-
function isQualifiedName(name) {
|
|
4
|
-
return name.includes(":");
|
|
5
|
-
}
|
|
6
|
-
/**
|
|
7
|
-
* Prefix a bare name with `<namespace>:`. Names that already contain a
|
|
8
|
-
* `:` are returned unchanged, so callers can reference another scope's
|
|
9
|
-
* ids explicitly (e.g. `ctx.rpc.call('other-plugin:fn')`).
|
|
10
|
-
*/
|
|
11
|
-
function qualifyName(namespace, name) {
|
|
12
|
-
return isQualifiedName(name) ? name : `${namespace}:${name}`;
|
|
13
|
-
}
|
|
14
|
-
//#endregion
|
|
15
|
-
export { isQualifiedName, qualifyName };
|
|
@@ -3,9 +3,9 @@ import fs from "node:fs";
|
|
|
3
3
|
import process from "node:process";
|
|
4
4
|
import os from "node:os";
|
|
5
5
|
import path from "node:path";
|
|
6
|
+
import fs$1, { constants } from "node:fs/promises";
|
|
6
7
|
import { fileURLToPath } from "node:url";
|
|
7
8
|
import childProcess, { execFile } from "node:child_process";
|
|
8
|
-
import fs$1, { constants } from "node:fs/promises";
|
|
9
9
|
import { Buffer } from "node:buffer";
|
|
10
10
|
//#region ../../node_modules/.pnpm/is-docker@3.0.0/node_modules/is-docker/index.js
|
|
11
11
|
let isDockerCached;
|