devframe 0.9.1 → 0.9.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.
Files changed (65) hide show
  1. package/dist/{_shared-DqbKCAew.d.mts → _shared-BAGBgTUO.d.mts} +1 -1
  2. package/dist/adapters/build.d.mts +1 -1
  3. package/dist/adapters/build.mjs +9 -8
  4. package/dist/adapters/cac.d.mts +1 -1
  5. package/dist/adapters/cac.mjs +1 -1
  6. package/dist/adapters/dev.d.mts +3 -3
  7. package/dist/adapters/dev.mjs +1 -1
  8. package/dist/adapters/embedded.d.mts +1 -1
  9. package/dist/adapters/embedded.mjs +2 -1
  10. package/dist/adapters/initiate.d.mts +2 -2
  11. package/dist/adapters/initiate.mjs +1 -1
  12. package/dist/adapters/mcp.d.mts +1 -1
  13. package/dist/adapters/mcp.mjs +1 -1
  14. package/dist/cli/main.mjs +2 -2
  15. package/dist/client/index.d.mts +1 -1
  16. package/dist/client/index.mjs +2 -2
  17. package/dist/{context-CXhjygJU.mjs → context-af2w_F0_.mjs} +1 -1
  18. package/dist/{context-dqyXS6o3.d.mts → context-al99DDJ8.d.mts} +1 -1
  19. package/dist/{context-Bdkakk8S.mjs → context-riPPHGiu.mjs} +34 -19
  20. package/dist/{dev-C8VHtuPP.mjs → dev-BKm_HisC.mjs} +10 -9
  21. package/dist/{devframe-BlLEZR-x.d.mts → devframe-mbfgpQQC.d.mts} +55 -21
  22. package/dist/{diagnostics-Di8ytitn.mjs → diagnostics-DI1HGj2I.mjs} +0 -4
  23. package/dist/hash-DdPnc4k3.mjs +360 -0
  24. package/dist/{host-agent-BDdcOXhG.mjs → host-agent-DVDLqjvj.mjs} +1 -1
  25. package/dist/{http-BbHCU5Zs.mjs → http-POepPnaQ.mjs} +6 -5
  26. package/dist/{index-BKFT9-jA.d.mts → index-Dipgo9ji.d.mts} +2 -2
  27. package/dist/index.d.mts +1 -1
  28. package/dist/{instance-registry-CHunhMi5.mjs → instance-registry-Dy28drtm.mjs} +1 -1
  29. package/dist/{instance-shell-DbDoozNM.mjs → instance-shell-GqTY93gC.mjs} +4 -4
  30. package/dist/{instance-shell-0iw-cQ5V.d.mts → instance-shell-mU5j5xWn.d.mts} +2 -2
  31. package/dist/internal/index.d.mts +4 -10
  32. package/dist/internal/index.mjs +5 -5
  33. package/dist/node/auth.d.mts +2 -2
  34. package/dist/node/hub-internals.d.mts +2 -2
  35. package/dist/node/hub-internals.mjs +1 -1
  36. package/dist/node/index.d.mts +10 -1
  37. package/dist/node/index.mjs +2 -2
  38. package/dist/recipes/common-rpc-functions.d.mts +11 -1
  39. package/dist/recipes/common-rpc-functions.mjs +10 -0
  40. package/dist/recipes/interactive-auth.d.mts +2 -2
  41. package/dist/recipes/interactive-auth.mjs +1 -1
  42. package/dist/{remote-assets-DRfY2RjX.mjs → remote-assets-CqxiyltC.mjs} +13 -3
  43. package/dist/rpc/dump.mjs +1 -1
  44. package/dist/rpc/index.mjs +1 -1
  45. package/dist/rpc/transports/ws-bun.d.mts +1 -1
  46. package/dist/rpc/transports/ws-deno.d.mts +26 -0
  47. package/dist/rpc/transports/ws-deno.mjs +30 -0
  48. package/dist/{rpc-core-Dru9uoM0.mjs → rpc-core-DRYnbxdD.mjs} +3 -10
  49. package/dist/{rpc-core-CR8o34O9.d.mts → rpc-core-dV69u4lY.d.mts} +2 -2
  50. package/dist/{shared-state-fRRbRUtD.mjs → shared-state-DoXutg_U.mjs} +1 -1
  51. package/dist/{static-BPZ1_OPA.mjs → static-DV_qUSRS.mjs} +1 -1
  52. package/dist/{storage-D4a99Ung.mjs → storage-BNqSAOxA.mjs} +1 -1
  53. package/dist/types/index.d.mts +1 -1
  54. package/dist/utils/events.d.mts +1 -1
  55. package/dist/utils/hash.mjs +1 -1
  56. package/dist/utils/remote-assets.d.mts +7 -1
  57. package/dist/utils/remote-assets.mjs +1 -1
  58. package/dist/utils/shared-state.d.mts +1 -1
  59. package/dist/utils/shared-state.mjs +1 -1
  60. package/dist/utils/streaming-channel.d.mts +1 -1
  61. package/dist/validation-YrZH6atx.mjs +311 -0
  62. package/package.json +4 -3
  63. package/skills/devframe/SKILL.md +1 -1
  64. package/dist/hash-KtDZYXDN.mjs +0 -266
  65. package/dist/validation-CpXFB6Dz.mjs +0 -266
