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.
- package/README.md +2 -2
- package/dist/{_shared-Bxa2_kq7.mjs → _shared-S-Ujqz_L.mjs} +1 -1
- package/dist/adapters/build.d.mts +1 -1
- package/dist/adapters/build.mjs +9 -5
- package/dist/adapters/cli.d.mts +2 -2
- package/dist/adapters/cli.mjs +78 -292
- package/dist/adapters/dev.d.mts +83 -0
- package/dist/adapters/dev.mjs +2 -0
- package/dist/adapters/embedded.d.mts +1 -1
- package/dist/adapters/kit.d.mts +1 -1
- package/dist/adapters/mcp.d.mts +1 -1
- package/dist/adapters/mcp.mjs +6 -3
- package/dist/adapters/vite.d.mts +1 -1
- package/dist/adapters/vite.mjs +1 -1
- package/dist/client/index.d.mts +41 -5
- package/dist/client/index.mjs +1673 -2
- package/dist/constants.d.mts +1 -1
- package/dist/{context-xQo1FcxX.mjs → context-BfvbAyGk.mjs} +429 -41
- package/dist/dev-B8i_CBlQ.mjs +325 -0
- package/dist/{devtool-CHT-4_OU.d.mts → devtool-Bm6zZAw5.d.mts} +371 -28
- package/dist/host-h3-BMvrFzIJ.mjs +24 -0
- package/dist/{index-Cei8vVcd.d.mts → index-BCo03GEF.d.mts} +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +11 -2
- package/dist/node/index.d.mts +41 -53
- package/dist/node/index.mjs +5 -4
- package/dist/recipes/open-helpers.d.mts +1 -1
- package/dist/recipes/open-helpers.mjs +4 -2
- package/dist/rpc/index.d.mts +2 -2
- package/dist/rpc/index.mjs +3 -3
- package/dist/rpc/transports/ws-client.d.mts +1 -1
- package/dist/rpc/transports/ws-client.mjs +1 -1
- package/dist/rpc/transports/ws-server.d.mts +1 -1
- package/dist/rpc/transports/ws-server.mjs +1 -1
- package/dist/{rpc-hbRk8qtt.mjs → rpc-INbWfHoX.mjs} +1 -1
- package/dist/{serialization-CWcWE7x7.mjs → serialization-DwKi05Pn.mjs} +1 -1
- package/dist/server-DksyT-um.d.mts +54 -0
- package/dist/{server-DkJ2-s0Y.mjs → server-qRRM8t3v.mjs} +27 -2
- package/dist/{static-dump-DwFfj4U_.mjs → static-dump-C1aVSwxY.mjs} +2 -19
- package/dist/types/index.d.mts +4 -4
- package/dist/{types-BkyzI9r4.d.mts → types-ag029cAe.d.mts} +1 -1
- package/dist/utils/events.d.mts +1 -1
- package/dist/utils/shared-state.d.mts +2 -2
- package/dist/utils/shared-state.mjs +1 -1
- package/dist/utils/state.d.mts +2 -1
- package/dist/utils/state.mjs +1 -1
- package/dist/utils/streaming-channel.d.mts +2 -0
- package/dist/utils/streaming-channel.mjs +255 -0
- package/dist/{ws-client-CDGmViwt.d.mts → ws-client-DQySVfF_.d.mts} +1 -1
- package/dist/{ws-server-Cu8tmZcF.d.mts → ws-server-VQqESKAs.d.mts} +13 -1
- package/package.json +10 -17
- package/skills/devframe/README.md +13 -0
- package/skills/devframe/SKILL.md +452 -0
- package/skills/devframe/templates/counter-devtool.ts +29 -0
- package/skills/devframe/templates/spa-devtool.ts +33 -0
- package/skills/devframe/templates/vite-client.ts +11 -0
- package/dist/client-CsR1_h3o.mjs +0 -1569
- package/dist/helpers/nuxt/index.d.mts +0 -46
- package/dist/helpers/nuxt/index.mjs +0 -58
- package/dist/helpers/nuxt/runtime/plugin.client.d.mts +0 -8
- package/dist/helpers/nuxt/runtime/plugin.client.mjs +0 -12
- package/dist/immer-DEqg5kOd.mjs +0 -894
- package/dist/src-DIKqQIjp.mjs +0 -85
- /package/dist/{define-CW9gLnyG.mjs → define-Bb4zh-Dc.mjs} +0 -0
- /package/dist/{main-BJD9t8dk.mjs → main-DpINGndA.mjs} +0 -0
- /package/dist/{open-BMO2_-wC.mjs → open-BtOOEldu.mjs} +0 -0
- /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 };
|