devframe 0.9.8 → 0.9.9
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-BM3PdYli.mjs → _shared-C08SdQRl.mjs} +15 -4
- package/dist/{_shared-mtXpcJIv.d.mts → _shared-CK3czkH4.d.mts} +25 -2
- package/dist/adapters/build.d.mts +6 -6
- package/dist/adapters/build.mjs +32 -22
- package/dist/adapters/cac.d.mts +16 -1
- package/dist/adapters/cac.mjs +8 -7
- package/dist/adapters/dev.d.mts +13 -13
- package/dist/adapters/dev.mjs +2 -2
- package/dist/adapters/embedded.d.mts +1 -1
- package/dist/adapters/initiate.d.mts +28 -26
- package/dist/adapters/initiate.mjs +1 -1
- package/dist/adapters/mcp.d.mts +28 -14
- package/dist/adapters/mcp.mjs +75 -39
- package/dist/{agent-tool-name-EgfoFO8C.mjs → agent-tool-name-DGzeuWcO.mjs} +2 -2
- package/dist/cli/main.d.mts +1 -1
- package/dist/cli/main.mjs +41 -17
- package/dist/client/index.d.mts +36 -36
- package/dist/client/index.mjs +83 -51
- package/dist/{client-assets-C7SXgTWY.mjs → client-assets-DNdhagGm.mjs} +2 -2
- package/dist/constants.d.mts +8 -7
- package/dist/constants.mjs +7 -6
- package/dist/{context-CLF4-8Pp.d.mts → context-4AIVRLYF.d.mts} +158 -122
- package/dist/{context-omlma_1n.mjs → context-CwPUinjn.mjs} +126 -88
- package/dist/{context-KUqAfawQ.mjs → context-DIUvJW4D.mjs} +3 -3
- package/dist/{context-DftYyXaR.d.mts → context-rgBSPFHS.d.mts} +5 -5
- package/dist/{crypto-token-XCqTSMg9.mjs → crypto-token-TVbGGFuj.mjs} +1 -1
- package/dist/{dev-CzkPCJwi.mjs → dev-Eqq5PX0k.mjs} +37 -18
- package/dist/{diagnostics-BXWW3VK-.mjs → diagnostics-BMfN8mb1.mjs} +30 -17
- package/dist/{diagnostics-CD8nlgll.mjs → diagnostics-D0EVm5M6.mjs} +2 -2
- package/dist/{events-4daw0uK9.mjs → events-BV4Dj59a.mjs} +2 -2
- package/dist/{host-h3-fRbF9yor.mjs → host-h3-BJ4siyz7.mjs} +1 -1
- package/dist/in-page-channel/index.d.mts +14 -14
- package/dist/in-page-channel/index.mjs +63 -54
- package/dist/{index-BzyopqxV.d.mts → index-pIVt92jP.d.mts} +9 -9
- package/dist/{index-D3k0BIhe.d.mts → index-pKl67H6w.d.mts} +4 -4
- package/dist/index.d.mts +8 -8
- package/dist/index.mjs +2 -2
- package/dist/{instance-registry-BjlMQbFB.mjs → instance-registry-C7-41RSp.mjs} +8 -8
- package/dist/{instance-shell-Tcp5hGoq.d.mts → instance-shell-7Z52PE4_.d.mts} +18 -18
- package/dist/{instance-shell-CpVW4zG0.mjs → instance-shell-cdVETpfz.mjs} +227 -58
- package/dist/internal/index.d.mts +40 -23
- package/dist/internal/index.mjs +10 -10
- 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 +2 -2
- package/dist/node/index.d.mts +5 -5
- package/dist/node/index.mjs +2 -2
- package/dist/{nostics-SPGDgHEP.d.mts → nostics-0sKe5HIj.d.mts} +2 -2
- package/dist/{nostics-CzECRXpE.mjs → nostics-D0PvLZsn.mjs} +1 -1
- package/dist/origin-DGDH8BI9.d.mts +45 -0
- package/dist/origin-DZit9g29.mjs +80 -0
- package/dist/recipes/common-rpc-functions.d.mts +5 -5
- package/dist/recipes/common-rpc-functions.mjs +3 -3
- package/dist/recipes/interactive-auth.d.mts +6 -6
- package/dist/recipes/interactive-auth.mjs +6 -6
- package/dist/{remote-assets-DezQmPQU.mjs → remote-assets-BIFWOlBW.mjs} +26 -6
- package/dist/{remote-assets-B13_vRkJ.d.mts → remote-assets-eBvSKZMS.d.mts} +7 -7
- package/dist/{revoke-COLW0cOi.mjs → revoke-cqztiCX4.mjs} +1 -1
- package/dist/rpc/dump.d.mts +2 -11
- package/dist/rpc/dump.mjs +1 -1
- package/dist/rpc/index.d.mts +2 -2
- package/dist/rpc/index.mjs +3 -3
- package/dist/rpc/transports/sse-client.d.mts +1 -1
- package/dist/rpc/transports/sse-client.mjs +30 -14
- package/dist/rpc/transports/sse-server.d.mts +4 -4
- package/dist/rpc/transports/sse-server.mjs +7 -7
- package/dist/rpc/transports/ws-bun.d.mts +5 -5
- package/dist/rpc/transports/ws-bun.mjs +8 -2
- package/dist/rpc/transports/ws-client.d.mts +1 -1
- package/dist/rpc/transports/ws-client.mjs +2 -2
- package/dist/rpc/transports/ws-deno.d.mts +4 -4
- package/dist/rpc/transports/ws-deno.mjs +8 -2
- package/dist/rpc/transports/ws-server.d.mts +2 -1
- package/dist/rpc/transports/ws-server.mjs +232 -1
- package/dist/{rpc-core-B3W3z9ff.d.mts → rpc-core-Ceu6AUz8.d.mts} +4 -4
- package/dist/{rpc-core-DlHd276T.mjs → rpc-core-DVQ7xi89.mjs} +14 -2
- package/dist/{serialization-BGzEwAdr.mjs → serialization-DTZnPQ1-.mjs} +20 -18
- package/dist/{services-install-CqqQVls5.mjs → services-install-P_DV7VYL.mjs} +32 -21
- package/dist/session-DPfj6zQG.mjs +16 -0
- package/dist/{shared-state--sduc6Xi.mjs → shared-state-CaxB1q0h.mjs} +2 -2
- package/dist/{simple-schema-DQPZrAaZ.mjs → simple-schema-Bi40l-P6.mjs} +2 -2
- package/dist/{sse-client-DwX021ST.d.mts → sse-client-BQ4jS3eO.d.mts} +4 -4
- package/dist/{state-CK9LjrnT.mjs → state-CeQQWzM-.mjs} +4 -4
- package/dist/{static-DV_qUSRS.mjs → static-DZ8P2Kn7.mjs} +130 -135
- package/dist/{storage-BXNVhKyR.mjs → storage-Dccf_IyD.mjs} +1 -1
- package/dist/types/index.d.mts +6 -6
- package/dist/{types-CMdPYhOx.d.mts → types-Dq4i156u.d.mts} +17 -17
- package/dist/utils/agent-tool-name.d.mts +2 -2
- package/dist/utils/agent-tool-name.mjs +2 -2
- package/dist/utils/colors.d.mts +1 -1
- package/dist/utils/crypto-token.d.mts +1 -1
- package/dist/utils/crypto-token.mjs +1 -1
- package/dist/utils/events.d.mts +1 -1
- package/dist/utils/nostics.d.mts +1 -1
- package/dist/utils/nostics.mjs +1 -1
- package/dist/utils/open.mjs +1 -1
- package/dist/utils/origin.d.mts +2 -0
- package/dist/utils/origin.mjs +80 -0
- package/dist/utils/remote-assets.d.mts +2 -2
- package/dist/utils/remote-assets.mjs +1 -1
- package/dist/utils/serve-static.d.mts +4 -4
- package/dist/utils/serve-static.mjs +56 -19
- package/dist/utils/shared-state.d.mts +1 -1
- package/dist/utils/shared-state.mjs +1 -1
- package/dist/utils/simple-schema.d.mts +5 -5
- package/dist/utils/simple-schema.mjs +2 -2
- package/dist/utils/streaming-channel.d.mts +1 -1
- package/dist/utils/streaming-channel.mjs +2 -2
- package/dist/utils/when.d.mts +5 -5
- package/dist/{validation-YrZH6atx.mjs → validation-BOy8IoFZ.mjs} +2 -2
- package/dist/{wire-codec-0K-o5MYW.mjs → wire-codec-dcCeXcSo.mjs} +3 -3
- package/dist/{ws-client-7_lZi-B9.d.mts → ws-client-Xpxt0oPA.d.mts} +3 -3
- package/dist/{ws-server-VyHlanzy.d.mts → ws-server-D2nv68Hg.d.mts} +13 -37
- package/package.json +2 -1
- package/dist/ws-server-Y_AumUQH.mjs +0 -294
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { i as defineDiagnostics } from "./nostics-
|
|
2
|
-
import { t as diagnostics } from "./diagnostics-
|
|
1
|
+
import { i as defineDiagnostics } from "./nostics-D0PvLZsn.mjs";
|
|
2
|
+
import { t as diagnostics } from "./diagnostics-D0EVm5M6.mjs";
|
|
3
3
|
import { RpcFunctionsCollectorBase } from "./rpc/index.mjs";
|
|
4
4
|
import { defineRpcFunction } from "./index.mjs";
|
|
5
|
-
import { t as DEVFRAME_EVENTS } from "./events-
|
|
5
|
+
import { t as DEVFRAME_EVENTS } from "./events-BV4Dj59a.mjs";
|
|
6
6
|
import { DEVFRAME_SERVICES_STATE_KEY } from "./constants.mjs";
|
|
7
|
-
import { t as diagnostics$1 } from "./diagnostics-
|
|
8
|
-
import { a as DevframeAgentHost, i as satisfiesVersionRange, n as expandResolveFrom, r as importServicePackage, s as createEventEmitter, t as deepMergeOptionSets } from "./services-install-
|
|
9
|
-
import { n as createDebug, t as resolveStaticAssetsSource } from "./remote-assets-
|
|
10
|
-
import { t as createStorage } from "./storage-
|
|
7
|
+
import { t as diagnostics$1 } from "./diagnostics-BMfN8mb1.mjs";
|
|
8
|
+
import { a as DevframeAgentHost, i as satisfiesVersionRange, n as expandResolveFrom, r as importServicePackage, s as createEventEmitter, t as deepMergeOptionSets } from "./services-install-P_DV7VYL.mjs";
|
|
9
|
+
import { n as createDebug, t as resolveStaticAssetsSource } from "./remote-assets-BIFWOlBW.mjs";
|
|
10
|
+
import { t as createStorage } from "./storage-Dccf_IyD.mjs";
|
|
11
11
|
import { createSharedState } from "devframe/utils/shared-state";
|
|
12
12
|
import process from "node:process";
|
|
13
13
|
import { join } from "pathe";
|
|
@@ -17,6 +17,10 @@ var DevframeDiagnosticsHost = class {
|
|
|
17
17
|
context;
|
|
18
18
|
_registry = {};
|
|
19
19
|
logger = new Proxy({}, { get: (_, code) => this._registry[code] });
|
|
20
|
+
/**
|
|
21
|
+
* Already pre-wires devframe's ANSI console reporter, so no extra merging
|
|
22
|
+
* needed here, the host's `defineDiagnostics` just is the shared one.
|
|
23
|
+
*/
|
|
20
24
|
defineDiagnostics = defineDiagnostics;
|
|
21
25
|
constructor(context, initialDefinitions = []) {
|
|
22
26
|
this.context = context;
|
|
@@ -123,6 +127,10 @@ function createRpcSharedStateServerHost(rpc) {
|
|
|
123
127
|
if (!sharedState.has(key)) return void 0;
|
|
124
128
|
return (await host.get(key)).value();
|
|
125
129
|
},
|
|
130
|
+
/**
|
|
131
|
+
* Pre-compute snapshots for the build-mode static dump so the SPA
|
|
132
|
+
* can read them without a live server.
|
|
133
|
+
*/
|
|
126
134
|
dump: () => ({ inputs: host.keys().map((key) => [key]) })
|
|
127
135
|
});
|
|
128
136
|
rpc.register({
|
|
@@ -158,7 +166,7 @@ var StreamClosedError = class extends Error {
|
|
|
158
166
|
name = "StreamClosedError";
|
|
159
167
|
};
|
|
160
168
|
/**
|
|
161
|
-
* Build a server-side stream sink. RPC-agnostic
|
|
169
|
+
* Build a server-side stream sink. RPC-agnostic; the RPC host wires
|
|
162
170
|
* `events.on('chunk' | 'end')` to broadcast, and reads `buffer` to replay
|
|
163
171
|
* for late or reconnecting subscribers.
|
|
164
172
|
*/
|
|
@@ -229,7 +237,7 @@ function createStreamSink(options = {}) {
|
|
|
229
237
|
};
|
|
230
238
|
}
|
|
231
239
|
/**
|
|
232
|
-
* Build a client-side stream reader. RPC-agnostic
|
|
240
|
+
* Build a client-side stream reader. RPC-agnostic; the RPC host calls
|
|
233
241
|
* `_push(seq, chunk)` on each incoming chunk and `_end(error?)` on the
|
|
234
242
|
* terminal frame. Consumers iterate with `for await` or pipe `readable`.
|
|
235
243
|
*/
|
|
@@ -412,7 +420,7 @@ function streamKey(channel, id) {
|
|
|
412
420
|
}
|
|
413
421
|
/**
|
|
414
422
|
* Build the server-side streaming host. Mirrors the layout of
|
|
415
|
-
* `createRpcSharedStateServerHost
|
|
423
|
+
* `createRpcSharedStateServerHost`: registers a fixed set of internal
|
|
416
424
|
* RPC methods (`subscribe` / `unsubscribe` / `cancel`) once, then per-channel
|
|
417
425
|
* state lives in a `Map<channelName, ChannelState>`.
|
|
418
426
|
*/
|
|
@@ -573,6 +581,10 @@ function createRpcStreamingServerHost(rpc) {
|
|
|
573
581
|
name,
|
|
574
582
|
options: {
|
|
575
583
|
replayWindow,
|
|
584
|
+
/**
|
|
585
|
+
* Default to a 30-second hold when replay is enabled so late
|
|
586
|
+
* subscribers can join after the producer finishes.
|
|
587
|
+
*/
|
|
576
588
|
closedStreamRetention: opts.closedStreamRetention ?? (replayWindow > 0 ? 3e4 : 0)
|
|
577
589
|
},
|
|
578
590
|
streams: /* @__PURE__ */ new Map(),
|
|
@@ -669,37 +681,39 @@ function createRpcStreamingServerHost(rpc) {
|
|
|
669
681
|
id: key.slice(sepIdx + 1)
|
|
670
682
|
};
|
|
671
683
|
}
|
|
684
|
+
function dropOutboundSubscriptions(meta) {
|
|
685
|
+
if (!meta.subscribedStreams) return;
|
|
686
|
+
for (const key of meta.subscribedStreams) {
|
|
687
|
+
const parsed = parseKey(key);
|
|
688
|
+
const state = parsed && channels.get(parsed.channelName);
|
|
689
|
+
const record = state && parsed && state.streams.get(parsed.id);
|
|
690
|
+
if (!parsed || !state || !record) continue;
|
|
691
|
+
record.subscribers.delete(meta);
|
|
692
|
+
if (record.subscribers.size === 0 && !record.sink.closed) record.sink.abort("all subscribers disconnected");
|
|
693
|
+
maybeFreeStream(state, parsed.id);
|
|
694
|
+
}
|
|
695
|
+
meta.subscribedStreams.clear();
|
|
696
|
+
}
|
|
697
|
+
function endInboundUploads(meta) {
|
|
698
|
+
if (!meta.uploadingStreams) return;
|
|
699
|
+
for (const key of meta.uploadingStreams) {
|
|
700
|
+
const parsed = parseKey(key);
|
|
701
|
+
const state = parsed && channels.get(parsed.channelName);
|
|
702
|
+
const record = state && parsed && state.inbound.get(parsed.id);
|
|
703
|
+
if (!parsed || !state || !record) continue;
|
|
704
|
+
record.reader._end({
|
|
705
|
+
name: "UploadDisconnected",
|
|
706
|
+
message: "Uploader disconnected before completing the stream"
|
|
707
|
+
});
|
|
708
|
+
state.inbound.delete(parsed.id);
|
|
709
|
+
}
|
|
710
|
+
meta.uploadingStreams.clear();
|
|
711
|
+
}
|
|
672
712
|
return {
|
|
673
713
|
create: createChannel,
|
|
674
714
|
_onSessionDisconnected(meta) {
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
const parsed = parseKey(key);
|
|
678
|
-
if (!parsed) continue;
|
|
679
|
-
const state = channels.get(parsed.channelName);
|
|
680
|
-
const record = state?.streams.get(parsed.id);
|
|
681
|
-
if (!state || !record) continue;
|
|
682
|
-
record.subscribers.delete(meta);
|
|
683
|
-
if (record.subscribers.size === 0 && !record.sink.closed) record.sink.abort("all subscribers disconnected");
|
|
684
|
-
maybeFreeStream(state, parsed.id);
|
|
685
|
-
}
|
|
686
|
-
meta.subscribedStreams.clear();
|
|
687
|
-
}
|
|
688
|
-
if (meta.uploadingStreams) {
|
|
689
|
-
for (const key of meta.uploadingStreams) {
|
|
690
|
-
const parsed = parseKey(key);
|
|
691
|
-
if (!parsed) continue;
|
|
692
|
-
const state = channels.get(parsed.channelName);
|
|
693
|
-
const record = state?.inbound.get(parsed.id);
|
|
694
|
-
if (!state || !record) continue;
|
|
695
|
-
record.reader._end({
|
|
696
|
-
name: "UploadDisconnected",
|
|
697
|
-
message: "Uploader disconnected before completing the stream"
|
|
698
|
-
});
|
|
699
|
-
state.inbound.delete(parsed.id);
|
|
700
|
-
}
|
|
701
|
-
meta.uploadingStreams.clear();
|
|
702
|
-
}
|
|
715
|
+
dropOutboundSubscriptions(meta);
|
|
716
|
+
endInboundUploads(meta);
|
|
703
717
|
}
|
|
704
718
|
};
|
|
705
719
|
}
|
|
@@ -784,13 +798,24 @@ function validateServiceDefinition(def) {
|
|
|
784
798
|
});
|
|
785
799
|
}
|
|
786
800
|
/**
|
|
801
|
+
* Merge every installer's option set in declaration order (the default
|
|
802
|
+
* deep-merge unions arrays and lets later scalars win; a service may override
|
|
803
|
+
* with its own `mergeOptions`).
|
|
804
|
+
*/
|
|
805
|
+
function mergeInstallerOptions(def, entries) {
|
|
806
|
+
const sets = entries.map((entry) => entry.input.options).filter((options) => options !== void 0);
|
|
807
|
+
if (def.mergeOptions) return def.mergeOptions(sets);
|
|
808
|
+
return sets.length > 0 ? deepMergeOptionSets(sets) : void 0;
|
|
809
|
+
}
|
|
810
|
+
/**
|
|
787
811
|
* Cross-plugin service registry (see `types/services.ts` for the contract).
|
|
788
812
|
* Values are held per context instance; `whenAvailable` subscriptions make
|
|
789
|
-
* the mechanism
|
|
813
|
+
* the mechanism work regardless of setup ordering between provider and
|
|
814
|
+
* consumer.
|
|
790
815
|
*
|
|
791
816
|
* On top of the in-process `provide`/`get` tier, this host implements the
|
|
792
817
|
* **wire-service** lifecycle: `install()` queues definitions/descriptors,
|
|
793
|
-
* `ready()` fires the collect-then-setup barrier
|
|
818
|
+
* `ready()` fires the collect-then-setup barrier: importing descriptor
|
|
794
819
|
* packages, merging option sets per service, constructing each service once,
|
|
795
820
|
* providing its node API under the package name, and advertising it to
|
|
796
821
|
* clients through the `devframe:services` shared state.
|
|
@@ -887,42 +912,68 @@ var DevframeServicesHostImpl = class {
|
|
|
887
912
|
}
|
|
888
913
|
let def = entries.filter((entry) => isServiceDefinition(entry.input))[0]?.input;
|
|
889
914
|
if (!def) {
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
915
|
+
def = await this.importServiceDefinition(pkg, entries);
|
|
916
|
+
if (!def) return void 0;
|
|
917
|
+
}
|
|
918
|
+
this.checkVersionRanges(pkg, def, entries);
|
|
919
|
+
const options = mergeInstallerOptions(def, entries);
|
|
920
|
+
if (!this.context) throw diagnostics$1.DF0070({
|
|
921
|
+
package: pkg,
|
|
922
|
+
reason: "this services host has no node context to install into"
|
|
923
|
+
});
|
|
924
|
+
debug("installing service %s@%s (scope %s)", def.package, def.version, def.scope);
|
|
925
|
+
const scoped = this.context.scope(def.scope);
|
|
926
|
+
const api = await def.setup(scoped, options === void 0 ? {} : { options });
|
|
927
|
+
this.installed.set(def.package, api);
|
|
928
|
+
this.provide(def.package, api);
|
|
929
|
+
await this.advertise(def);
|
|
930
|
+
return api;
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* Import a descriptor-only package, run its factory, and validate the
|
|
934
|
+
* resulting definition. Returns `undefined` when an optional package can't
|
|
935
|
+
* be imported (the install is skipped); throws for a required one.
|
|
936
|
+
*/
|
|
937
|
+
async importServiceDefinition(pkg, entries) {
|
|
938
|
+
const required = entries.map((entry) => entry.input).some((descriptor) => descriptor.required === true);
|
|
939
|
+
const cwd = this.context?.cwd ?? process.cwd();
|
|
940
|
+
const resolveFroms = [
|
|
941
|
+
...entries.map((entry) => entry.resolveFrom && expandResolveFrom(entry.resolveFrom, cwd)),
|
|
942
|
+
this.context?.workspaceRoot,
|
|
943
|
+
cwd
|
|
944
|
+
];
|
|
945
|
+
let mod;
|
|
946
|
+
try {
|
|
947
|
+
mod = await importServicePackage(pkg, resolveFroms);
|
|
948
|
+
} catch (error) {
|
|
949
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
950
|
+
if (required) throw diagnostics$1.DF0067({
|
|
917
951
|
package: pkg,
|
|
918
|
-
reason
|
|
952
|
+
reason,
|
|
953
|
+
cause: error
|
|
919
954
|
});
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
package: pkg
|
|
923
|
-
};
|
|
924
|
-
validateServiceDefinition(def);
|
|
955
|
+
debug("optional service %s not importable, skipping: %s", pkg, reason);
|
|
956
|
+
return;
|
|
925
957
|
}
|
|
958
|
+
const factory = mod.default;
|
|
959
|
+
if (typeof factory !== "function") throw diagnostics$1.DF0070({
|
|
960
|
+
package: pkg,
|
|
961
|
+
reason: "its default export is not a factory function"
|
|
962
|
+
});
|
|
963
|
+
let def = await factory();
|
|
964
|
+
if (!def || typeof def.setup !== "function") throw diagnostics$1.DF0070({
|
|
965
|
+
package: pkg,
|
|
966
|
+
reason: "its factory did not return a definition with a `setup` function"
|
|
967
|
+
});
|
|
968
|
+
if (typeof def.package !== "string" || def.package.length === 0) def = {
|
|
969
|
+
...def,
|
|
970
|
+
package: pkg
|
|
971
|
+
};
|
|
972
|
+
validateServiceDefinition(def);
|
|
973
|
+
return def;
|
|
974
|
+
}
|
|
975
|
+
/** Version-range checks against the resolved definition's real version. */
|
|
976
|
+
checkVersionRanges(pkg, def, entries) {
|
|
926
977
|
for (const entry of entries) {
|
|
927
978
|
const descriptor = entry.input;
|
|
928
979
|
if (isServiceDefinition(entry.input) || typeof descriptor.version !== "string") continue;
|
|
@@ -938,19 +989,6 @@ var DevframeServicesHostImpl = class {
|
|
|
938
989
|
installed: def.version
|
|
939
990
|
});
|
|
940
991
|
}
|
|
941
|
-
const sets = entries.map((entry) => entry.input.options).filter((options) => options !== void 0);
|
|
942
|
-
const options = def.mergeOptions ? def.mergeOptions(sets) : sets.length > 0 ? deepMergeOptionSets(sets) : void 0;
|
|
943
|
-
if (!this.context) throw diagnostics$1.DF0070({
|
|
944
|
-
package: pkg,
|
|
945
|
-
reason: "this services host has no node context to install into"
|
|
946
|
-
});
|
|
947
|
-
debug("installing service %s@%s (scope %s)", def.package, def.version, def.scope);
|
|
948
|
-
const scoped = this.context.scope(def.scope);
|
|
949
|
-
const api = await def.setup(scoped, options === void 0 ? {} : { options });
|
|
950
|
-
this.installed.set(def.package, api);
|
|
951
|
-
this.provide(def.package, api);
|
|
952
|
-
await this.advertise(def);
|
|
953
|
-
return api;
|
|
954
992
|
}
|
|
955
993
|
advertisementState() {
|
|
956
994
|
return this.context.rpc.sharedState.get(DEVFRAME_SERVICES_STATE_KEY, { initialValue: {} });
|
|
@@ -1019,7 +1057,7 @@ const agentListResources = defineRpcFunction({
|
|
|
1019
1057
|
/**
|
|
1020
1058
|
* Built-in agent introspection RPC functions. Registered automatically
|
|
1021
1059
|
* by `createHostContext`. Not themselves agent-exposed (no `agent`
|
|
1022
|
-
* field)
|
|
1060
|
+
* field); they power the MCP adapter and any future agent CLI.
|
|
1023
1061
|
*/
|
|
1024
1062
|
const BUILTIN_AGENT_RPC = [
|
|
1025
1063
|
defineRpcFunction({
|
|
@@ -1169,7 +1207,7 @@ function createScopedNodeContext(context, namespace) {
|
|
|
1169
1207
|
* Framework- and build-tool-agnostic core of the Devframe node context.
|
|
1170
1208
|
* Wires the RPC host, view (HTTP file-serving) host, diagnostics, and
|
|
1171
1209
|
* agent subsystems. Host adapters can wrap this to augment `ctx` with
|
|
1172
|
-
* extra surfaces
|
|
1210
|
+
* extra surfaces; for example, `@vitejs/devtools-kit`'s
|
|
1173
1211
|
* `createKitContext` attaches `docks`, `terminals`, `messages`, and
|
|
1174
1212
|
* `commands` when mounted into Vite DevTools.
|
|
1175
1213
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { n as randomToken } from "./crypto-token-
|
|
2
|
-
import { t as createStorage } from "./storage-
|
|
3
|
-
import { n as revokeAuthToken, t as revokeActiveConnectionsForToken } from "./revoke-
|
|
1
|
+
import { n as randomToken } from "./crypto-token-TVbGGFuj.mjs";
|
|
2
|
+
import { t as createStorage } from "./storage-Dccf_IyD.mjs";
|
|
3
|
+
import { n as revokeAuthToken, t as revokeActiveConnectionsForToken } from "./revoke-cqztiCX4.mjs";
|
|
4
4
|
import { join } from "pathe";
|
|
5
5
|
//#region src/node/hub-internals/context.ts
|
|
6
6
|
const internalContextMap = /* @__PURE__ */ new WeakMap();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { k as SharedState, o as DevframeNodeContext } from "./context-
|
|
1
|
+
import { k as SharedState, o as DevframeNodeContext } from "./context-4AIVRLYF.mjs";
|
|
2
2
|
//#region src/node/hub-internals/context.d.ts
|
|
3
3
|
interface InternalAnonymousAuthStorage {
|
|
4
4
|
trusted: Record<string, {
|
|
@@ -10,7 +10,7 @@ interface InternalAnonymousAuthStorage {
|
|
|
10
10
|
}
|
|
11
11
|
interface RemoteTokenRecord {
|
|
12
12
|
dockId: string;
|
|
13
|
-
/** Dock URL origin
|
|
13
|
+
/** Dock URL origin, matched against WS handshake `Origin` header when `originLock` is on. */
|
|
14
14
|
origin: string;
|
|
15
15
|
originLock: boolean;
|
|
16
16
|
}
|
|
@@ -24,7 +24,7 @@ interface DevframeInternalContext {
|
|
|
24
24
|
*/
|
|
25
25
|
revokeAuthToken: (token: string) => Promise<void>;
|
|
26
26
|
/**
|
|
27
|
-
* Session-only tokens issued to remote-UI iframe docks. Not persisted
|
|
27
|
+
* Session-only tokens issued to remote-UI iframe docks. Not persisted;
|
|
28
28
|
* regenerated on every dev-server restart.
|
|
29
29
|
*/
|
|
30
30
|
remoteTokens: Map<string, RemoteTokenRecord>;
|
|
@@ -45,8 +45,8 @@ interface DevframeInternalContext {
|
|
|
45
45
|
url: string;
|
|
46
46
|
};
|
|
47
47
|
/**
|
|
48
|
-
* Set {@link DevframeInternalContext.wsEndpoint} and notify subscribers
|
|
49
|
-
*
|
|
48
|
+
* Set {@link DevframeInternalContext.wsEndpoint} and notify subscribers.
|
|
49
|
+
* The WS-binding tiers (side-car, shared-server, and the `unbound` tier's
|
|
50
50
|
* `attach()`) call this once the socket is bound (or `undefined` once torn
|
|
51
51
|
* down) instead of assigning the field directly, so anything that already
|
|
52
52
|
* projected the endpoint (a hub's remote-dock URLs, registered before an
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
const HEX = "0123456789abcdef";
|
|
3
3
|
/**
|
|
4
4
|
* Generate a high-entropy, URL-safe (hex) random token suitable for use as a
|
|
5
|
-
* bearer credential
|
|
5
|
+
* bearer credential, e.g. the persistent client auth token or an ephemeral
|
|
6
6
|
* remote-dock token. Defaults to 16 bytes (128 bits) of entropy.
|
|
7
7
|
*/
|
|
8
8
|
function randomToken(byteLength = 16) {
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { t as resolveClientAssets } from "./client-assets-
|
|
1
|
+
import { t as resolveClientAssets } from "./client-assets-DNdhagGm.mjs";
|
|
2
2
|
import { DEVFRAME_CONNECTION_META_FILENAME } from "./constants.mjs";
|
|
3
|
-
import { t as diagnostics } from "./diagnostics-
|
|
4
|
-
import { t as createHostContext } from "./context-
|
|
5
|
-
import { t as resolveStaticAssetsSource } from "./remote-assets-
|
|
6
|
-
import { i as
|
|
7
|
-
import { t as createH3DevframeHost } from "./host-h3-
|
|
8
|
-
import { a as importRuntimeModule, i as normalizeHttpServerUrl, n as resolveInstanceRegister, t as createInstanceShell } from "./instance-shell-
|
|
3
|
+
import { t as diagnostics } from "./diagnostics-BMfN8mb1.mjs";
|
|
4
|
+
import { t as createHostContext } from "./context-CwPUinjn.mjs";
|
|
5
|
+
import { t as resolveStaticAssetsSource } from "./remote-assets-BIFWOlBW.mjs";
|
|
6
|
+
import { i as resolveMcpConfig, n as resolveBasePath, r as resolveDevServerPort, t as normalizeBasePath } from "./_shared-C08SdQRl.mjs";
|
|
7
|
+
import { t as createH3DevframeHost } from "./host-h3-BJ4siyz7.mjs";
|
|
8
|
+
import { a as importRuntimeModule, i as normalizeHttpServerUrl, n as resolveInstanceRegister, t as createInstanceShell } from "./instance-shell-cdVETpfz.mjs";
|
|
9
9
|
import { open } from "./utils/open.mjs";
|
|
10
10
|
import { mountStaticHandler } from "./utils/serve-static.mjs";
|
|
11
11
|
import { createServer } from "node:http";
|
|
12
12
|
import process from "node:process";
|
|
13
13
|
import { resolve } from "pathe";
|
|
14
|
-
import { joinURL, withBase } from "ufo";
|
|
14
|
+
import { joinURL, withBase, withoutLeadingSlash } from "ufo";
|
|
15
15
|
import { H3, toNodeHandler } from "h3";
|
|
16
16
|
//#region src/adapters/initiate.ts
|
|
17
17
|
const INSTANCE_INTERNALS = /* @__PURE__ */ new WeakMap();
|
|
@@ -20,7 +20,7 @@ function getInstanceInternals(handler) {
|
|
|
20
20
|
return INSTANCE_INTERNALS.get(handler) ?? {};
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
|
-
* Serve a devframe through one framework-agnostic, web-standard handler
|
|
23
|
+
* Serve a devframe through one framework-agnostic, web-standard handler:
|
|
24
24
|
* the SPA, `__connection.json` discovery, the WebSocket RPC endpoint, the
|
|
25
25
|
* auth gate, and the optional MCP route, all under a single mount base.
|
|
26
26
|
* Mount `handler` on any framework's catch-all route (or `nodeMiddleware` on
|
|
@@ -28,10 +28,10 @@ function getInstanceInternals(handler) {
|
|
|
28
28
|
*
|
|
29
29
|
* The factory is synchronous and kicks off initialization eagerly;
|
|
30
30
|
* `handler`/`nodeMiddleware` await readiness internally. Nothing binds a port
|
|
31
|
-
* on its own: the WebSocket resolves in precedence order
|
|
31
|
+
* on its own: the WebSocket resolves in precedence order: `ws.port` (pinned
|
|
32
32
|
* side-car) > `server` (shared upgrade at `<base>__ws`) > `ws.sidecar`
|
|
33
33
|
* (auto-port side-car) > the host driving upgrades itself through
|
|
34
|
-
* {@link DevframeInstance.attach}
|
|
34
|
+
* {@link DevframeInstance.attach}. Meanwhile `ws.url`, when set, overrides the
|
|
35
35
|
* advertised* endpoint (the tunnel pattern) and on its own hands the whole
|
|
36
36
|
* transport to an external server. `__connection.json` reflects whichever
|
|
37
37
|
* combination is active.
|
|
@@ -46,6 +46,10 @@ function initDevframe(def, options) {
|
|
|
46
46
|
app,
|
|
47
47
|
host,
|
|
48
48
|
origin: options.origin,
|
|
49
|
+
/**
|
|
50
|
+
* Auth resolution mirrors `createDevServer`: gate by default, explicit
|
|
51
|
+
* `false` opts out, a handler object installs a custom scheme.
|
|
52
|
+
*/
|
|
49
53
|
auth: options.auth !== void 0 ? options.auth : def.cli?.auth,
|
|
50
54
|
server: options.server,
|
|
51
55
|
ws: options.ws ?? def.cli?.ws,
|
|
@@ -84,12 +88,13 @@ function initDevframe(def, options) {
|
|
|
84
88
|
for (const input of def.services ?? []) context.services.install(input, { resolveFrom: def.importMetaUrl });
|
|
85
89
|
await context.services.ready();
|
|
86
90
|
await def.setup(context, setupInfo);
|
|
87
|
-
const
|
|
88
|
-
|
|
91
|
+
const mcpConfig = resolveMcpConfig(options.mcp ?? def.cli?.mcp);
|
|
92
|
+
let mcpMeta;
|
|
89
93
|
let mcpDispose;
|
|
90
|
-
if (
|
|
91
|
-
const
|
|
92
|
-
|
|
94
|
+
if (mcpConfig) {
|
|
95
|
+
const mcpRoute = withoutLeadingSlash(mcpConfig.path ?? "__mcp");
|
|
96
|
+
mcpMeta = { path: mcpRoute };
|
|
97
|
+
const mcpPath = joinURL(base, mcpRoute);
|
|
93
98
|
let mountMcpHttp;
|
|
94
99
|
try {
|
|
95
100
|
({mountMcpHttp} = await importRuntimeModule("devframe/adapters/mcp"));
|
|
@@ -105,6 +110,7 @@ function initDevframe(def, options) {
|
|
|
105
110
|
serverName: `${def.id} (devframe)`,
|
|
106
111
|
serverVersion: def.version ?? "0.0.0",
|
|
107
112
|
exposeSharedState: true,
|
|
113
|
+
authorization: mcpConfig.authorization,
|
|
108
114
|
allowedOrigins: mcpConfig.allowedOrigins
|
|
109
115
|
}).dispose;
|
|
110
116
|
}
|
|
@@ -139,14 +145,14 @@ function initDevframe(def, options) {
|
|
|
139
145
|
//#endregion
|
|
140
146
|
//#region src/adapters/dev.ts
|
|
141
147
|
/**
|
|
142
|
-
* Start a devframe dev server for a {@link DevframeDefinition}
|
|
148
|
+
* Start a devframe dev server for a {@link DevframeDefinition}:
|
|
143
149
|
* h3 + WebSocket RPC + (optionally) the author's SPA mounted at the
|
|
144
150
|
* resolved base path.
|
|
145
151
|
*
|
|
146
152
|
* When `distDir` is omitted (and the definition's client assets are unset) the
|
|
147
153
|
* server runs in **bridge mode**: only `__connection.json` and the WS
|
|
148
154
|
* endpoint are mounted, with no SPA mount. The SPA is expected to be
|
|
149
|
-
* hosted elsewhere (e.g. by a parent Vite/Nuxt dev server)
|
|
155
|
+
* hosted elsewhere (e.g. by a parent Vite/Nuxt dev server); see
|
|
150
156
|
* `devframeViteBridge` from `@devframes/vite`.
|
|
151
157
|
*
|
|
152
158
|
* Returns the underlying {@link StartedServer} handle so callers can
|
|
@@ -194,12 +200,25 @@ async function createDevServer(def, options = {}) {
|
|
|
194
200
|
ws: options.ws,
|
|
195
201
|
allowedOrigins: options.allowedOrigins,
|
|
196
202
|
sse: options.sse,
|
|
203
|
+
/**
|
|
204
|
+
* The `--no-auth` flag forces the gate off regardless of the `auth`
|
|
205
|
+
* option / definition default (which the instance resolves itself).
|
|
206
|
+
*/
|
|
197
207
|
auth: flags.auth === false ? false : options.auth,
|
|
198
208
|
mcp: options.mcp,
|
|
199
209
|
flags,
|
|
200
210
|
onPeerConnect: options.onPeerConnect,
|
|
201
211
|
onPeerDisconnect: options.onPeerDisconnect,
|
|
212
|
+
/**
|
|
213
|
+
* Publish in the global registry so discovery tooling (`devframe connect`)
|
|
214
|
+
* finds the server without port guessing. The instance owns the record's
|
|
215
|
+
* lifecycle, written once its (pinned) origin resolves, removed on close.
|
|
216
|
+
*/
|
|
202
217
|
register: true,
|
|
218
|
+
/**
|
|
219
|
+
* This server is devframe's own, and nothing else handles its upgrades, so
|
|
220
|
+
* off-route upgrade attempts are rejected promptly.
|
|
221
|
+
*/
|
|
203
222
|
destroyUnmatchedUpgrades: true
|
|
204
223
|
});
|
|
205
224
|
try {
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
import { i as defineDiagnostics } from "./nostics-
|
|
1
|
+
import { i as defineDiagnostics } from "./nostics-D0PvLZsn.mjs";
|
|
2
2
|
//#region src/node/diagnostics.ts
|
|
3
|
+
/**
|
|
4
|
+
* DF00xx codes are allocated across packages (e.g. @devframes/json-render
|
|
5
|
+
* owns DF0037–DF0041), so this file alone doesn't show the next free
|
|
6
|
+
* number; check `docs/content/6.errors/` for the full allocation before adding one.
|
|
7
|
+
*/
|
|
3
8
|
const diagnostics = defineDiagnostics({
|
|
4
9
|
docsBase: "https://devfra.me/errors",
|
|
5
10
|
codes: {
|
|
@@ -9,7 +14,7 @@ const diagnostics = defineDiagnostics({
|
|
|
9
14
|
DF0012: { why: (p) => `Failed to parse storage file: ${p.filepath}, falling back to defaults.` },
|
|
10
15
|
DF0013: { why: (p) => `Shared state of "${p.key}" is not found, please provide an initial value for the first time` },
|
|
11
16
|
DF0014: {
|
|
12
|
-
why: (p) => `RPC function "${p.name}" has an invalid \`agent\` field
|
|
17
|
+
why: (p) => `RPC function "${p.name}" has an invalid \`agent\` field: \`description\` must be a non-empty string.`,
|
|
13
18
|
fix: "Provide a short description (~1–3 sentences) explaining what the tool does and when agents should invoke it."
|
|
14
19
|
},
|
|
15
20
|
DF0015: {
|
|
@@ -23,12 +28,12 @@ const diagnostics = defineDiagnostics({
|
|
|
23
28
|
fix: "The consumer is too slow for the producer. Raise `highWaterMark` on the subscription, slow the producer, or batch chunks."
|
|
24
29
|
},
|
|
25
30
|
DF0030: {
|
|
26
|
-
why: (p) => `Stream "${p.channel}#${p.id}" is unknown
|
|
31
|
+
why: (p) => `Stream "${p.channel}#${p.id}" is unknown; no producer has called \`channel.start({ id: "${p.id}" })\`.`,
|
|
27
32
|
fix: "Ensure the server-side producer is running before clients subscribe, or check for typos in the stream id."
|
|
28
33
|
},
|
|
29
34
|
DF0031: {
|
|
30
35
|
why: (p) => `Cannot write to closed stream "${p.channel}#${p.id}".`,
|
|
31
|
-
fix: "Track the producer lifecycle
|
|
36
|
+
fix: "Track the producer lifecycle by guarding writes with the `stream.signal.aborted` flag."
|
|
32
37
|
},
|
|
33
38
|
DF0032: {
|
|
34
39
|
why: (p) => `Streaming channel "${p.channel}" is already registered.`,
|
|
@@ -48,14 +53,14 @@ const diagnostics = defineDiagnostics({
|
|
|
48
53
|
},
|
|
49
54
|
DF0036: {
|
|
50
55
|
why: (p) => `RPC call to "${p.name}" was rejected: the caller is not authorized.`,
|
|
51
|
-
fix: "Complete the auth handshake (or connect with a static/pre-shared token) before calling a trusted method. Untrusted callers may only call `anonymous:`-prefixed methods
|
|
56
|
+
fix: "Complete the auth handshake (or connect with a static/pre-shared token) before calling a trusted method. Untrusted callers may only call `anonymous:`-prefixed methods; see `isAnonymousRpcMethod`."
|
|
52
57
|
},
|
|
53
58
|
DF0037: {
|
|
54
59
|
why: (p) => `A service is already provided under "${p.id}".`,
|
|
55
60
|
fix: "Service ids are unique per context. Revoke the existing provider first (the `provide()` call returns a revoke function), or namespace the id with your plugin id to avoid collisions."
|
|
56
61
|
},
|
|
57
62
|
DF0042: {
|
|
58
|
-
why: (p) => `"${p.id}" declares \`capabilities.build: false
|
|
63
|
+
why: (p) => `"${p.id}" declares \`capabilities.build: false\`, so its static export is not meaningful (writes are excluded and any live-served data won't be there).`,
|
|
59
64
|
fix: "Pass `{ force: true }` to `createBuild()` if the degraded export is still useful to you, or drop `capabilities.build: false` on the definition."
|
|
60
65
|
},
|
|
61
66
|
DF0045: {
|
|
@@ -80,7 +85,7 @@ const diagnostics = defineDiagnostics({
|
|
|
80
85
|
},
|
|
81
86
|
DF0050: {
|
|
82
87
|
why: (p) => `No running devframe instance on port ${p.port}.`,
|
|
83
|
-
fix: "Call devframe_connect_list-instances for the current instance list
|
|
88
|
+
fix: "Call devframe_connect_list-instances for the current instance list; the instance may have stopped or changed port."
|
|
84
89
|
},
|
|
85
90
|
DF0051: {
|
|
86
91
|
why: (p) => `The devframe instance on port ${p.port} has no MCP endpoint.`,
|
|
@@ -92,7 +97,7 @@ const diagnostics = defineDiagnostics({
|
|
|
92
97
|
},
|
|
93
98
|
DF0054: {
|
|
94
99
|
why: (p) => `connectionMeta() was called before initDevframe("${p.id}") finished initializing.`,
|
|
95
|
-
fix: "Await `instance.ready` (or any request through `instance.handler`) before reading `connectionMeta()
|
|
100
|
+
fix: "Await `instance.ready` (or any request through `instance.handler`) before reading `connectionMeta()`; the WebSocket binding it describes is only known once initialization completes."
|
|
96
101
|
},
|
|
97
102
|
DF0055: {
|
|
98
103
|
why: (p) => `This instance already owns its WebSocket transport (${p.tier}), so it cannot take over the host's upgrade events.`,
|
|
@@ -104,10 +109,10 @@ const diagnostics = defineDiagnostics({
|
|
|
104
109
|
},
|
|
105
110
|
DF0057: {
|
|
106
111
|
why: () => "This instance disables its WebSocket transport (`ws: false`), so there is no socket to drive upgrades into.",
|
|
107
|
-
fix: "Clients connect over the SSE endpoint instead
|
|
112
|
+
fix: "Clients connect over the SSE endpoint instead, so no upgrade wiring is needed. Remove `ws: false` if the instance should serve a WebSocket after all."
|
|
108
113
|
},
|
|
109
114
|
DF0058: {
|
|
110
|
-
why: (p) => `"${p.id}" declares \`capabilities.dev: false
|
|
115
|
+
why: (p) => `"${p.id}" declares \`capabilities.dev: false\`, so it does not support a live dev server (its value is a static export only).`,
|
|
111
116
|
fix: "Pass `{ force: true }` to `createDevServer()` to run it anyway, or drop `capabilities.dev: false` on the definition."
|
|
112
117
|
},
|
|
113
118
|
DF0059: {
|
|
@@ -120,10 +125,10 @@ const diagnostics = defineDiagnostics({
|
|
|
120
125
|
},
|
|
121
126
|
DF0061: {
|
|
122
127
|
why: (p) => `The locally installed "${p.package}@${p.installed}" is a different major version than the required "${p.required}".`,
|
|
123
|
-
fix: "Align the installed assets package with the version its node package declares
|
|
128
|
+
fix: "Align the installed assets package with the version its node package declares; they are published in lockstep."
|
|
124
129
|
},
|
|
125
130
|
DF0062: {
|
|
126
|
-
why: (p) => `The locally installed "${p.package}@${p.installed}" differs from the required "${p.required}"
|
|
131
|
+
why: (p) => `The locally installed "${p.package}@${p.installed}" differs from the required "${p.required}"; serving the installed one.`,
|
|
127
132
|
fix: "Install the exact declared version to serve byte-identical assets."
|
|
128
133
|
},
|
|
129
134
|
DF0063: {
|
|
@@ -136,10 +141,10 @@ const diagnostics = defineDiagnostics({
|
|
|
136
141
|
},
|
|
137
142
|
DF0065: {
|
|
138
143
|
why: (p) => `Invalid remote-assets ${p.field} "${p.value}".`,
|
|
139
|
-
fix: "A remote-assets `package` must be a valid npm package name and `version` an exact semver version (e.g. `1.2.3`)
|
|
144
|
+
fix: "A remote-assets `package` must be a valid npm package name and `version` an exact semver version (e.g. `1.2.3`); they are interpolated into CDN URLs and the cache path."
|
|
140
145
|
},
|
|
141
146
|
DF0066: {
|
|
142
|
-
why: (p) => `Service "${p.package}" is already installed
|
|
147
|
+
why: (p) => `Service "${p.package}" is already installed; keeping the first installation and ignoring this one's options.`,
|
|
143
148
|
fix: "Option sets only merge before `ctx.services.ready()` fires. Install the service (or declare it in `DevframeDefinition.services`) before the barrier so its options join the merge."
|
|
144
149
|
},
|
|
145
150
|
DF0067: {
|
|
@@ -151,16 +156,24 @@ const diagnostics = defineDiagnostics({
|
|
|
151
156
|
fix: "Align the installed service package with the range its declarer requires, or drop `required: true` to downgrade the mismatch to a warning."
|
|
152
157
|
},
|
|
153
158
|
DF0069: {
|
|
154
|
-
why: (p) => `The installed service "${p.package}@${p.installed}" does not satisfy the declared range "${p.required}"
|
|
159
|
+
why: (p) => `The installed service "${p.package}@${p.installed}" does not satisfy the declared range "${p.required}"; installing it anyway.`,
|
|
155
160
|
fix: "The advertised meta carries the real version, so clients can gate on it. Align the installed service package with the declared range to silence this warning."
|
|
156
161
|
},
|
|
157
162
|
DF0070: {
|
|
158
163
|
why: (p) => `Invalid service "${p.package}": ${p.reason}`,
|
|
159
|
-
fix: "A service package's default export must be a factory returning a `DevframeServiceDefinition
|
|
164
|
+
fix: "A service package's default export must be a factory returning a `DevframeServiceDefinition`, an object with `package`, `version`, `scope`, and a `setup` function."
|
|
160
165
|
},
|
|
161
166
|
DF0072: {
|
|
162
|
-
why: (p) => `\`rpc.snapshot\` names "${p.method}", but no RPC function is registered under that id
|
|
167
|
+
why: (p) => `\`rpc.snapshot\` names "${p.method}", but no RPC function is registered under that id, so nothing to bake into the static build.`,
|
|
163
168
|
fix: "Check the method id, and ensure the service/plugin that registers it is installed (e.g. declared in `services`) before the build collects the dump."
|
|
169
|
+
},
|
|
170
|
+
DF0075: {
|
|
171
|
+
why: (p) => `On ${p.runtime} the shared server's WebSocket upgrade needs crossws's Node adapter, which refuses to run off Node, and SSE is disabled, so this instance advertises no RPC transport at all.`,
|
|
172
|
+
fix: "Keep the SSE endpoint enabled (drop `sse: false`) so clients connect over it on Bun/Deno, or move the socket to a side-car (`ws: { sidecar: true }`) which binds the native WebSocket adapter on its own port."
|
|
173
|
+
},
|
|
174
|
+
DF0076: {
|
|
175
|
+
why: (p) => `\`attach\` / \`handleUpgrade\` drive a raw \`node:http\` upgrade into crossws's Node adapter, which refuses to run on ${p.runtime}.`,
|
|
176
|
+
fix: "On Bun/Deno, serve the advertised `__ws` route from `Bun.serve` / `Deno.serve` with `attachBunWsTransport` / `attachDenoWsTransport` (see the hub-deno-minimal example), or connect over the SSE endpoint instead."
|
|
164
177
|
}
|
|
165
178
|
}
|
|
166
179
|
});
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { i as defineDiagnostics } from "./nostics-
|
|
1
|
+
import { i as defineDiagnostics } from "./nostics-D0PvLZsn.mjs";
|
|
2
2
|
//#region src/rpc/diagnostics.ts
|
|
3
3
|
const diagnostics = defineDiagnostics({
|
|
4
4
|
docsBase: "https://devfra.me/errors",
|
|
5
5
|
codes: {
|
|
6
6
|
DF0019: {
|
|
7
|
-
why: (p) => `RPC function "${p.name}" has \`agent\` set but \`jsonSerializable\` is not \`true
|
|
7
|
+
why: (p) => `RPC function "${p.name}" has \`agent\` set but \`jsonSerializable\` is not \`true\`; MCP requires JSON-serializable data.`,
|
|
8
8
|
fix: "Set `jsonSerializable: true` if the payload is JSON-safe, or remove `agent` to keep it RPC-only."
|
|
9
9
|
},
|
|
10
10
|
DF0020: {
|