@@ -1,4 +1,4 @@
1
- import { d as ConnectionMeta, l as McpRouteOptions, n as DevframeDefinition, r as DevframeDeploymentKind } from "./devframe-BlLEZR-x.mjs";
1
+ import { d as ConnectionMeta, l as McpRouteOptions, n as DevframeDefinition, r as DevframeDeploymentKind } from "./devframe-mbfgpQQC.mjs";
2
2
  //#region src/adapters/_shared.d.ts
3
3
  /**
4
4
  * Resolve the mount base path for a devframe's SPA. Hosted adapters
@@ -1,4 +1,4 @@
1
- import { n as DevframeDefinition } from "../devframe-BlLEZR-x.mjs";
1
+ import { n as DevframeDefinition } from "../devframe-mbfgpQQC.mjs";
2
2
  import { o as StaticAssetsSource } from "../remote-assets-Bg4gCUZ_.mjs";
3
3
  //#region src/adapters/build.d.ts
4
4
  interface CreateBuildOptions {
@@ -1,11 +1,11 @@
1
1
  import { s as colors } from "../nostics-CzECRXpE.mjs";
2
2
  import { n as strictJsonStringify } from "../serialization-BGzEwAdr.mjs";
3
3
  import { DEVFRAME_CONNECTION_META_FILENAME, DEVFRAME_RPC_DUMP_DIRNAME, DEVFRAME_RPC_DUMP_MANIFEST_FILENAME } from "../constants.mjs";
4
- import { t as collectStaticRpcDump } from "../static-BPZ1_OPA.mjs";
4
+ import { t as collectStaticRpcDump } from "../static-DV_qUSRS.mjs";
5
5
  import { n as structuredCloneStringify } from "../structured-clone-CbAV5rFI.mjs";
6
- import { t as diagnostics } from "../diagnostics-Di8ytitn.mjs";
7
- import { t as createHostContext } from "../context-Bdkakk8S.mjs";
8
- import { t as resolveStaticAssetsSource } from "../remote-assets-DRfY2RjX.mjs";
6
+ import { t as diagnostics } from "../diagnostics-DI1HGj2I.mjs";
7
+ import { t as createHostContext } from "../context-riPPHGiu.mjs";
8
+ import { t as resolveStaticAssetsSource } from "../remote-assets-CqxiyltC.mjs";
9
9
  import { t as createH3DevframeHost } from "../host-h3-fRbF9yor.mjs";
10
10
  import process from "node:process";
11
11
  import { dirname, resolve } from "pathe";
@@ -34,7 +34,7 @@ async function createBuild(d, options = {}) {
34
34
  origin: "http://localhost",
35
35
  appName: d.id
36
36
  });
37
- const resolved = resolveStaticAssetsSource(distSource, host.getStorageDir("project"));
37
+ const resolved = resolveStaticAssetsSource(distSource, host.getStorageDir("project"), d.importMetaUrl);
38
38
  if (typeof resolved === "string") {
39
39
  console.log(colors.cyan`[devframe] copying SPA from ${resolved} -> ${outDir}`);
40
40
  await fs$1.cp(resolved, outDir, { recursive: true });
@@ -45,11 +45,12 @@ async function createBuild(d, options = {}) {
45
45
  const ctx = await createHostContext({
46
46
  cwd: process.cwd(),
47
47
  mode: "build",
48
- host
48
+ host,
49
+ importMetaUrl: d.importMetaUrl
49
50
  });
50
- for (const input of d.services ?? []) ctx.services.install(input, { resolveFrom: d.packageName });
51
- await d.setup(ctx);
51
+ for (const input of d.services ?? []) ctx.services.install(input, { resolveFrom: d.importMetaUrl });
52
52
  await ctx.services.ready();
53
+ await d.setup(ctx);
53
54
  await fs$1.mkdir(resolve(outDir, DEVFRAME_RPC_DUMP_DIRNAME), { recursive: true });
54
55
  const jsonSerializableMethods = [];
55
56
  for (const def of ctx.rpc.definitions.values()) if (def.jsonSerializable === true) jsonSerializableMethods.push(def.name);
@@ -1,4 +1,4 @@
1
- import { Ft as CliFlagsSchema, It as InferCliFlags, Lt as defineCliFlags, Rt as parseCliFlags, n as DevframeDefinition } from "../devframe-BlLEZR-x.mjs";
1
+ import { Ft as CliFlagsSchema, It as InferCliFlags, Lt as defineCliFlags, Rt as parseCliFlags, n as DevframeDefinition } from "../devframe-mbfgpQQC.mjs";
2
2
  import { CAC } from "cac";
3
3
  import { H3 } from "h3";
4
4
  //#region src/adapters/cac.d.ts
@@ -1,7 +1,7 @@
1
1
  import { s as colors } from "../nostics-CzECRXpE.mjs";
2
2
  import { r as resolveDevServerPort } from "../_shared-BM3PdYli.mjs";
3
3
  import { createBuild } from "./build.mjs";
4
- import { t as createDevServer } from "../dev-C8VHtuPP.mjs";
4
+ import { t as createDevServer } from "../dev-BKm_HisC.mjs";
5
5
  import process from "node:process";
6
6
  import cac$1 from "cac";
7
7
  //#region src/adapters/flags.ts
@@ -1,8 +1,8 @@
1
- import { _ as DevframeNodeRpcSession, c as DevframeWsOptions, l as McpRouteOptions, n as DevframeDefinition, s as DevframeSseOptions, u as DevframeAuthHandler } from "../devframe-BlLEZR-x.mjs";
1
+ import { _ as DevframeNodeRpcSession, c as DevframeWsOptions, l as McpRouteOptions, n as DevframeDefinition, s as DevframeSseOptions, u as DevframeAuthHandler } from "../devframe-mbfgpQQC.mjs";
2
2
  import { d as DevframeRpcConnection, n as WsOriginRegistry, u as DevframeNodeRpcSessionMeta } from "../ws-server-D1d3QM9f.mjs";
3
3
  import { o as StaticAssetsSource } from "../remote-assets-Bg4gCUZ_.mjs";
4
- import { c as StartedServer } from "../instance-shell-0iw-cQ5V.mjs";
5
- import { a as resolveMcpConnectionMeta, i as resolveDevServerPort, t as ResolveDevServerPortOptions } from "../_shared-DqbKCAew.mjs";
4
+ import { c as StartedServer } from "../instance-shell-mU5j5xWn.mjs";
5
+ import { a as resolveMcpConnectionMeta, i as resolveDevServerPort, t as ResolveDevServerPortOptions } from "../_shared-BAGBgTUO.mjs";
6
6
  import { H3 } from "h3";
7
7
  //#region src/adapters/dev.d.ts
8
8
  interface CreateDevServerOptions {
@@ -1,3 +1,3 @@
1
1
  import { i as resolveMcpConnectionMeta, r as resolveDevServerPort } from "../_shared-BM3PdYli.mjs";
2
- import { t as createDevServer } from "../dev-C8VHtuPP.mjs";
2
+ import { t as createDevServer } from "../dev-BKm_HisC.mjs";
3
3
  export { createDevServer, resolveDevServerPort, resolveMcpConnectionMeta };
@@ -1,4 +1,4 @@
1
- import { g as DevframeNodeContext, n as DevframeDefinition } from "../devframe-BlLEZR-x.mjs";
1
+ import { g as DevframeNodeContext, n as DevframeDefinition } from "../devframe-mbfgpQQC.mjs";
2
2
  //#region src/adapters/embedded.d.ts
3
3
  interface CreateEmbeddedOptions {
4
4
  /** Target context the devframe is registered into. Required. */
