devframe 0.1.18 → 0.1.20

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 (67) hide show
  1. package/README.md +2 -2
  2. package/dist/{_shared-Bxa2_kq7.mjs → _shared-S-Ujqz_L.mjs} +1 -1
  3. package/dist/adapters/build.d.mts +1 -1
  4. package/dist/adapters/build.mjs +9 -5
  5. package/dist/adapters/cli.d.mts +2 -2
  6. package/dist/adapters/cli.mjs +78 -292
  7. package/dist/adapters/dev.d.mts +83 -0
  8. package/dist/adapters/dev.mjs +2 -0
  9. package/dist/adapters/embedded.d.mts +1 -1
  10. package/dist/adapters/kit.d.mts +1 -1
  11. package/dist/adapters/mcp.d.mts +1 -1
  12. package/dist/adapters/mcp.mjs +6 -3
  13. package/dist/adapters/vite.d.mts +1 -1
  14. package/dist/adapters/vite.mjs +1 -1
  15. package/dist/client/index.d.mts +41 -5
  16. package/dist/client/index.mjs +1673 -2
  17. package/dist/constants.d.mts +1 -1
  18. package/dist/{context-xQo1FcxX.mjs → context-BfvbAyGk.mjs} +429 -41
  19. package/dist/dev-B8i_CBlQ.mjs +325 -0
  20. package/dist/{devtool-CHT-4_OU.d.mts → devtool-Bm6zZAw5.d.mts} +371 -28
  21. package/dist/host-h3-BMvrFzIJ.mjs +24 -0
  22. package/dist/{index-Cei8vVcd.d.mts → index-BCo03GEF.d.mts} +1 -1
  23. package/dist/index.d.mts +4 -4
  24. package/dist/index.mjs +11 -2
  25. package/dist/node/index.d.mts +41 -53
  26. package/dist/node/index.mjs +5 -4
  27. package/dist/recipes/open-helpers.d.mts +1 -1
  28. package/dist/recipes/open-helpers.mjs +4 -2
  29. package/dist/rpc/index.d.mts +2 -2
  30. package/dist/rpc/index.mjs +3 -3
  31. package/dist/rpc/transports/ws-client.d.mts +1 -1
  32. package/dist/rpc/transports/ws-client.mjs +1 -1
  33. package/dist/rpc/transports/ws-server.d.mts +1 -1
  34. package/dist/rpc/transports/ws-server.mjs +1 -1
  35. package/dist/{rpc-hbRk8qtt.mjs → rpc-INbWfHoX.mjs} +1 -1
  36. package/dist/{serialization-CWcWE7x7.mjs → serialization-DwKi05Pn.mjs} +1 -1
  37. package/dist/server-DksyT-um.d.mts +54 -0
  38. package/dist/{server-DkJ2-s0Y.mjs → server-qRRM8t3v.mjs} +27 -2
  39. package/dist/{static-dump-DwFfj4U_.mjs → static-dump-C1aVSwxY.mjs} +2 -19
  40. package/dist/types/index.d.mts +4 -4
  41. package/dist/{types-BkyzI9r4.d.mts → types-ag029cAe.d.mts} +1 -1
  42. package/dist/utils/events.d.mts +1 -1
  43. package/dist/utils/shared-state.d.mts +2 -2
  44. package/dist/utils/shared-state.mjs +1 -1
  45. package/dist/utils/state.d.mts +2 -1
  46. package/dist/utils/state.mjs +1 -1
  47. package/dist/utils/streaming-channel.d.mts +2 -0
  48. package/dist/utils/streaming-channel.mjs +255 -0
  49. package/dist/{ws-client-CDGmViwt.d.mts → ws-client-DQySVfF_.d.mts} +1 -1
  50. package/dist/{ws-server-Cu8tmZcF.d.mts → ws-server-VQqESKAs.d.mts} +13 -1
  51. package/package.json +10 -17
  52. package/skills/devframe/README.md +13 -0
  53. package/skills/devframe/SKILL.md +452 -0
  54. package/skills/devframe/templates/counter-devtool.ts +29 -0
  55. package/skills/devframe/templates/spa-devtool.ts +33 -0
  56. package/skills/devframe/templates/vite-client.ts +11 -0
  57. package/dist/client-CsR1_h3o.mjs +0 -1569
  58. package/dist/helpers/nuxt/index.d.mts +0 -46
  59. package/dist/helpers/nuxt/index.mjs +0 -58
  60. package/dist/helpers/nuxt/runtime/plugin.client.d.mts +0 -8
  61. package/dist/helpers/nuxt/runtime/plugin.client.mjs +0 -12
  62. package/dist/immer-DEqg5kOd.mjs +0 -894
  63. package/dist/src-DIKqQIjp.mjs +0 -85
  64. /package/dist/{define-CW9gLnyG.mjs → define-Bb4zh-Dc.mjs} +0 -0
  65. /package/dist/{main-BJD9t8dk.mjs → main-DpINGndA.mjs} +0 -0
  66. /package/dist/{open-BMO2_-wC.mjs → open-BtOOEldu.mjs} +0 -0
  67. /package/dist/{transports-4bqw6Fqg.mjs → transports-BPUzHhI2.mjs} +0 -0
