devframe 0.8.2 → 0.9.0-beta.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.
Files changed (127) hide show
  1. package/dist/_shared-BPmX9fqK.d.mts +41 -0
  2. package/dist/_shared-CbZ_yhbz.mjs +68 -0
  3. package/dist/adapters/build.d.mts +10 -12
  4. package/dist/adapters/build.mjs +26 -29
  5. package/dist/adapters/cac.d.mts +1 -1
  6. package/dist/adapters/cac.mjs +156 -1
  7. package/dist/adapters/dev.d.mts +38 -46
  8. package/dist/adapters/dev.mjs +2 -1
  9. package/dist/adapters/embedded.d.mts +1 -1
  10. package/dist/adapters/initiate.d.mts +224 -0
  11. package/dist/adapters/initiate.mjs +2 -0
  12. package/dist/adapters/mcp.d.mts +24 -7
  13. package/dist/adapters/mcp.mjs +2 -2
  14. package/dist/{agent-tool-name-C3b5vEwJ.mjs → agent-tool-name-EgfoFO8C.mjs} +0 -3
  15. package/dist/cli/main.d.mts +0 -2
  16. package/dist/cli/main.mjs +4 -8
  17. package/dist/client/index.d.mts +71 -7
  18. package/dist/client/index.mjs +720 -1540
  19. package/dist/constants.d.mts +28 -7
  20. package/dist/constants.mjs +28 -7
  21. package/dist/{context-DoSozfvx.d.mts → context-B3YUu_95.d.mts} +19 -1
  22. package/dist/{host-h3-D2hYZvDK.mjs → context-CEe4PBz1.mjs} +25 -557
  23. package/dist/{context-CBg8iRbQ.mjs → context-xdynGSLP.mjs} +10 -1
  24. package/dist/dev--rAPzbvO.mjs +239 -0
  25. package/dist/{devframe-mQ4qZAuo.d.mts → devframe-DJMg0WLe.d.mts} +181 -134
  26. package/dist/{diagnostics-hwjXp_UV.mjs → diagnostics-CD8nlgll.mjs} +1 -3
  27. package/dist/{diagnostics-D7wM2cwM.mjs → diagnostics-DOQPnQmX.mjs} +51 -5
  28. package/dist/dist-eNI9qM_I.mjs +228 -0
  29. package/dist/host-agent-xLCSe65D.mjs +264 -0
  30. package/dist/host-h3-Crkzm42q.mjs +26 -0
  31. package/dist/{fetch-BKaD0Vb3.mjs → http-DYpK0cUi.mjs} +42 -11
  32. package/dist/{index-b64Uuhy2.d.mts → index-CB-fSUyn.d.mts} +2 -2
  33. package/dist/{index-Dbw1p5ch.d.mts → index-tdrk1bzV.d.mts} +3 -32
  34. package/dist/index.d.mts +12 -5
  35. package/dist/index.mjs +8 -1
  36. package/dist/{instance-registry-BnnA2Eoh.mjs → instance-registry-WvQkt42E.mjs} +9 -8
  37. package/dist/instance-shell-CMFyszWJ.mjs +486 -0
  38. package/dist/instance-shell-CljiKq1c.d.mts +255 -0
  39. package/dist/internal/index.d.mts +397 -0
  40. package/dist/internal/index.mjs +9 -0
  41. package/dist/node/auth.d.mts +2 -2
  42. package/dist/node/auth.mjs +1 -1
  43. package/dist/node/hub-internals.d.mts +2 -14
  44. package/dist/node/hub-internals.mjs +2 -2
  45. package/dist/node/index.d.mts +4 -268
  46. package/dist/node/index.mjs +3 -5
  47. package/dist/nostics-CzECRXpE.mjs +59 -0
  48. package/dist/nostics-SPGDgHEP.d.mts +33 -0
  49. package/dist/recipes/common-rpc-functions.d.mts +4 -4
  50. package/dist/recipes/interactive-auth.d.mts +3 -3
  51. package/dist/recipes/interactive-auth.mjs +8 -8
  52. package/dist/remote-assets-Bg4gCUZ_.d.mts +123 -0
  53. package/dist/remote-assets-nTTxY2MU.mjs +636 -0
  54. package/dist/rolldown-runtime-JspESFgx.mjs +35 -0
  55. package/dist/rpc/dump.d.mts +77 -1
  56. package/dist/rpc/dump.mjs +1 -1
  57. package/dist/rpc/index.d.mts +3 -3
  58. package/dist/rpc/index.mjs +4 -18
  59. package/dist/rpc/transports/sse-client.d.mts +2 -0
  60. package/dist/rpc/transports/sse-client.mjs +142 -0
  61. package/dist/rpc/transports/sse-server.d.mts +61 -0
  62. package/dist/rpc/transports/sse-server.mjs +209 -0
  63. package/dist/rpc/transports/ws-bun.d.mts +35 -0
  64. package/dist/rpc/transports/ws-bun.mjs +31 -0
  65. package/dist/rpc/transports/ws-client.d.mts +1 -1
  66. package/dist/rpc/transports/ws-client.mjs +10 -18
  67. package/dist/rpc/transports/ws-server.d.mts +2 -2
  68. package/dist/rpc/transports/ws-server.mjs +2 -235
  69. package/dist/rpc-core-Cc4lucI0.d.mts +48 -0
  70. package/dist/rpc-core-DMTe-hLo.mjs +81 -0
  71. package/dist/{serialization-C8Mnw9hK.mjs → serialization-BGzEwAdr.mjs} +2 -2
  72. package/dist/{shared-state-6kHolYZy.mjs → shared-state-fRRbRUtD.mjs} +1 -1
  73. package/dist/sse-client-CFBOIaUi.d.mts +37 -0
  74. package/dist/state-Cc1IeSmQ.mjs +1291 -0
  75. package/dist/{dump-CgZShDRB.mjs → static-BPZ1_OPA.mjs} +3 -266
  76. package/dist/storage-CYye7P7L.mjs +137 -0
  77. package/dist/types/index.d.mts +6 -4
  78. package/dist/types/index.mjs +1 -6
  79. package/dist/{types-CnJSgRVa.d.mts → types-Djq7CBXh.d.mts} +0 -7
  80. package/dist/utils/agent-tool-name.d.mts +0 -3
  81. package/dist/utils/agent-tool-name.mjs +0 -3
  82. package/dist/utils/events.d.mts +1 -1
  83. package/dist/utils/get-port.d.mts +17 -0
  84. package/dist/utils/get-port.mjs +2 -0
  85. package/dist/utils/launch-editor.mjs +1 -25
  86. package/dist/utils/nostics.d.mts +2 -0
  87. package/dist/utils/nostics.mjs +2 -0
  88. package/dist/utils/open.d.mts +2 -10
  89. package/dist/utils/open.mjs +56 -1
  90. package/dist/utils/remote-assets.d.mts +15 -0
  91. package/dist/utils/remote-assets.mjs +2 -0
  92. package/dist/utils/serve-static.d.mts +13 -5
  93. package/dist/utils/serve-static.mjs +119 -9
  94. package/dist/utils/shared-state.d.mts +1 -1
  95. package/dist/utils/shared-state.mjs +1 -1
  96. package/dist/utils/simple-schema.d.mts +101 -1
  97. package/dist/utils/streaming-channel.d.mts +1 -1
  98. package/dist/validation-CpXFB6Dz.mjs +266 -0
  99. package/dist/wire-codec-0K-o5MYW.mjs +56 -0
  100. package/dist/{ws-client-B6Tnr0ic.d.mts → ws-client-DhjNyQo3.d.mts} +7 -2
  101. package/dist/ws-server-BdSLrhxE.mjs +267 -0
  102. package/dist/{ws-server-uKQcClcJ.d.mts → ws-server-D1d3QM9f.d.mts} +90 -9
  103. package/package.json +13 -12
  104. package/skills/devframe/SKILL.md +91 -93
  105. package/dist/_shared-bWRzeSa0.mjs +0 -19
  106. package/dist/adapters/cli.d.mts +0 -11
  107. package/dist/adapters/cli.mjs +0 -6
  108. package/dist/cac-D4_9ok0z.mjs +0 -157
  109. package/dist/dev-Bc49u3qg.mjs +0 -439
  110. package/dist/diagnostics-reporter-CsIG85Q5.mjs +0 -38
  111. package/dist/helpers/vite.d.mts +0 -100
  112. package/dist/helpers/vite.mjs +0 -105
  113. package/dist/http-C4T68YV6.mjs +0 -38
  114. package/dist/index-vAX6bYuc.d.mts +0 -78
  115. package/dist/open-Deb5xmIT.mjs +0 -547
  116. package/dist/recipes/open-helpers.d.mts +0 -6
  117. package/dist/recipes/open-helpers.mjs +0 -6
  118. package/dist/server-CD8XmBXl.mjs +0 -167
  119. package/dist/server-UHWae43Q.d.mts +0 -149
  120. package/dist/simple-schema-BDzLeJDk.d.mts +0 -102
  121. package/dist/state-BeUHDDjk.mjs +0 -108
  122. package/dist/storage-CTNVbuFB.mjs +0 -1122
  123. package/dist/utils/promise.d.mts +0 -8
  124. package/dist/utils/promise.mjs +0 -15
  125. package/dist/utils/scope.d.mts +0 -11
  126. package/dist/utils/scope.mjs +0 -15
  127. package/skills/devframe/templates/spa-devframe.ts +0 -38