@@ -9,7 +9,8 @@
9
9
  * effective default follows the hosted rule of `def.basePath ?? '/__<id>/'`.
10
10
  */
11
11
  async function createEmbedded(d, options) {
12
- for (const input of d.services ?? []) options.ctx.services.install(input, { resolveFrom: d.packageName });
12
+ for (const input of d.services ?? []) options.ctx.services.install(input, { resolveFrom: d.importMetaUrl });
13
+ await options.ctx.services.ready();
13
14
  await d.setup(options.ctx);
14
15
  }
15
16
  //#endregion
@@ -1,7 +1,7 @@
1
- import { $ as DevframeStorageScope, _ as DevframeNodeRpcSession, c as DevframeWsOptions, d as ConnectionMeta, g as DevframeNodeContext, l as McpRouteOptions, n as DevframeDefinition, s as DevframeSseOptions, u as DevframeAuthHandler } from "../devframe-BlLEZR-x.mjs";
1
+ import { $ as DevframeStorageScope, _ as DevframeNodeRpcSession, c as DevframeWsOptions, d as ConnectionMeta, g as DevframeNodeContext, l as McpRouteOptions, n as DevframeDefinition, s as DevframeSseOptions, u as DevframeAuthHandler } from "../devframe-mbfgpQQC.mjs";
2
2
  import { d as DevframeRpcConnection, n as WsOriginRegistry, u as DevframeNodeRpcSessionMeta } from "../ws-server-D1d3QM9f.mjs";