@@ -0,0 +1,325 @@
1
+ import { t as createHostContext } from "./context-BfvbAyGk.mjs";
2
+ import { DEVTOOLS_CONNECTION_META_FILENAME } from "./constants.mjs";
3
+ import { t as createH3DevToolsHost } from "./host-h3-BMvrFzIJ.mjs";
4
+ import { t as startHttpAndWs } from "./server-qRRM8t3v.mjs";
5
+ import { n as resolveBasePath, t as normalizeBasePath } from "./_shared-S-Ujqz_L.mjs";
6
+ import { resolve } from "pathe";
7
+ import process$1 from "node:process";
8
+ import { networkInterfaces } from "node:os";
9
+ import { createApp, eventHandler, fromNodeMiddleware } from "h3";
10
+ import { createServer } from "node:net";
11
+ import sirv from "sirv";
12
+ //#region ../../../node_modules/.pnpm/get-port-please@3.2.0/node_modules/get-port-please/dist/index.mjs
13
+ const unsafePorts = /* @__PURE__ */ new Set([
14
+ 1,
15
+ 7,
16
+ 9,
17
+ 11,
18
+ 13,
19
+ 15,
20
+ 17,
21
+ 19,
22
+ 20,
23
+ 21,
24
+ 22,
25
+ 23,
26
+ 25,
27
+ 37,
28
+ 42,
29
+ 43,
30
+ 53,
31
+ 69,
32
+ 77,
33
+ 79,
34
+ 87,
35
+ 95,
36
+ 101,
37
+ 102,
38
+ 103,
39
+ 104,
40
+ 109,
41
+ 110,
42
+ 111,
43
+ 113,
44
+ 115,
45
+ 117,
46
+ 119,
47
+ 123,
48
+ 135,
49
+ 137,
50
+ 139,
51
+ 143,
52
+ 161,
53
+ 179,
54
+ 389,
55
+ 427,
56
+ 465,
57
+ 512,
58
+ 513,
59
+ 514,
60
+ 515,
61
+ 526,
62
+ 530,
63
+ 531,
64
+ 532,
65
+ 540,
66
+ 548,
67
+ 554,
68
+ 556,
69
+ 563,
70
+ 587,
71
+ 601,
72
+ 636,
73
+ 989,
74
+ 990,
75
+ 993,
76
+ 995,
77
+ 1719,
78
+ 1720,
79
+ 1723,
80
+ 2049,
81
+ 3659,
82
+ 4045,
83
+ 5060,
84
+ 5061,
85
+ 6e3,
86
+ 6566,
87
+ 6665,
88
+ 6666,
89
+ 6667,
90
+ 6668,
91
+ 6669,
92
+ 6697,
93
+ 10080
94
+ ]);
95
+ function isUnsafePort(port) {
96
+ return unsafePorts.has(port);
97
+ }
98
+ function isSafePort(port) {
99
+ return !isUnsafePort(port);
100
+ }
101
+ var GetPortError = class extends Error {
102
+ constructor(message, opts) {
103
+ super(message, opts);
104
+ this.message = message;
105
+ }
106
+ name = "GetPortError";
107
+ };
108
+ function _log(verbose, message) {
109
+ if (verbose) console.log(`[get-port] ${message}`);
110
+ }
111
+ function _generateRange(from, to) {
112
+ if (to < from) return [];
113
+ const r = [];
114
+ for (let index = from; index <= to; index++) r.push(index);
115
+ return r;
116
+ }
117
+ function _tryPort(port, host) {
118
+ return new Promise((resolve) => {
119
+ const server = createServer();
120
+ server.unref();
121
+ server.on("error", () => {
122
+ resolve(false);
123
+ });
124
+ server.listen({
125
+ port,
126
+ host
127
+ }, () => {
128
+ const { port: port2 } = server.address();
129
+ server.close(() => {
130
+ resolve(isSafePort(port2) && port2);
131
+ });
132
+ });
133
+ });
134
+ }
135
+ function _getLocalHosts(additional) {
136
+ const hosts = new Set(additional);
137
+ 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);
138
+ return [...hosts];
139
+ }
140
+ async function _findPort(ports, host) {
141
+ for (const port of ports) {
142
+ const r = await _tryPort(port, host);
143
+ if (r) return r;
144
+ }
145
+ }
146
+ function _fmtOnHost(hostname) {
147
+ return hostname ? `on host ${JSON.stringify(hostname)}` : "on any host";
148
+ }
149
+ const HOSTNAME_RE = /^(?!-)[\d.:A-Za-z-]{1,63}(?<!-)$/;
150
+ function _validateHostname(hostname, _public, verbose) {
151
+ if (hostname && !HOSTNAME_RE.test(hostname)) {
152
+ const fallbackHost = _public ? "0.0.0.0" : "127.0.0.1";
153
+ _log(verbose, `Invalid hostname: ${JSON.stringify(hostname)}. Using ${JSON.stringify(fallbackHost)} as fallback.`);
154
+ return fallbackHost;
155
+ }
156
+ return hostname;
157
+ }
158
+ async function getPort(_userOptions = {}) {
159
+ if (typeof _userOptions === "number" || typeof _userOptions === "string") _userOptions = { port: Number.parseInt(_userOptions + "") || 0 };
160
+ const _port = Number(_userOptions.port ?? process.env.PORT);
161
+ const _userSpecifiedAnyPort = Boolean(_userOptions.port || _userOptions.ports?.length || _userOptions.portRange?.length);
162
+ const options = {
163
+ random: _port === 0,
164
+ ports: [],
165
+ portRange: [],
166
+ alternativePortRange: _userSpecifiedAnyPort ? [] : [3e3, 3100],
167
+ verbose: false,
168
+ ..._userOptions,
169
+ port: _port,
170
+ host: _validateHostname(_userOptions.host ?? process.env.HOST, _userOptions.public, _userOptions.verbose)
171
+ };
172
+ if (options.random && !_userSpecifiedAnyPort) return getRandomPort(options.host);
173
+ const portsToCheck = [
174
+ options.port,
175
+ ...options.ports,
176
+ ..._generateRange(...options.portRange)
177
+ ].filter((port) => {
178
+ if (!port) return false;
179
+ if (!isSafePort(port)) {
180
+ _log(options.verbose, `Ignoring unsafe port: ${port}`);
181
+ return false;
182
+ }
183
+ return true;
184
+ });
185
+ if (portsToCheck.length === 0) portsToCheck.push(3e3);
186
+ let availablePort = await _findPort(portsToCheck, options.host);
187
+ if (!availablePort && options.alternativePortRange.length > 0) {
188
+ availablePort = await _findPort(_generateRange(...options.alternativePortRange), options.host);
189
+ if (portsToCheck.length > 0) {
190
+ let message = `Unable to find an available port (tried ${portsToCheck.join("-")} ${_fmtOnHost(options.host)}).`;
191
+ if (availablePort) message += ` Using alternative port ${availablePort}.`;
192
+ _log(options.verbose, message);
193
+ }
194
+ }
195
+ if (!availablePort && _userOptions.random !== false) {
196
+ availablePort = await getRandomPort(options.host);
197
+ if (availablePort) _log(options.verbose, `Using random port ${availablePort}`);
198
+ }
199
+ if (!availablePort) {
200
+ const triedRanges = [
201
+ options.port,
202
+ options.portRange.join("-"),
203
+ options.alternativePortRange.join("-")
204
+ ].filter(Boolean).join(", ");
205
+ throw new GetPortError(`Unable to find an available port ${_fmtOnHost(options.host)} (tried ${triedRanges})`);
206
+ }
207
+ return availablePort;
208
+ }
209
+ async function getRandomPort(host) {
210
+ const port = await checkPort(0, host);
211
+ if (port === false) throw new GetPortError(`Unable to find a random port ${_fmtOnHost(host)}`);
212
+ return port;
213
+ }
214
+ async function checkPort(port, host = process.env.HOST, verbose) {
215
+ if (!host) host = _getLocalHosts([void 0, "0.0.0.0"]);
216
+ if (!Array.isArray(host)) return _tryPort(port, host);
217
+ for (const _host of host) {
218
+ const _port = await _tryPort(port, _host);
219
+ if (_port === false) {
220
+ if (port < 1024 && verbose) _log(verbose, `Unable to listen to the privileged port ${port} ${_fmtOnHost(_host)}`);
221
+ return false;
222
+ }
223
+ if (port === 0 && _port !== 0) port = _port;
224
+ }
225
+ return port;
226
+ }
227
+ //#endregion
228
+ //#region src/adapters/dev.ts
229
+ const DEFAULT_PORT = 9999;
230
+ /**
231
+ * Resolve the listening port for {@link createDevServer}, honoring the
232
+ * definition's `cli.port` / `cli.portRange` / `cli.random` settings.
233
+ * Exposed separately so authors who run their own argv parsing can
234
+ * resolve a port up-front (to print it, log it, etc.) before starting
235
+ * the server.
236
+ */
237
+ async function resolveDevServerPort(def, options = {}) {
238
+ const host = options.host ?? def.cli?.host ?? "localhost";
239
+ const portOptions = {
240
+ port: options.defaultPort ?? def.cli?.port ?? DEFAULT_PORT,
241
+ host
242
+ };
243
+ if (def.cli?.portRange) portOptions.portRange = def.cli.portRange;
244
+ if (def.cli?.random) portOptions.random = def.cli.random;
245
+ return getPort(portOptions);
246
+ }
247
+ /**
248
+ * Start a devframe dev server for a {@link DevtoolDefinition} —
249
+ * h3 + WebSocket RPC + the author's SPA mounted at the resolved base
250
+ * path.
251
+ *
252
+ * Returns the underlying {@link StartedServer} handle so callers can
253
+ * close it gracefully (SIGINT, hot-reload, test teardown).
254
+ *
255
+ * Use this directly when integrating devframe into an existing CLI
256
+ * framework (commander, yargs, hand-rolled CAC). For the all-in-one
257
+ * `dev` / `build` / `mcp` shell, reach for {@link createCli} instead.
258
+ */
259
+ async function createDevServer(def, options = {}) {
260
+ const distDir = options.distDir ?? def.cli?.distDir;
261
+ if (!distDir) throw new Error(`[devframe] createDevServer: no distDir for "${def.id}". Set \`cli.distDir\` on the definition or pass it as an option.`);
262
+ const host = options.host ?? def.cli?.host ?? "localhost";
263
+ const port = options.port ?? await resolveDevServerPort(def, { host });
264
+ const flags = options.flags ?? {};
265
+ const basePath = options.basePath ? normalizeBasePath(options.basePath) : resolveBasePath(def, "standalone");
266
+ const app = options.app ?? createApp();
267
+ const h3Host = createH3DevToolsHost({
268
+ origin: `http://${host}:${port}`,
269
+ appName: def.id,
270
+ mount: (base, dir) => {
271
+ app.use(base, fromNodeMiddleware(sirv(dir, {
272
+ dev: true,
273
+ single: true
274
+ })));
275
+ }
276
+ });
277
+ const ctx = await createHostContext({
278
+ cwd: process$1.cwd(),
279
+ mode: "dev",
280
+ host: h3Host
281
+ });
282
+ const setupInfo = { flags };
283
+ await def.setup(ctx, setupInfo);
284
+ const connectionMetaPath = `${basePath}${DEVTOOLS_CONNECTION_META_FILENAME}`;
285
+ app.use(connectionMetaPath, eventHandler((event) => {
286
+ event.node.res.setHeader("Content-Type", "application/json");
287
+ return event.node.res.end(JSON.stringify({
288
+ backend: "websocket",
289
+ websocket: port
290
+ }));
291
+ }));
292
+ app.use(basePath, fromNodeMiddleware(sirv(resolve(distDir), {
293
+ dev: true,
294
+ single: true
295
+ })));
296
+ return startHttpAndWs({
297
+ context: ctx,
298
+ host,
299
+ port,
300
+ app,
301
+ auth: def.cli?.auth,
302
+ onReady: async (info) => {
303
+ await options.onReady?.(info);
304
+ await maybeOpenBrowser(def, flags, `${info.origin}${basePath}`, options.openBrowser);
305
+ }
306
+ });
307
+ }
308
+ async function maybeOpenBrowser(def, flags, origin, override) {
309
+ const flagsOpen = flags.open;
310
+ const cliOpen = def.cli?.open;
311
+ const resolved = override ?? flagsOpen ?? cliOpen;
312
+ if (resolved === void 0 || resolved === false) return;
313
+ const target = typeof resolved === "string" ? resolveOpenTarget(origin, resolved) : origin;
314
+ try {
315
+ const { default: open } = await import("./open-BtOOEldu.mjs");
316
+ await open(target);
317
+ } catch {}
318
+ }
319
+ function resolveOpenTarget(origin, target) {
320
+ if (/^https?:/.test(target)) return target;
321
+ if (target.startsWith("/")) return origin.replace(/\/$/, "") + target;
322
+ return origin.replace(/\/$/, "") + (target ? `/${target}` : "");
323
+ }
324
+ //#endregion
325
+ export { resolveDevServerPort as n, createDevServer as t };