@@ -1,157 +0,0 @@
1
- import { n as colors } from "./diagnostics-reporter-CsIG85Q5.mjs";
2
- import { createBuild } from "./adapters/build.mjs";
3
- import { n as resolveDevServerPort, t as createDevServer } from "./dev-Bc49u3qg.mjs";
4
- import process from "node:process";
5
- import cac$1 from "cac";
6
- //#region src/adapters/flags.ts
7
- /**
8
- * Identity helper that preserves the literal schema-map type — use this
9
- * so `InferCliFlags<typeof myFlags>` resolves to the right object shape.
10
- *
11
- * ```ts
12
- * const appFlags = defineCliFlags({
13
- * depth: v.pipe(v.number(), v.integer()),
14
- * config: v.optional(v.string()),
15
- * })
16
- *
17
- * defineDevframe({
18
- * cli: { flags: appFlags },
19
- * setup(ctx, info) {
20
- * const flags = info.flags as InferCliFlags<typeof appFlags>
21
- * flags.depth // number
22
- * flags.config // string | undefined
23
- * },
24
- * })
25
- * ```
26
- */
27
- function defineCliFlags(flags) {
28
- return flags;
29
- }
30
- /**
31
- * Best-effort, dependency-free probe of a schema to decide whether the
32
- * corresponding CAC option takes a value. Duck-types the `type` /
33
- * `wrapped` / `inner` / `pipe` fields exposed by valibot and by devframe's
34
- * built-in `s` builder, unwrapping `optional` / `nullable` / `nullish` /
35
- * `pipe` wrappers then matching on the inner kind. Validators that don't
36
- * expose these fields (e.g. zod) fall through to a value-taking option.
37
- */
38
- function getSchemaKind(schema) {
39
- let current = schema;
40
- while (current) {
41
- const kind = current.type;
42
- if (kind === "optional" || kind === "nullable" || kind === "nullish" || kind === "undefined") {
43
- current = current.wrapped ?? current.inner;
44
- continue;
45
- }
46
- if (kind === "pipe" && Array.isArray(current.pipe) && current.pipe.length > 0) {
47
- current = current.pipe[0];
48
- continue;
49
- }
50
- return kind ?? "unknown";
51
- }
52
- return "unknown";
53
- }
54
- /** Whether the CAC option for this schema should be a boolean flag. */
55
- function isBooleanFlag(schema) {
56
- return getSchemaKind(schema) === "boolean";
57
- }
58
- /** Validate the raw cac-parsed bag against a {@link CliFlagsSchema}. */
59
- function parseCliFlags(schema, raw) {
60
- const flags = {};
61
- const issues = [];
62
- for (const [key, fieldSchema] of Object.entries(schema)) {
63
- const result = fieldSchema["~standard"].validate(raw[key]);
64
- if (result instanceof Promise) {
65
- issues.push(`--${toKebab(key)}: async flag validation is not supported`);
66
- continue;
67
- }
68
- if (result.issues) issues.push(`--${toKebab(key)}: ${result.issues.map((i) => i.message).join(", ")}`);
69
- else flags[key] = result.value;
70
- }
71
- for (const [key, value] of Object.entries(raw)) if (!(key in schema) && !(key in flags)) flags[key] = value;
72
- return issues.length ? {
73
- flags,
74
- issues
75
- } : { flags };
76
- }
77
- function toKebab(camel) {
78
- return camel.replaceAll(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
79
- }
80
- /** Kebab-case a schema key for CAC option registration. */
81
- function flagKeyToOption(camel) {
82
- return toKebab(camel);
83
- }
84
- //#endregion
85
- //#region src/adapters/cac.ts
86
- /**
87
- * Wrap a {@link DevframeDefinition} in a `cac`-powered command-line
88
- * interface exposing `dev` / `build` / `mcp` subcommands.
89
- *
90
- * Requires the optional `cac` peer dependency.
91
- */
92
- function createCac(d, options = {}) {
93
- const defaultPort = options.defaultPort ?? d.cli?.port ?? 9999;
94
- const defaultHost = d.cli?.host ?? "localhost";
95
- const cli = cac$1(d.cli?.command ?? d.id);
96
- const devCommand = cli.command("[...args]", "Start a local dev server").option("--port <port>", "Port to listen on").option("--host <host>", "Host to bind to", { default: defaultHost }).option("--open", "Open the browser on start").option("--no-open", "Do not open the browser").option("--no-auth", "Disable the interactive authentication gate").option("--mcp", "Expose an MCP server over HTTP at /__mcp (use --no-mcp to disable) [experimental]");
97
- if (d.cli?.flags) for (const [key, schema] of Object.entries(d.cli.flags)) {
98
- const optionName = flagKeyToOption(key);
99
- const description = schema.description ?? "";
100
- if (isBooleanFlag(schema)) devCommand.option(`--${optionName}`, description);
101
- else devCommand.option(`--${optionName} <value>`, description);
102
- }
103
- devCommand.action(async (_args, rawFlags) => {
104
- const flags = resolveTypedFlags(d, rawFlags);
105
- const host = flags.host ?? defaultHost;
106
- const port = flags.port ?? await resolveDevServerPort(d, {
107
- host,
108
- defaultPort
109
- });
110
- const mcp = flags.mcp;
111
- await createDevServer(d, {
112
- host,
113
- port,
114
- flags,
115
- mcp,
116
- onReady: options.onReady
117
- });
118
- });
119
- if (d.capabilities?.build !== false) cli.command("build", "Build a self-contained static deploy of the devframe").option("--out-dir <outDir>", "Output directory", { default: "dist-static" }).option("--base <base>", "URL base", { default: "/" }).option("--pretty", "Pretty-print dump JSON (larger on disk)").action(async (flags) => {
120
- await createBuild(d, {
121
- outDir: flags.outDir,
122
- base: flags.base,
123
- pretty: flags.pretty
124
- });
125
- });
126
- cli.command("mcp", "Start an MCP server exposing agent-facing tools (stdio) [experimental]").action(async () => {
127
- const { createMcpServer } = await import("./adapters/mcp.mjs");
128
- await createMcpServer(d, {
129
- transport: "stdio",
130
- onReady: ({ transport }) => {
131
- console.error(`[devframe] "${d.id}" MCP server ready (${transport})`);
132
- }
133
- });
134
- });
135
- d.cli?.configure?.(cli);
136
- options.configureCli?.(cli);
137
- cli.help();
138
- cli.version("0.0.0");
139
- return {
140
- cli,
141
- async parse(argv = process.argv) {
142
- cli.parse(argv, { run: false });
143
- await cli.runMatchedCommand();
144
- }
145
- };
146
- }
147
- function resolveTypedFlags(d, raw) {
148
- if (!d.cli?.flags) return raw;
149
- const { flags, issues } = parseCliFlags(d.cli.flags, raw);
150
- if (issues?.length) {
151
- for (const issue of issues) console.error(colors.red`[devframe] invalid flag — ${issue}`);
152
- process.exit(1);
153
- }
154
- return flags;
155
- }
156
- //#endregion
157
- export { defineCliFlags as n, parseCliFlags as r, createCac as t };
@@ -1,439 +0,0 @@
1
- import { DEVFRAME_CONNECTION_META_FILENAME } from "./constants.mjs";
2
- import { n as createHostContext, t as createH3DevframeHost } from "./host-h3-D2hYZvDK.mjs";
3
- import { t as diagnostics } from "./diagnostics-D7wM2cwM.mjs";
4
- import { r as registerDevframeInstance } from "./instance-registry-BnnA2Eoh.mjs";
5
- import { i as normalizeHttpServerUrl, t as startHttpAndWs } from "./server-CD8XmBXl.mjs";
6
- import { n as resolveBasePath, t as normalizeBasePath } from "./_shared-bWRzeSa0.mjs";
7
- import { t as open } from "./open-Deb5xmIT.mjs";
8
- import { mountStaticHandler } from "./utils/serve-static.mjs";
9
- import { createInteractiveAuth } from "./recipes/interactive-auth.mjs";
10
- import { resolve } from "pathe";
11
- import process$1 from "node:process";
12
- import { networkInterfaces } from "node:os";
13
- import { H3 } from "h3";
14
- import { createServer } from "node:net";
15
- import { joinURL, withBase, withLeadingSlash, withoutLeadingSlash } from "ufo";
16
- //#region ../../node_modules/.pnpm/get-port-please@3.2.0/node_modules/get-port-please/dist/index.mjs
17
- const unsafePorts = /* @__PURE__ */ new Set([
18
- 1,
19
- 7,
20
- 9,
21
- 11,
22
- 13,
23
- 15,
24
- 17,
25
- 19,
26
- 20,
27
- 21,
28
- 22,
29
- 23,
30
- 25,
31
- 37,
32
- 42,
33
- 43,
34
- 53,
35
- 69,
36
- 77,
37
- 79,
38
- 87,
39
- 95,
40
- 101,
41
- 102,
42
- 103,
43
- 104,
44
- 109,
45
- 110,
46
- 111,
47
- 113,
48
- 115,
49
- 117,
50
- 119,
51
- 123,
52
- 135,
53
- 137,
54
- 139,
55
- 143,
56
- 161,
57
- 179,
58
- 389,
59
- 427,
60
- 465,
61
- 512,
62
- 513,
63
- 514,
64
- 515,
65
- 526,
66
- 530,
67
- 531,
68
- 532,
69
- 540,
70
- 548,
71
- 554,
72
- 556,
73
- 563,
74
- 587,
75
- 601,
76
- 636,
77
- 989,
78
- 990,
79
- 993,
80
- 995,
81
- 1719,
82
- 1720,
83
- 1723,
84
- 2049,
85
- 3659,
86
- 4045,
87
- 5060,
88
- 5061,
89
- 6e3,
90
- 6566,
91
- 6665,
92
- 6666,
93
- 6667,
94
- 6668,
95
- 6669,
96
- 6697,
97
- 10080
98
- ]);
99
- function isUnsafePort(port) {
100
- return unsafePorts.has(port);
101
- }
102
- function isSafePort(port) {
103
- return !isUnsafePort(port);
104
- }
105
- var GetPortError = class extends Error {
106
- constructor(message, opts) {
107
- super(message, opts);
108
- this.message = message;
109
- }
110
- name = "GetPortError";
111
- };
112
- function _log(verbose, message) {
113
- if (verbose) console.log(`[get-port] ${message}`);
114
- }
115
- function _generateRange(from, to) {
116
- if (to < from) return [];
117
- const r = [];
118
- for (let index = from; index <= to; index++) r.push(index);
119
- return r;
120
- }
121
- function _tryPort(port, host) {
122
- return new Promise((resolve) => {
123
- const server = createServer();
124
- server.unref();
125
- server.on("error", () => {
126
- resolve(false);
127
- });
128
- server.listen({
129
- port,
130
- host
131
- }, () => {
132
- const { port: port2 } = server.address();
133
- server.close(() => {
134
- resolve(isSafePort(port2) && port2);
135
- });
136
- });
137
- });
138
- }
139
- function _getLocalHosts(additional) {
140
- const hosts = new Set(additional);
141
- for (const _interface of Object.values(networkInterfaces())) for (const config of _interface || []) if (config.address && !config.internal && !config.address.startsWith("fe80::") && !config.address.startsWith("169.254")) hosts.add(config.address);
142
- return [...hosts];
143
- }
144
- async function _findPort(ports, host) {
145
- for (const port of ports) {
146
- const r = await _tryPort(port, host);
147
- if (r) return r;
148
- }
149
- }
150
- function _fmtOnHost(hostname) {
151
- return hostname ? `on host ${JSON.stringify(hostname)}` : "on any host";
152
- }
153
- const HOSTNAME_RE = /^(?!-)[\d.:A-Za-z-]{1,63}(?<!-)$/;
154
- function _validateHostname(hostname, _public, verbose) {
155
- if (hostname && !HOSTNAME_RE.test(hostname)) {
156
- const fallbackHost = _public ? "0.0.0.0" : "127.0.0.1";
157
- _log(verbose, `Invalid hostname: ${JSON.stringify(hostname)}. Using ${JSON.stringify(fallbackHost)} as fallback.`);
158
- return fallbackHost;
159
- }
160
- return hostname;
161
- }
162
- async function getPort(_userOptions = {}) {
163
- if (typeof _userOptions === "number" || typeof _userOptions === "string") _userOptions = { port: Number.parseInt(_userOptions + "") || 0 };
164
- const _port = Number(_userOptions.port ?? process.env.PORT);
165
- const _userSpecifiedAnyPort = Boolean(_userOptions.port || _userOptions.ports?.length || _userOptions.portRange?.length);
166
- const options = {
167
- random: _port === 0,
168
- ports: [],
169
- portRange: [],
170
- alternativePortRange: _userSpecifiedAnyPort ? [] : [3e3, 3100],
171
- verbose: false,
172
- ..._userOptions,
173
- port: _port,
174
- host: _validateHostname(_userOptions.host ?? process.env.HOST, _userOptions.public, _userOptions.verbose)
175
- };
176
- if (options.random && !_userSpecifiedAnyPort) return getRandomPort(options.host);
177
- const portsToCheck = [
178
- options.port,
179
- ...options.ports,
180
- ..._generateRange(...options.portRange)
181
- ].filter((port) => {
182
- if (!port) return false;
183
- if (!isSafePort(port)) {
184
- _log(options.verbose, `Ignoring unsafe port: ${port}`);
185
- return false;
186
- }
187
- return true;
188
- });
189
- if (portsToCheck.length === 0) portsToCheck.push(3e3);
190
- let availablePort = await _findPort(portsToCheck, options.host);
191
- if (!availablePort && options.alternativePortRange.length > 0) {
192
- availablePort = await _findPort(_generateRange(...options.alternativePortRange), options.host);
193
- if (portsToCheck.length > 0) {
194
- let message = `Unable to find an available port (tried ${portsToCheck.join("-")} ${_fmtOnHost(options.host)}).`;
195
- if (availablePort) message += ` Using alternative port ${availablePort}.`;
196
- _log(options.verbose, message);
197
- }
198
- }
199
- if (!availablePort && _userOptions.random !== false) {
200
- availablePort = await getRandomPort(options.host);
201
- if (availablePort) _log(options.verbose, `Using random port ${availablePort}`);
202
- }
203
- if (!availablePort) {
204
- const triedRanges = [
205
- options.port,
206
- options.portRange.join("-"),
207
- options.alternativePortRange.join("-")
208
- ].filter(Boolean).join(", ");
209
- throw new GetPortError(`Unable to find an available port ${_fmtOnHost(options.host)} (tried ${triedRanges})`);
210
- }
211
- return availablePort;
212
- }
213
- async function getRandomPort(host) {
214
- const port = await checkPort(0, host);
215
- if (port === false) throw new GetPortError(`Unable to find a random port ${_fmtOnHost(host)}`);
216
- return port;
217
- }
218
- async function checkPort(port, host = process.env.HOST, verbose) {
219
- if (!host) host = _getLocalHosts([void 0, "0.0.0.0"]);
220
- if (!Array.isArray(host)) return _tryPort(port, host);
221
- for (const _host of host) {
222
- const _port = await _tryPort(port, _host);
223
- if (_port === false) {
224
- if (port < 1024 && verbose) _log(verbose, `Unable to listen to the privileged port ${port} ${_fmtOnHost(_host)}`);
225
- return false;
226
- }
227
- if (port === 0 && _port !== 0) port = _port;
228
- }
229
- return port;
230
- }
231
- //#endregion
232
- //#region src/adapters/dev.ts
233
- const DEFAULT_PORT = 9999;
234
- /**
235
- * Resolve the listening port for {@link createDevServer}, honoring the
236
- * definition's `cli.port` / `cli.portRange` / `cli.random` settings.
237
- * Exposed separately so authors who run their own argv parsing can
238
- * resolve a port up-front (to print it, log it, etc.) before starting
239
- * the server.
240
- */
241
- async function resolveDevServerPort(def, options = {}) {
242
- const host = options.host ?? def.cli?.host ?? "localhost";
243
- const portOptions = {
244
- port: options.defaultPort ?? def.cli?.port ?? DEFAULT_PORT,
245
- host
246
- };
247
- if (def.cli?.portRange) portOptions.portRange = def.cli.portRange;
248
- if (def.cli?.random) portOptions.random = def.cli.random;
249
- return getPort(portOptions);
250
- }
251
- /**
252
- * Start a devframe dev server for a {@link DevframeDefinition} —
253
- * h3 + WebSocket RPC + (optionally) the author's SPA mounted at the
254
- * resolved base path.
255
- *
256
- * When `distDir` is omitted (and `def.cli?.distDir` is unset) the
257
- * server runs in **bridge mode**: only `__connection.json` and the WS
258
- * endpoint are mounted, with no SPA mount. The SPA is expected to be
259
- * hosted elsewhere (e.g. by a parent Vite/Nuxt dev server) — see
260
- * `viteDevBridge({ devMiddleware })`.
261
- *
262
- * Returns the underlying {@link StartedServer} handle so callers can
263
- * close it gracefully (SIGINT, hot-reload, test teardown).
264
- *
265
- * Use this directly when integrating devframe into an existing CLI
266
- * framework (commander, yargs, hand-rolled CAC). For the all-in-one
267
- * `dev` / `build` / `mcp` shell, reach for {@link createCac} instead.
268
- */
269
- async function createDevServer(def, options = {}) {
270
- const distDir = options.distDir ?? def.cli?.distDir;
271
- const host = options.host ?? def.cli?.host ?? "localhost";
272
- const port = options.port ?? await resolveDevServerPort(def, { host });
273
- const flags = options.flags ?? {};
274
- const basePath = options.basePath ? normalizeBasePath(options.basePath) : resolveBasePath(def, "standalone");
275
- const app = options.app ?? new H3();
276
- const h3Host = createH3DevframeHost({
277
- origin: normalizeHttpServerUrl(host, port),
278
- appName: def.id,
279
- mount: (base, dir) => {
280
- mountStaticHandler(app, base, dir);
281
- }
282
- });
283
- const ctx = await createHostContext({
284
- cwd: process$1.cwd(),
285
- mode: "dev",
286
- host: h3Host
287
- });
288
- const setupInfo = { flags };
289
- await def.setup(ctx, setupInfo);
290
- const mcpConfig = resolveMcpConfig(options.mcp ?? def.cli?.mcp);
291
- let mcpDispose;
292
- let mcpMeta;
293
- if (mcpConfig) {
294
- const mcpRoute = withoutLeadingSlash(mcpConfig.path ?? "__mcp");
295
- const mcpPath = joinURL(basePath, mcpRoute);
296
- let mountMcpHttp;
297
- try {
298
- ({mountMcpHttp} = await import("./http-C4T68YV6.mjs"));
299
- } catch (error) {
300
- const reason = error instanceof Error ? error.message : String(error);
301
- throw diagnostics.DF0017({
302
- transport: "http",
303
- reason,
304
- cause: error
305
- });
306
- }
307
- mcpDispose = mountMcpHttp(app, ctx, mcpPath, {
308
- serverName: `${def.id} (devframe)`,
309
- serverVersion: def.version ?? "0.0.0",
310
- exposeSharedState: true,
311
- allowedOrigins: mcpConfig.allowedOrigins
312
- }).dispose;
313
- mcpMeta = { path: mcpRoute };
314
- }
315
- const { bindPath, wsPort, meta } = resolveWsConnection(def, options, basePath);
316
- const connectionMetaPath = joinURL(basePath, DEVFRAME_CONNECTION_META_FILENAME);
317
- app.use(connectionMetaPath, () => ({
318
- backend: "websocket",
319
- websocket: meta,
320
- ...mcpMeta ? { mcp: mcpMeta } : {}
321
- }));
322
- if (distDir) mountStaticHandler(app, basePath, resolve(distDir));
323
- const authOption = flags.auth === false ? false : options.auth !== void 0 ? options.auth : def.cli?.auth;
324
- let authHandler;
325
- let resolvedAuth;
326
- if (authOption === false) resolvedAuth = false;
327
- else if (typeof authOption === "object") {
328
- authHandler = authOption;
329
- resolvedAuth = authOption;
330
- } else {
331
- authHandler = createInteractiveAuth(ctx);
332
- resolvedAuth = authHandler;
333
- }
334
- const started = await startHttpAndWs({
335
- context: ctx,
336
- host,
337
- port,
338
- app,
339
- path: bindPath,
340
- wsPort,
341
- auth: resolvedAuth,
342
- onPeerConnect: options.onPeerConnect,
343
- onPeerDisconnect: options.onPeerDisconnect,
344
- onReady: async (info) => {
345
- authHandler?.printBanner();
346
- await options.onReady?.(info);
347
- await maybeOpenBrowser(def, flags, `${info.origin}${basePath}`, options.openBrowser, authHandler);
348
- }
349
- });
350
- const registration = registerDevframeInstance({
351
- pid: process$1.pid,
352
- port: started.port,
353
- origin: normalizeHttpServerUrl(host, started.port),
354
- basePath,
355
- id: def.id,
356
- name: def.name,
357
- rootDir: process$1.cwd(),
358
- mcp: mcpConfig ? { path: joinURL(basePath, withoutLeadingSlash(mcpConfig.path ?? "__mcp")) } : null,
359
- startedAt: Date.now()
360
- });
361
- const closeServer = started.close;
362
- started.close = async () => {
363
- registration.unregister();
364
- await mcpDispose?.();
365
- await closeServer();
366
- };
367
- return started;
368
- }
369
- /**
370
- * Normalize the `cli.mcp` / `mcp` option (`boolean | McpRouteOptions`) into
371
- * concrete options, or `undefined` when the MCP route is disabled.
372
- */
373
- function resolveMcpConfig(mcp) {
374
- if (!mcp) return void 0;
375
- return mcp === true ? {} : mcp;
376
- }
377
- /**
378
- * Resolve the `mcp` entry a `__connection.json` should advertise for a dev
379
- * server started with the given `mcp` option (falling back to `def.cli?.mcp`,
380
- * exactly like {@link createDevServer}), or `undefined` when the route is
381
- * disabled.
382
- *
383
- * Hosted bridges that hand-roll their connection meta (`viteDevBridge`,
384
- * `@devframes/next`'s handler) pass the side-car `port`: the advertised path
385
- * becomes absolute (the side-car mounts at `/`) and the client dials
386
- * `<page-host>:<port><path>`. Without `port` the path stays relative, resolved
387
- * against `__connection.json`'s own location (the same-server default).
388
- *
389
- * @experimental
390
- */
391
- function resolveMcpConnectionMeta(def, mcp, port) {
392
- const config = resolveMcpConfig(mcp ?? def.cli?.mcp);
393
- if (!config) return void 0;
394
- const route = withoutLeadingSlash(config.path ?? "__mcp");
395
- return port != null ? {
396
- path: withLeadingSlash(route),
397
- port
398
- } : { path: route };
399
- }
400
- /**
401
- * Resolve the three WS connection scenarios from the definition / call-site
402
- * config into a concrete server bind path, optional dedicated port, and the
403
- * `__connection.json` descriptor the browser resolves.
404
- */
405
- function resolveWsConnection(def, options, basePath) {
406
- const ws = options.ws ?? def.cli?.ws ?? {};
407
- const route = withoutLeadingSlash(ws.route ?? "__devframe_ws");
408
- if (ws.url) return {
409
- bindPath: joinURL(basePath, route),
410
- wsPort: void 0,
411
- meta: ws.url
412
- };
413
- if (ws.port != null) return {
414
- bindPath: withLeadingSlash(route),
415
- wsPort: ws.port,
416
- meta: {
417
- port: ws.port,
418
- path: route
419
- }
420
- };
421
- return {
422
- bindPath: joinURL(basePath, route),
423
- wsPort: void 0,
424
- meta: { path: route }
425
- };
426
- }
427
- async function maybeOpenBrowser(def, flags, origin, override, authHandler) {
428
- const flagsOpen = flags.open;
429
- const cliOpen = def.cli?.open;
430
- const resolved = override ?? flagsOpen ?? cliOpen;
431
- if (resolved === void 0 || resolved === false) return;
432
- const target = typeof resolved === "string" ? withBase(resolved, origin) : origin;
433
- const authorizedTarget = authHandler?.buildOpenUrl?.(target) ?? target;
434
- try {
435
- await open(authorizedTarget);
436
- } catch {}
437
- }
438
- //#endregion
439
- export { resolveDevServerPort as n, resolveMcpConnectionMeta as r, createDevServer as t };
@@ -1,38 +0,0 @@
1
- import { ansiFormatter } from "nostics/formatters/ansi";
2
- //#region src/utils/colors.ts
3
- function makeColor(open, close) {
4
- const o = `\x1B[${open}m`;
5
- const c = `\x1B[${close}m`;
6
- return ((arg, ...values) => {
7
- if (Array.isArray(arg) && "raw" in arg) {
8
- const strings = arg;
9
- let out = "";
10
- for (let i = 0; i < strings.length; i++) {
11
- out += strings[i];
12
- if (i < values.length) out += String(values[i]);
13
- }
14
- return `${o}${out}${c}`;
15
- }
16
- return `${o}${String(arg)}${c}`;
17
- });
18
- }
19
- const colors = {
20
- blue: makeColor(34, 39),
21
- cyan: makeColor(36, 39),
22
- gray: makeColor(90, 39),
23
- green: makeColor(32, 39),
24
- red: makeColor(31, 39),
25
- yellow: makeColor(33, 39),
26
- bold: makeColor(1, 22),
27
- dim: makeColor(2, 22),
28
- reset: makeColor(0, 0),
29
- underline: makeColor(4, 24)
30
- };
31
- //#endregion
32
- //#region src/utils/diagnostics-reporter.ts
33
- const formatAnsi = ansiFormatter(colors);
34
- function devframeReporter(d, { method = "warn" } = {}) {
35
- console[method](formatAnsi(d));
36
- }
37
- //#endregion
38
- export { colors as n, devframeReporter as t };