3
3
  import { o as StaticAssetsSource } from "../remote-assets-Bg4gCUZ_.mjs";
4
- import { c as StartedServer, f as DevframeInstanceRecord } from "../instance-shell-0iw-cQ5V.mjs";
4
+ import { c as StartedServer, f as DevframeInstanceRecord } from "../instance-shell-mU5j5xWn.mjs";
5
5
  import { Buffer } from "node:buffer";
6
6
  import { IncomingMessage, Server, ServerResponse } from "node:http";
7
7
  import { Duplex } from "node:stream";
@@ -1,2 +1,2 @@
1
- import { n as getInstanceInternals, r as initDevframe } from "../dev-C8VHtuPP.mjs";
1
+ import { n as getInstanceInternals, r as initDevframe } from "../dev-BKm_HisC.mjs";
2
2
  export { getInstanceInternals, initDevframe };
@@ -1,4 +1,4 @@
1
- import { g as DevframeNodeContext, n as DevframeDefinition } from "../devframe-BlLEZR-x.mjs";
1
+ import { g as DevframeNodeContext, n as DevframeDefinition } from "../devframe-mbfgpQQC.mjs";
2
2
  import { H3 } from "h3";
3
3
  import "@modelcontextprotocol/server";
4
4
  //#region src/adapters/mcp/build-server.d.ts
@@ -1,2 +1,2 @@
1
- import { i as createMcpServer, n as mountMcpHttp, r as createMcpFetchHandler } from "../http-BbHCU5Zs.mjs";
1
+ import { i as createMcpServer, n as mountMcpHttp, r as createMcpFetchHandler } from "../http-POepPnaQ.mjs";
2
2
  export { createMcpFetchHandler, createMcpServer, mountMcpHttp };
package/dist/cli/main.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { t as Diagnostic } from "../nostics-CzECRXpE.mjs";
2
- import { t as diagnostics } from "../diagnostics-Di8ytitn.mjs";
3
- import { n as listLiveDevframeInstances, r as probeDevframeOrigin } from "../instance-registry-CHunhMi5.mjs";
2
+ import { t as diagnostics } from "../diagnostics-DI1HGj2I.mjs";
3
+ import { n as listLiveDevframeInstances, r as probeDevframeOrigin } from "../instance-registry-Dy28drtm.mjs";
4
4
  import { t as toAgentToolName } from "../agent-tool-name-EgfoFO8C.mjs";
5
5
  import process from "node:process";
6
6
  import { joinURL } from "ufo";
@@ -1,4 +1,4 @@
1
- import { E as DevframeRpcServerFunctions, H as DevframeSettings, J as ScopedServerFunctions, M as DevframeServiceMeta, Mt as EventEmitter, P as DevframeServiceScopeOf, R as DevframeServicesState, T as DevframeRpcClientFunctions, X as SettingsForNamespace, Y as ScopedSharedStates, b as RpcSharedStateGetOptions, d as ConnectionMeta, gt as SharedState, ot as StreamReader, q as ScopedRpcFn, st as StreamSink, x as RpcSharedStateHost } from "../devframe-BlLEZR-x.mjs";
1
+ import { E as DevframeRpcServerFunctions, H as DevframeSettings, J as ScopedServerFunctions, M as DevframeServiceMeta, Mt as EventEmitter, P as DevframeServiceScopeOf, R as DevframeServicesState, T as DevframeRpcClientFunctions, X as SettingsForNamespace, Y as ScopedSharedStates, b as RpcSharedStateGetOptions, d as ConnectionMeta, gt as SharedState, ot as StreamReader, q as ScopedRpcFn, st as StreamSink, x as RpcSharedStateHost } from "../devframe-mbfgpQQC.mjs";
2
2
  import { f as RpcCacheManager, p as RpcCacheOptions } from "../index-tdrk1bzV.mjs";
3
3
  import { _ as RpcFunctionDefinition, w as RpcFunctionsCollector } from "../types-Djq7CBXh.mjs";
4
4
  import { t as SseRpcChannelOptions } from "../sse-client-CFBOIaUi.mjs";
@@ -1,7 +1,7 @@
1
- import { t as hash } from "../hash-KtDZYXDN.mjs";
1
+ import { t as hash } from "../hash-DdPnc4k3.mjs";
2
2
  import { colors } from "../utils/colors.mjs";
3
3
  import { createEventEmitter } from "../utils/events.mjs";
