@devframes/next 0.9.8 → 0.9.10

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/client.d.mts CHANGED
@@ -5,7 +5,7 @@ import { ConnectionMeta } from "devframe";
5
5
  interface DevframeRpcState {
6
6
  /** The connected client, or `null` while the initial connect is in flight. */
7
7
  rpc: DevframeRpcClient | null;
8
- /** Live connection status — `'connecting'` until the client resolves. */
8
+ /** Live connection status, `'connecting'` until the client resolves. */
9
9
  status: DevframeConnectionStatus;
10
10
  /** The latest connection error, or `null`. */
11
11
  error: Error | null;
@@ -25,8 +25,8 @@ interface RpcProviderProps {
25
25
  connectionMeta?: ConnectionMeta;
26
26
  }
27
27
  /**
28
- * Connect to the devframe RPC backend once and provide the client — plus live
29
- * connection status — to the tree. The React counterpart to `@devframes/nuxt`'s
28
+ * Connect to the devframe RPC backend once and provide the client, plus live
29
+ * connection status, to the tree. The React counterpart to `@devframes/nuxt`'s
30
30
  * client plugin.
31
31
  *
32
32
  * Children render immediately (before the connection resolves), so your shell
package/dist/client.mjs CHANGED
@@ -10,8 +10,8 @@ const INITIAL = {
10
10
  error: null
11
11
  };
12
12
  /**
13
- * Connect to the devframe RPC backend once and provide the client — plus live
14
- * connection status — to the tree. The React counterpart to `@devframes/nuxt`'s
13
+ * Connect to the devframe RPC backend once and provide the client, plus live
14
+ * connection status, to the tree. The React counterpart to `@devframes/nuxt`'s
15
15
  * client plugin.
16
16
  *
17
17
  * Children render immediately (before the connection resolves), so your shell
@@ -10,7 +10,7 @@ interface UseDevframeHubClientOptions extends DevframeClientRuntimeOptions$1 {
10
10
  base?: string;
11
11
  }
12
12
  /**
13
- * Boot the devframes-hub **client runtime** inside a React (Next.js) page —
13
+ * Boot the devframes-hub **client runtime** inside a React (Next.js) page:
14
14
  * the browser half of {@link import('./hub').nextDevframeHub}. Connects RPC to
15
15
  * the hub (defaulting `base` to `/__devframes/`), assembles the shared
16
16
  * `DevframeClientContext`, imports each dock's client script into the page,
@@ -4,7 +4,7 @@ import { createDevframeClientRuntime } from "@devframes/hub/client";
4
4
  import { DEVFRAMES_HUB_BASE } from "@devframes/hub/constants";
5
5
  //#region src/hub-client.tsx
6
6
  /**
7
- * Boot the devframes-hub **client runtime** inside a React (Next.js) page —
7
+ * Boot the devframes-hub **client runtime** inside a React (Next.js) page:
8
8
  * the browser half of {@link import('./hub').nextDevframeHub}. Connects RPC to
9
9
  * the hub (defaulting `base` to `/__devframes/`), assembles the shared
10
10
  * `DevframeClientContext`, imports each dock's client script into the page,
package/dist/hub.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { DevframeHubUi, HubInstance, InitHubOptions } from "@devframes/hub/initiate";
2
- import { ConnectionMeta, DevframeHost, DevframeNodeContext, DevframeStorageScope } from "devframe";
2
+ import { ConnectionMeta, DevframeHost, DevframeNodeContext, DevframeStorageScope, McpAuthorization } from "devframe";
3
3
  //#region src/host.d.ts
4
4
  interface CreateDevframeNextHostOptions {
5
5
  /**
@@ -16,12 +16,21 @@ interface CreateDevframeNextHostOptions {
16
16
  /**
17
17
  * Initial connection meta served at every base registered via
18
18
  * {@link DevframeHost.mountConnectionMeta}. Usually unknown until the
19
- * side-car RPC/WS server has started — publish it later with
19
+ * side-car RPC/WS server has started, so publish it later with
20
20
  * {@link DevframeNextHost.setConnectionMeta}.
21
21
  */
22
22
  connectionMeta?: ConnectionMeta;
23
23
  }
