@devframes/hub 0.9.1 → 0.9.3

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.
@@ -904,7 +904,18 @@ function nextAvailableDockId(views, baseId) {
904
904
  * machinery — e.g. `@vitejs/devtools-kit`'s `createPluginFromDevframe`
905
905
  * returns a Vite `Plugin` whose `devtools.setup` ultimately delegates here.
906
906
  */
907
- async function installDevframe(ctx, d, options = {}) {
907
+ /**
908
+ * Phase one of an install: run the duplication guard, serve the SPA + meta,
909
+ * register the iframe dock, and queue the definition's declarative wire
910
+ * services — everything up to (but not including) `setup(ctx)`. Returns a
911
+ * deferred setup thunk, or `null` when the devframe was deduplicated.
912
+ *
913
+ * The hub's initial batch uses this to collect every devframe's services
914
+ * across the whole hub, `ready()` them once, and only then run the setups —
915
+ * so services are ready before any setup, and a plugin can consume a service
916
+ * another plugin declared regardless of mount order.
917
+ */
918
+ async function prepareDevframe(ctx, d, options = {}) {
908
919
  const strategy = d.duplicationStrategy ?? "warn";
909
920
  const isDuplicate = ctx.docks.views.has(d.id);
910
921
  if (isDuplicate && strategy !== "duplicate") {
@@ -916,7 +927,7 @@ async function installDevframe(ctx, d, options = {}) {
916
927
  id: d.id,
917
928
  name: d.name
918
929
  });
919
- return;
930
+ return null;
920
931
  }
921
932
  const id = isDuplicate ? nextAvailableDockId(ctx.docks.views, d.id) : d.id;
922
933
  const base = options.base ?? (id === d.id ? resolveBasePath(d, "hosted") : resolveBasePath({
@@ -932,7 +943,7 @@ async function installDevframe(ctx, d, options = {}) {
932
943
  base
933
944
  });
934
945
  const distSource = d.cli.distDir;
935
- ctx.views.hostStatic(base, typeof distSource === "string" ? resolve(distSource) : distSource);
946
+ ctx.views.hostStatic(base, typeof distSource === "string" ? resolve(distSource) : distSource, d.importMetaUrl);
936
947
  }
937
948
  ctx.docks.register({
938
949
  id,
@@ -943,8 +954,21 @@ async function installDevframe(ctx, d, options = {}) {
943
954
  type: "iframe",
944
955
  url: base
945
956
  });
946
- for (const input of d.services ?? []) ctx.services.install(input, { resolveFrom: d.packageName });
947
- await d.setup(ctx);
957
+ for (const input of d.services ?? []) ctx.services.install(input, { resolveFrom: d.importMetaUrl });
958
+ return () => Promise.resolve(d.setup(ctx));
959
+ }
960
+ /**
961
+ * Install a {@link DevframeDefinition} into a hub in one call — serve its SPA,
962
+ * register its dock, ready its services, and run `setup(ctx)`. The imperative
963
+ * counterpart to the hub's declarative `devframes` list (which batches the
964
+ * phases via {@link prepareDevframe}); use it from `configure(ctx)` or
965
+ * wherever you hold the context to plug in an extra devframe after startup.
966
+ */
967
+ async function installDevframe(ctx, d, options = {}) {
968
+ const run = await prepareDevframe(ctx, d, options);
969
+ if (!run) return;
970
+ await ctx.services.ready();
971
+ await run();
948
972
  }
949
973
  //#endregion
950
974
  //#region src/node/rpc-builtins.ts
@@ -1200,4 +1224,4 @@ async function createHubContext(options) {
1200
1224
  return context;
1201
1225
  }
1202
1226
  //#endregion
1203
- export { DevframeCommandsHost as _, hubMessagesAdd as a, hubMessagesUpdate as c, hubTerminalsRestart as d, hubTerminalsTerminate as f, DevframeDocksHost as g, DevframeMessagesHost as h, hubDocksActivate as i, hubTerminalsRemove as l, DevframeTerminalsHost as m, builtinHubRpcDeclarations as n, hubMessagesClear as o, hubTerminalsWrite as p, hubCommandsExecute as r, hubMessagesRemove as s, createHubContext as t, hubTerminalsResize as u, diagnostics as v };
1227
+ export { DevframeDocksHost as _, hubMessagesAdd as a, hubMessagesUpdate as c, hubTerminalsRestart as d, hubTerminalsTerminate as f, DevframeMessagesHost as g, DevframeTerminalsHost as h, hubDocksActivate as i, hubTerminalsRemove as l, prepareDevframe as m, builtinHubRpcDeclarations as n, hubMessagesClear as o, hubTerminalsWrite as p, hubCommandsExecute as r, hubMessagesRemove as s, createHubContext as t, hubTerminalsResize as u, DevframeCommandsHost as v, diagnostics as y };
@@ -1,4 +1,4 @@
1
- import { _ as DevframeCommandsHost, a as hubMessagesAdd, c as hubMessagesUpdate, d as hubTerminalsRestart, f as hubTerminalsTerminate, g as DevframeDocksHost, h as DevframeMessagesHost, i as hubDocksActivate, l as hubTerminalsRemove, m as DevframeTerminalsHost, n as builtinHubRpcDeclarations, o as hubMessagesClear, p as hubTerminalsWrite, r as hubCommandsExecute, s as hubMessagesRemove, t as createHubContext, u as hubTerminalsResize } from "../context-90I4t0S3.mjs";
1
+ import { _ as DevframeDocksHost, a as hubMessagesAdd, c as hubMessagesUpdate, d as hubTerminalsRestart, f as hubTerminalsTerminate, g as DevframeMessagesHost, h as DevframeTerminalsHost, i as hubDocksActivate, l as hubTerminalsRemove, n as builtinHubRpcDeclarations, o as hubMessagesClear, p as hubTerminalsWrite, r as hubCommandsExecute, s as hubMessagesRemove, t as createHubContext, u as hubTerminalsResize, v as DevframeCommandsHost } from "../context-TgU_TKiY.mjs";
2
2
  import "ufo";
3
3
  import "pathe";
4
4
  import "node:process";
@@ -1,7 +1,7 @@
1
1
  import { i as InstallDevframeOptions, n as DevframeHubContext, t as CreateHubContextOptions } from "../context-BVkxwz5k.mjs";
2
2
  import { r as DEVFRAMES_HUB_BASE } from "../constants-CmESZCBq.mjs";
3
3
  import { DevframeInstanceRecord } from "devframe/internal";
4
- import { ConnectionMeta, DevframeDefinition, DevframeSseOptions, DevframeStorageScope, DevframeWsOptions, McpRouteOptions } from "devframe/types";
4
+ import { ConnectionMeta, DevframeDefinition, DevframeServiceInput, DevframeSseOptions, DevframeStorageScope, DevframeWsOptions, McpRouteOptions } from "devframe/types";
5
5
  import { DevframeAuthHandler } from "devframe/node/auth";
6
6
  import { WsOriginRegistry } from "devframe/rpc/transports/ws-server";
7
7
  import { Buffer } from "node:buffer";
@@ -114,6 +114,14 @@ interface InitHubOptions {
114
114
  * (category, icon, a `clientScript` to run in the host page, …).
115
115
  */
116
116
  devframes?: DevframesInput;
117
+ /**
118
+ * Host-level wire services to install, on top of whatever the mounted
119
+ * devframes declare. Constructed (option sets merged) at the pre-setup
120
+ * barrier, so every devframe's `setup` sees them ready. Reach for this to
121
+ * configure a shared service centrally — e.g.
122
+ * `services: [createShikiService({ themes })]`.
123
+ */
124
+ services?: DevframeServiceInput[];
117
125
  /**
118
126
  * Extra RPC declarations registered at context creation, alongside the
119
127
  * hub built-ins — forwarded to `createHubContext`'s
@@ -1,6 +1,6 @@
1
1
  import { a as normalizeHubBase, i as DOCK_RENDERERS_STATE_KEY, r as DEVFRAMES_HUB_BASE } from "../constants-C2b2cACy.mjs";
2
2
  import { a as resolveClientModuleSpecifier } from "../remote-url-Bgc7gtsP.mjs";
3
- import { t as createHubContext, v as diagnostics } from "../context-90I4t0S3.mjs";
3
+ import { m as prepareDevframe, t as createHubContext, y as diagnostics } from "../context-TgU_TKiY.mjs";
4
4
  import { joinURL, withTrailingSlash, withoutLeadingSlash } from "ufo";
5
5
  import { DEVFRAME_CONNECTION_META_FILENAME, DEVFRAME_DOCK_IMPORTS_FILENAME, DEVFRAME_MCP_ROUTE, DEVFRAME_WS_ROUTE } from "devframe/constants";
6
6
  import { createH3DevframeHost, createInstanceShell, resolveInstanceRegister } from "devframe/internal";
@@ -171,23 +171,27 @@ function initHub(options) {
171
171
  clientModuleResolution: options.clientModuleResolution
172
172
  };
173
173
  const devframes = await resolveDevframesInput(options.devframes ?? []);
174
+ for (const input of options.services ?? []) ctx.services.install(input);
175
+ const setups = [];
174
176
  for (const { devframe: def, dock } of devframes) {
175
177
  if (RESERVED_HUB_PATHS.includes(def.id)) throw diagnostics.DF8000({ id: def.id });
176
178
  if (!/^[\w.-]+$/.test(def.id)) throw diagnostics.DF8004({ id: def.id });
177
179
  const frameBase = withTrailingSlash(joinURL(base, def.id));
178
- await ctx.install(def, {
180
+ const run = await prepareDevframe(ctx, def, {
179
181
  base: frameBase,
180
182
  ...dock ? { dock } : {}
181
183
  });
184
+ if (run) setups.push(run);
182
185
  frames.push({
183
186
  id: def.id,
184
187
  base: frameBase,
185
188
  title: def.name
186
189
  });
187
190
  }
191
+ await ctx.services.ready();
192
+ for (const run of setups) await run();
188
193
  await options.configure?.(ctx);
189
194
  await options.ui?.setup?.(ctx);
190
- await ctx.services.ready();
191
195
  if (rendererRegistrations.length > 0) {
192
196
  const manifest = {};
193
197
  for (const registration of rendererRegistrations) manifest[registration.type] = {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@devframes/hub",
3
3
  "type": "module",
4
- "version": "0.9.1",
4
+ "version": "0.9.3",
5
5
  "description": "Hub layer that orchestrates devframe docks, terminals, messages, and commands on any host.",
6
6
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",
@@ -34,7 +34,7 @@
34
34
  "dist"
35
35
  ],
36
36
  "peerDependencies": {
37
- "devframe": "0.9.1"
37
+ "devframe": "0.9.3"
38
38
  },
39
39
  "dependencies": {
40
40
  "@standard-schema/spec": "^1.1.0",
@@ -52,7 +52,7 @@
52
52
  "mlly": "^1.8.2",
53
53
  "tsdown": "^0.22.14",
54
54
  "valibot": "^1.4.2",
55
- "devframe": "0.9.1"
55
+ "devframe": "0.9.3"
56
56
  },
57
57
  "scripts": {
58
58
  "build": "tsdown",