4
- import { t as createSharedState } from "../shared-state-fRRbRUtD.mjs";
4
+ import { t as createSharedState } from "../shared-state-DoXutg_U.mjs";
5
5
  import { i as structuredCloneStringify, n as structuredCloneParse, t as structuredCloneDeserialize } from "../structured-clone-CgtQ61SA.mjs";
6
6
  import { createStreamReader, createStreamSink } from "../utils/streaming-channel.mjs";
7
7
  import { defineDiagnostics } from "nostics";
@@ -1,5 +1,5 @@
1
1
  import { n as randomToken } from "./crypto-token-XCqTSMg9.mjs";
2
- import { t as createStorage } from "./storage-D4a99Ung.mjs";
2
+ import { t as createStorage } from "./storage-BNqSAOxA.mjs";
3
3
  import { n as revokeAuthToken, t as revokeActiveConnectionsForToken } from "./revoke-3Q6aDKWk.mjs";
4
4
  import { join } from "pathe";
5
5
  //#region src/node/hub-internals/context.ts
@@ -1,4 +1,4 @@
1
- import { g as DevframeNodeContext, gt as SharedState } from "./devframe-BlLEZR-x.mjs";
1
+ import { g as DevframeNodeContext, gt as SharedState } from "./devframe-mbfgpQQC.mjs";
2
2
  //#region src/node/hub-internals/context.d.ts