24
24
  interface DevframeNextHostMcpOptions {
25
+ /**
26
+ * Optional identity check layered on the origin gate. Defaults to
27
+ * origin-only (`false`), trusting same-machine callers. A bearer token
28
+ * string (matched in constant time) or a `(request) => boolean` callback
29
+ * hardens the route when a same-machine process is not your trust boundary;
30
+ * see {@link McpAuthorization}. Back a bearer with an environment variable,
31
+ * never a literal.
32
+ */
33
+ authorization?: McpAuthorization;
25
34
  /** Name reported in the MCP handshake. Default: `'devframe (next)'`. */
26
35
  serverName?: string;
27
36
  /** Version reported in the MCP handshake. Default: `'0.0.0'`. */
@@ -31,7 +40,8 @@ interface DevframeNextHostMcpOptions {
31
40
  /**
32
41
  * Origin allow-list beyond the loopback default. `false` disables the
33
42
  * origin gate entirely. Note the MCP route rejects `Origin`-less requests
34
- * (see `createMcpFetchHandler`).
43
+ * (see `createMcpFetchHandler`). This hardens the request; `authorization`
44
+ * proves identity.
35
45
  */
36
46
  allowedOrigins?: readonly string[] | false;
37
47
  }
@@ -44,7 +54,7 @@ interface DevframeNextHost {
44
54
  host: DevframeHost;
45
55
  /**
46
56
  * A WHATWG-`fetch` handler that serves every mounted SPA (with SPA
47
- * fallback, correct content types, and path-traversal guarding — all from
57
+ * fallback, correct content types, and path-traversal guarding, all from
48
58
  * devframe's own `serveStaticHandler`) and answers `<base>/__connection.json`
49
59
  * for each base registered via `mountConnectionMeta`. Delegate a Next App
50
60
  * Router route handler straight to it:
@@ -63,12 +73,12 @@ interface DevframeNextHost {
63
73
  */
64
74
  setConnectionMeta: (meta: ConnectionMeta) => void;
65
75
  /**
66
- * Serve an MCP Streamable-HTTP endpoint at `path` **in-process** — on the
76
+ * Serve an MCP Streamable-HTTP endpoint at `path` **in-process**, on the
67
77
  * Next app's own origin, through the same catch-all route as the SPAs (the
68
78
  * `/_next/mcp` shape). Built on `createMcpFetchHandler` from
69
- * `devframe/adapters/mcp` (imported lazily: `@modelcontextprotocol/server`
70
- * stays an optional peer). Advertise the path in the connection meta
71
- * (`mcp: { path }` — same origin, no port) and register the instance via
79
+ * `devframe/adapters/mcp` (imported lazily, so the MCP SDK stays out of
80
+ * the app's bundle graph). Advertise the path in the connection meta
81
+ * (`mcp: { path }`, same origin, no port) and register the instance via
72
82
  * `registerDevframeInstance` so `devframe connect` can discover it.
73
83
  */
74
84
  mountMcp: (ctx: DevframeNodeContext, path: string, options?: DevframeNextHostMcpOptions) => Promise<{
@@ -81,7 +91,7 @@ interface DevframeNextHost {
81
91
  * route delegates to.
82
92
  *
83
93
  * This is the hosted-adapter counterpart to `devframeViteBridge` for the Next
84
- * runtime, which — being webpack/Turbopack rather than Vite — can't reuse the
94
+ * runtime, which (being webpack/Turbopack rather than Vite) can't reuse the
85
95
  * Vite middleware path. Instead of hand-rolling static serving in a route
86
96
  * handler, static mounts are registered on an internal h3 app and served
87
97
  * through devframe's shared `serveStaticHandler` (`app.fetch` makes h3 a
@@ -95,7 +105,7 @@ declare function createDevframeNextHost(options: CreateDevframeNextHostOptions):
95
105
  //#region src/hub.d.ts
96
106
  interface NextDevframeHubOptions {
97
107
  /**
98
- * Mount base the hub answers under — every frame lives at `<base><id>/`,
108
+ * Mount base the hub answers under; every frame lives at `<base><id>/`,
99
109
  * so the App Router needs one catch-all route under it. Default:
100
110
  * `/__devframes/`.
101
111
  */
@@ -113,7 +123,7 @@ interface NextDevframeHubOptions {
113
123
  /**
114
124
  * Devframes to mount. Load built-in plugin packages through a
115
125
  * bundler-ignored dynamic `import()` (their node code + `import.meta.url`
116
- * dist lookups don't survive static Next bundling) and pass them here —
126
+ * dist lookups don't survive static Next bundling) and pass them here, where
117
127
  * `initHub` resolves async/factory entries.
118
128
  */
119
129
  devframes?: InitHubOptions['devframes'];
@@ -133,8 +143,11 @@ interface NextDevframeHubOptions {
133
143
  /** The hub's single auth gate. Gates by default; `false` opts out. */
134
144
  auth?: InitHubOptions['auth'];
135
145
  /**
136
- * Expose the aggregate MCP endpoint at `<base>__mcp`. Default: `true`
137
- * (the Next hub's agent surface rides the same catch-all route).
146
+ * Expose the aggregate MCP endpoint at `<base>__mcp`. Defaults to `'auto'`
147
+ * (mount once any mounted devframe exposes an agent surface); `true`
148
+ * mounts it unconditionally with the
149
+ * loopback origin gate (trusting same-machine callers), an object opts
150
+ * into an `authorization` identity check, `false` keeps it off.
138
151
  */
139
152
  mcp?: InitHubOptions['mcp'];
140
153
  /** Public origin the Next app is reachable at. Default: derived from `PORT`. */
@@ -152,12 +165,13 @@ interface NextDevframeHubOptions {
152
165
  * Build a devframes-hub for a Next.js App Router app: one `initHub()` call
153
166
  * mounting every devframe under `<base><id>/` behind one web-standard
154
167
  * `handler`, with the RPC socket on a side-car (Next routes can't accept WS
155
- * upgrades) and the aggregate MCP route on by default. The UI defaults to
168
+ * upgrades) and the aggregate MCP route mounted on demand (the `'auto'`
169
+ * default; pass `mcp` to force or disable it). The UI defaults to
156
170
  * `@devframes/hub-ui`'s `createUi()`, loaded lazily via a bundler-ignored
157
171
  * dynamic `import()` so its asset lookups resolve at request time; pass `ui`
158
172
  * to swap it or `ui: false` for a headless hub.
159
173
  *
160
- * Prefer {@link nextDevframeHub} at a route module — it memoizes this on
174
+ * Prefer {@link nextDevframeHub} at a route module: it memoizes this on
161
175
  * `globalThis` so Next's dev-time route re-evaluation reuses one instance
162
176
  * instead of leaking a side-car per reload.
163
177
  */
package/dist/hub.mjs CHANGED
@@ -16,7 +16,7 @@ function stripTrailingSlash(base) {
16
16
  * route delegates to.
17
17
  *
18
18
  * This is the hosted-adapter counterpart to `devframeViteBridge` for the Next
19
- * runtime, which — being webpack/Turbopack rather than Vite — can't reuse the
19
+ * runtime, which (being webpack/Turbopack rather than Vite) can't reuse the
20
20
  * Vite middleware path. Instead of hand-rolling static serving in a route
21
21
  * handler, static mounts are registered on an internal h3 app and served
22
22
  * through devframe's shared `serveStaticHandler` (`app.fetch` makes h3 a
@@ -66,6 +66,7 @@ function createDevframeNextHost(options) {
66
66
  serverName: mcpOptions.serverName ?? "devframe (next)",
67
67
  serverVersion: mcpOptions.serverVersion ?? "0.0.0",
68
68
  exposeSharedState: mcpOptions.exposeSharedState ?? true,
69
+ authorization: mcpOptions.authorization,
69
70
  allowedOrigins: mcpOptions.allowedOrigins
70
71
  });
71
72
  const key = stripTrailingSlash(path);
@@ -83,12 +84,13 @@ function createDevframeNextHost(options) {
83
84
  * Build a devframes-hub for a Next.js App Router app: one `initHub()` call
84
85
  * mounting every devframe under `<base><id>/` behind one web-standard
85
86
  * `handler`, with the RPC socket on a side-car (Next routes can't accept WS
86
- * upgrades) and the aggregate MCP route on by default. The UI defaults to
87
+ * upgrades) and the aggregate MCP route mounted on demand (the `'auto'`
88
+ * default; pass `mcp` to force or disable it). The UI defaults to
87
89
  * `@devframes/hub-ui`'s `createUi()`, loaded lazily via a bundler-ignored
88
90
  * dynamic `import()` so its asset lookups resolve at request time; pass `ui`
89
91
  * to swap it or `ui: false` for a headless hub.
90
92
  *
91
- * Prefer {@link nextDevframeHub} at a route module — it memoizes this on
93
+ * Prefer {@link nextDevframeHub} at a route module: it memoizes this on
92
94
  * `globalThis` so Next's dev-time route re-evaluation reuses one instance
93
95
  * instead of leaking a side-car per reload.
94
96
  */
@@ -101,8 +103,9 @@ async function createNextDevframeHub(options = {}) {
101
103
  ...options.host != null ? { host: options.host } : {},
102
104
  ...options.origin != null ? { origin: options.origin } : {},
103
105
  auth: options.auth,
106
+ /** Next route handlers can't accept WS upgrades, so always a side-car socket. */
104
107
  ws: options.port != null ? { port: options.port } : { sidecar: true },
105
- mcp: options.mcp ?? true,
108
+ ...options.mcp !== void 0 ? { mcp: options.mcp } : {},
106
109
  ...ui ? { ui } : {},
107
110
  ...options.renderers ? { renderers: options.renderers } : {},
108
111
  ...options.rpcDeclarations ? { rpcDeclarations: options.rpcDeclarations } : {},
@@ -170,7 +173,7 @@ function nextDevframeHub(options = {}) {
170
173
  * Load `@devframes/hub-ui`'s default UI through a bundler-ignored dynamic
171
174
  * `import()`: `createUi()` resolves its prebuilt assets via `import.meta.url`,
172
175
  * which only points at the published `dist` when Node loads the package at
173
- * request time — a static import would be rewritten into a Next server chunk.
176
+ * request time, since a static import would be rewritten into a Next server chunk.
174
177
  */
175
178
  async function loadDefaultUi() {
176
179
  return (await import(
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
1
  //#region src/index.ts
2
- throw new Error("[@devframes/next] has no root export. Import from a scoped subpath instead:\n • \"@devframes/next/single\" (+ \"/single/client\") — host one devframe's SPA\n • \"@devframes/next/hub\" (+ \"/hub/client\") — mount a devframes-hub\n");
2
+ throw new Error("[@devframes/next] has no root export. Import from a scoped subpath instead:\n • \"@devframes/next/single\" (+ \"/single/client\"): host one devframe's SPA\n • \"@devframes/next/hub\" (+ \"/hub/client\"): mount a devframes-hub\n");
3
3
  //#endregion
4
4
  export {};
package/dist/single.d.mts CHANGED
@@ -33,7 +33,7 @@ declare function withDevframe<T extends DevframeNextConfig>(nextConfig?: T): T;
33
33
  //#region src/handler.d.ts
34
34
  interface CreateDevframeNextHandlerOptions {
35
35
  /**
36
- * Mount base for the SPA. Defaults to `def.basePath ?? '/__<id>/'` — the
36
+ * Mount base for the SPA. Defaults to `def.basePath ?? '/__<id>/'`, the
37
37
  * hosted-adapter default, so the devframe shares the Next app's origin
38
38
  * without colliding with its routes.
39
39
  */
@@ -57,11 +57,12 @@ interface CreateDevframeNextHandlerOptions {
57
57
  /** Override where persisted devframe state lives (defaults under the cwd / home). */
58
58
  getStorageDir?: (scope: DevframeStorageScope) => string;
59
59
  /**
60
- * Expose the route-based MCP server (Streamable-HTTP) at `<base>__mcp` —
60
+ * Expose the route-based MCP server (Streamable-HTTP) at `<base>__mcp`,
61
61
  * on the Next app's own origin, through the same catch-all route as the
62
- * SPA — and advertise it in the handler's `__connection.json`. Overrides
63
- * `def.cli?.mcp`, `undefined` falls through to it, `false` disables the
64
- * route regardless.
62
+ * SPA, and advertise it in the handler's `__connection.json`. Overrides
63
+ * `def.cli?.mcp`, `undefined` falls through to it, then to the `'auto'`
64
+ * default (mount once the agent surface is non-empty); `false` disables
65
+ * the route regardless.
65
66
  */
66
67
  mcp?: InitDevframeOptions['mcp'];
67
68
  /**
@@ -85,7 +86,7 @@ interface DevframeNextHandler {
85
86
  close: () => Promise<void>;
86
87
  }
87
88
  /**
88
- * Host a **single** devframe from a Next.js App Router app — the Next
89
+ * Host a **single** devframe from a Next.js App Router app: the Next
89
90
  * counterpart to `devframeViteBridge`, reduced to memoization + defaults over
90
91
  * `initDevframe` (Next's route handlers can't accept WS upgrades, so the
91
92
  * RPC socket lives on the instance's side-car port, advertised at
package/dist/single.mjs CHANGED
@@ -52,7 +52,7 @@ function defaultGetStorageDir(scope) {
52
52
  return join(homedir(), ".devframe");
53
53
  }
54
54
  /**
55
- * Host a **single** devframe from a Next.js App Router app — the Next
55
+ * Host a **single** devframe from a Next.js App Router app: the Next
56
56
  * counterpart to `devframeViteBridge`, reduced to memoization + defaults over
57
57
  * `initDevframe` (Next's route handlers can't accept WS upgrades, so the
58
58
  * RPC socket lives on the instance's side-car port, advertised at
@@ -85,8 +85,17 @@ function createDevframeNextHandler(def, options = {}) {
85
85
  distDir,
86
86
  host: options.host,
87
87
  flags: options.flags,
88
+ /**
89
+ * Gate by default: an unset `auth` defers to the instance (devframe's
90
+ * interactive OTP unless `cli.auth` opts out). `false` opts out.
91
+ */
88
92
  auth: options.auth,
89
93
  mcp: options.mcp,
94
+ /**
95
+ * Next's route handlers never see WebSocket upgrades, so the RPC socket
96
+ * lives on a side-car server (on `options.port` when pinned, otherwise
97
+ * a free port), advertised via `<base>__connection.json`.
98
+ */
90
99
  ws: options.port != null ? { port: options.port } : { sidecar: true },
91
100
  ...options.resolveOrigin ? { origin: options.resolveOrigin } : {},
92
101
  getStorageDir: options.getStorageDir ?? defaultGetStorageDir
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@devframes/next",
3
3
  "type": "module",
4
- "version": "0.9.8",
4
+ "version": "0.9.10",
5
5
  "description": "Next.js host integration that serves mounted devframes from an App Router route.",
6
6
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",
@@ -47,9 +47,9 @@
47
47
  "dist"
48
48
  ],
49
49
  "peerDependencies": {
50
- "@devframes/hub": "0.9.8",
51
- "@devframes/hub-ui": "0.9.8",
52
- "devframe": "0.9.8",
50
+ "@devframes/hub": "0.9.10",
51
+ "@devframes/hub-ui": "0.9.10",
52
+ "devframe": "0.9.10",
53
53
  "next": "^14.0.0 || ^15.0.0 || ^16.0.0",
54
54
  "react": "^18.0.0 || ^19.0.0"
55
55
  },
@@ -71,11 +71,11 @@
71
71
  "h3": "^2.0.1-rc.29"
72
72
  },
73
73
  "devDependencies": {
74
- "@devframes/hub": "0.9.8",
75
- "@devframes/hub-ui": "0.9.8",
74
+ "@devframes/hub": "0.9.10",
75
+ "@devframes/hub-ui": "0.9.10",
76
76
  "@types/node": "^26.4.0",
77
77
  "@types/react": "^19.2.18",
78
- "devframe": "0.9.8",
78
+ "devframe": "0.9.10",
79
79
  "react": "^19.2.8",
80
80
  "tsdown": "^0.22.14"
81
81
  },