3
3
  interface InternalAnonymousAuthStorage {
4
4
  trusted: Record<string, {
@@ -4,10 +4,10 @@ import { RpcFunctionsCollectorBase } from "./rpc/index.mjs";
4
4
  import { defineRpcFunction } from "./index.mjs";
5
5
  import { t as DEVFRAME_EVENTS } from "./events-DKfSmoTj.mjs";
6
6
  import { DEVFRAME_SERVICES_STATE_KEY } from "./constants.mjs";
7
- import { t as diagnostics$1 } from "./diagnostics-Di8ytitn.mjs";
8
- import { r as createEventEmitter, t as DevframeAgentHost } from "./host-agent-BDdcOXhG.mjs";
9
- import { n as createDebug, t as resolveStaticAssetsSource } from "./remote-assets-DRfY2RjX.mjs";
10
- import { t as createStorage } from "./storage-D4a99Ung.mjs";
7
+ import { t as diagnostics$1 } from "./diagnostics-DI1HGj2I.mjs";
8
+ import { r as createEventEmitter, t as DevframeAgentHost } from "./host-agent-DVDLqjvj.mjs";
9
+ import { n as createDebug, t as resolveStaticAssetsSource } from "./remote-assets-CqxiyltC.mjs";
10
+ import { t as createStorage } from "./storage-BNqSAOxA.mjs";
11
11
  import { createRequire } from "node:module";
12
12
  import { createSharedState } from "devframe/utils/shared-state";
13
13
  import process from "node:process";
@@ -776,10 +776,10 @@ function toRequireBase(resolveFrom) {
776
776
  }
777
777
  /**
778
778
  * Normalize an `install()` `resolveFrom` into a resolution base. Paths and
779
- * file URLs pass through; a bare npm package name (the common case: the
780
- * declaring plugin's `packageName`) resolves to that package's location from
781
- * `cwd`, so a service it declares resolves against the plugin's own
782
- * dependencies. An unresolvable package name reads as no base (the caller's
779
+ * file URLs pass through (the common case: the declaring plugin's
780
+ * `importMetaUrl`, so a service it declares resolves against the plugin's own
781
+ * dependencies); a bare npm package name resolves to that package's location
782
+ * from `cwd`. An unresolvable package name reads as no base (the caller's
783
783
  * workspace fallbacks apply).
784
784
  */
785
785
  function expandResolveFrom(resolveFrom, cwd) {
@@ -880,14 +880,27 @@ function satisfiesVersionRange(version, range) {
880
880
  if (alternatives.length === 0) return true;
881
881
  return alternatives.some((alternative) => alternative.split(/\s+/).every((comparator) => satisfiesComparator(parsed, comparator)));
882
882
  }
883
+ function isPlainObject(value) {
884
+ return typeof value === "object" && value !== null && !Array.isArray(value);
885
+ }
886
+ /** Deep-merge two values with the service option-set rules (see below). */
887
+ function deepMergeTwo(a, b) {
888
+ if (Array.isArray(a) && Array.isArray(b)) return [.../* @__PURE__ */ new Set([...a, ...b])];
889
+ if (isPlainObject(a) && isPlainObject(b)) {
890
+ const out = { ...a };
891
+ for (const key of Object.keys(b)) out[key] = key in a ? deepMergeTwo(a[key], b[key]) : b[key];
892
+ return out;
893
+ }
894
+ return b;
895
+ }
883
896
  /**
884
897
  * Default option-set merge when a service declares no `mergeOptions`:
885
- * shallow-merge plain objects in declaration order (later sets win); any
886
- * non-object set collapses the merge to "last one wins".
898
+ * deep-merge in declaration order — objects recurse, arrays union-dedupe,
899
+ * scalars take the later value. Covers the built-in services (`roots` /
900
+ * `langs` union, `themes` per-key last-wins) without a custom hook.
887
901
  */
888
- function shallowMergeOptionSets(sets) {
889
- if (sets.some((set) => typeof set !== "object" || set === null || Array.isArray(set))) return sets[sets.length - 1];
890
- return Object.assign({}, ...sets);
902
+ function deepMergeOptionSets(sets) {
903
+ return sets.reduce((merged, set) => deepMergeTwo(merged, set));
891
904
  }
892
905
  //#endregion
893
906
  //#region src/node/host-services.ts
@@ -1068,7 +1081,7 @@ var DevframeServicesHostImpl = class {
1068
1081
  });
1069
1082
  }
1070
1083
  const sets = entries.map((entry) => entry.input.options).filter((options) => options !== void 0);
1071
- const options = def.mergeOptions ? def.mergeOptions(sets) : sets.length > 0 ? shallowMergeOptionSets(sets) : void 0;
1084
+ const options = def.mergeOptions ? def.mergeOptions(sets) : sets.length > 0 ? deepMergeOptionSets(sets) : void 0;
1072
1085
  if (!this.context) throw diagnostics$1.DF0070({
1073
1086
  package: pkg,
1074
1087
  reason: "this services host has no node context to install into"
@@ -1101,15 +1114,17 @@ var DevframeServicesHostImpl = class {
1101
1114
  //#region src/node/host-views.ts
1102
1115
  var DevframeViewHost = class {
1103
1116
  context;
1117
+ importMetaUrl;
1104
1118
  /**
1105
1119
  * @internal
1106
1120
  */
1107
1121
  buildStaticDirs = [];
1108
- constructor(context) {
1122
+ constructor(context, importMetaUrl) {
1109
1123
  this.context = context;
1124
+ this.importMetaUrl = importMetaUrl;
1110
1125
  }
1111
- hostStatic(baseUrl, source) {
1112
- const resolved = resolveStaticAssetsSource(source, this.context.host.getStorageDir("project"));
1126
+ hostStatic(baseUrl, source, defaultResolveFrom = this.importMetaUrl) {
1127
+ const resolved = resolveStaticAssetsSource(source, this.context.host.getStorageDir("project"), defaultResolveFrom);
1113
1128
  if (typeof resolved === "string" && !existsSync(resolved)) throw diagnostics$1.DF0008({ distDir: resolved });
1114
1129
  this.buildStaticDirs.push({
1115
1130
  baseUrl,
@@ -1301,7 +1316,7 @@ function createScopedNodeContext(context, namespace) {
1301
1316
  * `commands` when mounted into Vite DevTools.
1302
1317
  */
1303
1318
  async function createHostContext(options) {
1304
- const { cwd, workspaceRoot = cwd, mode, host, builtinRpcDeclarations = [] } = options;
1319
+ const { cwd, workspaceRoot = cwd, mode, host, importMetaUrl, builtinRpcDeclarations = [] } = options;
1305
1320
  const context = {
1306
1321
  cwd,
1307
1322
  workspaceRoot,
@@ -1316,7 +1331,7 @@ async function createHostContext(options) {
1316
1331
  scope: void 0
1317
1332
  };
1318
1333
  const rpcHost = new RpcFunctionsHostImpl(context);
1319
- const viewsHost = new DevframeViewHost(context);
1334
+ const viewsHost = new DevframeViewHost(context, importMetaUrl);
1320
1335
  const diagnosticsHost = new DevframeDiagnosticsHost(context, [diagnostics$1, diagnostics]);
1321
1336
  context.rpc = rpcHost;
1322
1337
  context.views = viewsHost;
@@ -1,10 +1,10 @@
1
1
  import { DEVFRAME_CONNECTION_META_FILENAME } from "./constants.mjs";
2
- import { t as diagnostics } from "./diagnostics-Di8ytitn.mjs";
3
- import { t as createHostContext } from "./context-Bdkakk8S.mjs";
4
- import { t as resolveStaticAssetsSource } from "./remote-assets-DRfY2RjX.mjs";
2
+ import { t as diagnostics } from "./diagnostics-DI1HGj2I.mjs";
3
+ import { t as createHostContext } from "./context-riPPHGiu.mjs";
4
+ import { t as resolveStaticAssetsSource } from "./remote-assets-CqxiyltC.mjs";
5
5
  import { i as resolveMcpConnectionMeta, n as resolveBasePath, r as resolveDevServerPort, t as normalizeBasePath } from "./_shared-BM3PdYli.mjs";
6
6
  import { t as createH3DevframeHost } from "./host-h3-fRbF9yor.mjs";
7
- import { i as normalizeHttpServerUrl, n as resolveInstanceRegister, t as createInstanceShell } from "./instance-shell-DbDoozNM.mjs";
7
+ import { i as normalizeHttpServerUrl, n as resolveInstanceRegister, t as createInstanceShell } from "./instance-shell-GqTY93gC.mjs";
8
8
  import { open } from "./utils/open.mjs";
9
9
  import { mountStaticHandler } from "./utils/serve-static.mjs";
10
10
  import { createServer } from "node:http";
@@ -76,12 +76,13 @@ function initDevframe(def, options) {
76
76
  const context = await createHostContext({
77
77
  cwd: process.cwd(),
78
78
  mode: "dev",
79
- host: hostImpl
79
+ host: hostImpl,
80
+ importMetaUrl: def.importMetaUrl
80
81
  });
81
82
  const setupInfo = { flags: options.flags ?? {} };
82
- for (const input of def.services ?? []) context.services.install(input, { resolveFrom: def.packageName });
83
- await def.setup(context, setupInfo);
83
+ for (const input of def.services ?? []) context.services.install(input, { resolveFrom: def.importMetaUrl });
84
84
  await context.services.ready();
85
+ await def.setup(context, setupInfo);
85
86
  const mcpOption = options.mcp ?? def.cli?.mcp;
86
87
  const mcpMeta = resolveMcpConnectionMeta(def, mcpOption);
87
88
  let mcpDispose;
@@ -90,7 +91,7 @@ function initDevframe(def, options) {
90
91
  const mcpPath = joinURL(base, mcpMeta.path);
91
92
  let mountMcpHttp;
92
93
  try {
93
- ({mountMcpHttp} = await import("./http-BbHCU5Zs.mjs").then((n) => n.t));
94
+ ({mountMcpHttp} = await import("./http-POepPnaQ.mjs").then((n) => n.t));
94
95
  } catch (error) {
95
96
  const reason = error instanceof Error ? error.message : String(error);
96
97
  throw diagnostics.DF0017({
@@ -115,7 +116,7 @@ function initDevframe(def, options) {
115
116
  mount(context, meta) {
116
117
  app.use(joinURL(base, DEVFRAME_CONNECTION_META_FILENAME), () => meta);
117
118
  if (distDir) {
118
- const source = resolveStaticAssetsSource(distDir, context.host.getStorageDir("project"));
119
+ const source = resolveStaticAssetsSource(distDir, context.host.getStorageDir("project"), def.importMetaUrl);
119
120
  mountStaticHandler(app, base, typeof source === "string" ? resolve(source) : source);
120
121
  }
121
122
  }
@@ -636,8 +636,15 @@ interface DevframeViewHost {
636
636
  *
637
637
  * Accepts a local dist directory, or a {@link StaticAssetsSource} remote
638
638
  * declaration served through devframe's caching CDN back-proxy.
639
+ *
640
+ * `defaultResolveFrom` overrides, for this call only, the context's own
641
+ * `importMetaUrl` as the default `resolveFrom` for a remote source that
642
+ * doesn't set one. A shared host that mounts assets on behalf of another
643
+ * devframe (a hub installing a plugin) passes that plugin's `importMetaUrl`
644
+ * so the assets resolve against the plugin's dependency graph rather than
645
+ * the host's.
639
646
  */
640
- hostStatic: (baseUrl: string, source: StaticAssetsSource) => void;
647
+ hostStatic: (baseUrl: string, source: StaticAssetsSource, defaultResolveFrom?: string | null) => void;
641
648
  }
642
649
  //#endregion
643
650
  //#region src/types/scope.d.ts
@@ -981,33 +988,37 @@ interface DevframeServicesHost {
981
988
  /** Ids of every currently-provided service. */
982
989
  keys: () => string[];
983
990
  /**
984
- * Install a **wire service** (see {@link DevframeServiceDefinition}).
985
- * Before {@link DevframeServicesHost.ready} fires, installs are queued —
986
- * option sets from every installer accumulate and each service is
987
- * constructed **once** at the barrier with the merged options; the
988
- * returned promise resolves with the service's node API then (or
989
- * `undefined` when an optional descriptor's package can't be imported).
990
- * After the barrier, installs construct immediately; installing an
991
- * already-installed package returns the existing API (a warning is
992
- * emitted when the late install carried options, since they're ignored).
991
+ * Install a **wire service** (see {@link DevframeServiceDefinition}). The
992
+ * common path is declarative — list services on `DevframeDefinition.services`
993
+ * (or `initHub({ services })`) and the adapter installs them for you before
994
+ * `setup` runs. Call `install()` directly only for the dynamic escape hatch:
995
+ * a service configured at runtime from data unknown until then.
996
+ *
997
+ * Before the pre-setup ready fires, installs are queued and their option
998
+ * sets deep-merged, constructing each service **once**. After it, an install
999
+ * constructs immediately; installing an already-installed package returns
1000
+ * the existing API (a warning — `DF0066` — when the late install carried
1001
+ * options, since they're ignored). The returned promise resolves with the
1002
+ * node API (or `undefined` when an optional descriptor's package can't be
1003
+ * imported).
993
1004
  *
994
1005
  * `resolveFrom` is where a descriptor's package resolves **from**: a path
995
- * or file URL (e.g. `import.meta.url`), or an npm package name — typically
996
- * the declaring plugin's `packageName`, so its declared services resolve
997
- * against the plugin's own dependencies. Falls back to the context's
998
- * `workspaceRoot`.
1006
+ * or file URL (e.g. the declaring devframe's `importMetaUrl`), or an npm
1007
+ * package name, so its declared services resolve against the declarer's own
1008
+ * dependencies. Falls back to the context's `workspaceRoot` then `cwd`.
999
1009
  */
1000
1010
  install: <API = unknown, Options = any>(input: DevframeServiceInput<API, Options>, options?: {
1001
1011
  resolveFrom?: string | null;
1002
1012
  }) => Promise<API | undefined>;
1003
1013
  /**
1004
- * Fire the collect-then-setup barrier: resolve every queued descriptor
1005
- * (importing its package), merge option sets per service, construct each
1006
- * service once, `provide()` its node API under the package name, and
1007
- * advertise it to clients via the `devframe:services` shared state.
1008
- * Idempotent — adapters call it once after every devframe's `setup` has
1009
- * run; a repeat returns the same promise. Rejects when a `required`
1010
- * service fails to import or misses its version range.
1014
+ * Construct every queued service — importing descriptor packages, merging
1015
+ * option sets, `provide()`-ing each node API under its package name, and
1016
+ * advertising it to clients via the `devframe:services` shared state.
1017
+ * Idempotent. **Internal**: the adapters call it once, before running any
1018
+ * `setup`, so services are ready for `setup` to consume; application code
1019
+ * uses declarative `services` (or `install()` for the dynamic case) and
1020
+ * never calls this. Rejects when a `required` service fails to import or
1021
+ * misses its version range.
1011
1022
  */
1012
1023
  ready: () => Promise<void>;
1013
1024
  }
@@ -1932,6 +1943,29 @@ interface DevframeDefinition {
1932
1943
  version: string;
1933
1944
  /** npm package name the devframe ships in (e.g. `@scope/my-tool`). */
1934
1945
  packageName: string;
1946
+ /**
1947
+ * `import.meta.url` of the module that defines this devframe. **Always
1948
+ * provide it** (`importMetaUrl: import.meta.url`): it is the resolution base
1949
+ * for the tool's own dependency graph, which lets the host resolve
1950
+ * everything against the plugin's own installed packages rather than the
1951
+ * consuming app's.
1952
+ *
1953
+ * - **Remote assets** — becomes the default `resolveFrom` for any remote
1954
+ * {@link StaticAssetsSource} the devframe hosts (its `cli.distDir`, and
1955
+ * every `ctx.views.hostStatic` call) that doesn't set one explicitly, so a
1956
+ * locally installed copy of the assets package is served with zero
1957
+ * network. A per-asset `resolveFrom` still wins, and an explicit
1958
+ * `resolveFrom: null` still opts out.
1959
+ * - **Service dependencies** — becomes the base the host resolves declared
1960
+ * {@link DevframeServiceInput | services} from, so a plugin can ship a
1961
+ * service package as its own dependency instead of asking users to install
1962
+ * it.
1963
+ *
1964
+ * Optional for backward compatibility; omitting it falls back to
1965
+ * runtime-directory resolution and disables the zero-network installed-copy
1966
+ * fast paths above.
1967
+ */
1968
+ importMetaUrl?: string;
1935
1969
  /** Project homepage or documentation URL. */
1936
1970
  homepage: string;
1937
1971
  /** One-line summary of what the tool does. */
@@ -157,10 +157,6 @@ const diagnostics = defineDiagnostics({
157
157
  DF0070: {
158
158
  why: (p) => `Invalid service "${p.package}": ${p.reason}`,
159
159
  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
- },
161
- DF0071: {
162
- why: (p) => `Deferred service installation failed while flushing on the first client connection: ${p.reason}`,
163
- fix: "Call `ctx.services.ready()` explicitly after every devframe's setup has run (the first-party adapters do) so installation errors surface at startup instead of at connect time."
164
160
  }
165
161
  }
166
162
  });