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.
- package/dist/_shared-BPmX9fqK.d.mts +41 -0
- package/dist/_shared-CbZ_yhbz.mjs +68 -0
- package/dist/adapters/build.d.mts +10 -12
- package/dist/adapters/build.mjs +26 -29
- package/dist/adapters/cac.d.mts +1 -1
- package/dist/adapters/cac.mjs +156 -1
- package/dist/adapters/dev.d.mts +38 -46
- package/dist/adapters/dev.mjs +2 -1
- package/dist/adapters/embedded.d.mts +1 -1
- package/dist/adapters/initiate.d.mts +224 -0
- package/dist/adapters/initiate.mjs +2 -0
- package/dist/adapters/mcp.d.mts +24 -7
- package/dist/adapters/mcp.mjs +2 -2
- package/dist/{agent-tool-name-C3b5vEwJ.mjs → agent-tool-name-EgfoFO8C.mjs} +0 -3
- package/dist/cli/main.d.mts +0 -2
- package/dist/cli/main.mjs +4 -8
- package/dist/client/index.d.mts +71 -7
- package/dist/client/index.mjs +720 -1540
- package/dist/constants.d.mts +28 -7
- package/dist/constants.mjs +28 -7
- package/dist/{context-DoSozfvx.d.mts → context-B3YUu_95.d.mts} +19 -1
- package/dist/{host-h3-D2hYZvDK.mjs → context-CEe4PBz1.mjs} +25 -557
- package/dist/{context-CBg8iRbQ.mjs → context-xdynGSLP.mjs} +10 -1
- package/dist/dev--rAPzbvO.mjs +239 -0
- package/dist/{devframe-mQ4qZAuo.d.mts → devframe-DJMg0WLe.d.mts} +181 -134
- package/dist/{diagnostics-hwjXp_UV.mjs → diagnostics-CD8nlgll.mjs} +1 -3
- package/dist/{diagnostics-D7wM2cwM.mjs → diagnostics-DOQPnQmX.mjs} +51 -5
- package/dist/dist-eNI9qM_I.mjs +228 -0
- package/dist/host-agent-xLCSe65D.mjs +264 -0
- package/dist/host-h3-Crkzm42q.mjs +26 -0
- package/dist/{fetch-BKaD0Vb3.mjs → http-DYpK0cUi.mjs} +42 -11
- package/dist/{index-b64Uuhy2.d.mts → index-CB-fSUyn.d.mts} +2 -2
- package/dist/{index-Dbw1p5ch.d.mts → index-tdrk1bzV.d.mts} +3 -32
- package/dist/index.d.mts +12 -5
- package/dist/index.mjs +8 -1
- package/dist/{instance-registry-BnnA2Eoh.mjs → instance-registry-WvQkt42E.mjs} +9 -8
- package/dist/instance-shell-CMFyszWJ.mjs +486 -0
- package/dist/instance-shell-CljiKq1c.d.mts +255 -0
- package/dist/internal/index.d.mts +397 -0
- package/dist/internal/index.mjs +9 -0
- package/dist/node/auth.d.mts +2 -2
- package/dist/node/auth.mjs +1 -1
- package/dist/node/hub-internals.d.mts +2 -14
- package/dist/node/hub-internals.mjs +2 -2
- package/dist/node/index.d.mts +4 -268
- package/dist/node/index.mjs +3 -5
- package/dist/nostics-CzECRXpE.mjs +59 -0
- package/dist/nostics-SPGDgHEP.d.mts +33 -0
- package/dist/recipes/common-rpc-functions.d.mts +4 -4
- package/dist/recipes/interactive-auth.d.mts +3 -3
- package/dist/recipes/interactive-auth.mjs +8 -8
- package/dist/remote-assets-Bg4gCUZ_.d.mts +123 -0
- package/dist/remote-assets-nTTxY2MU.mjs +636 -0
- package/dist/rolldown-runtime-JspESFgx.mjs +35 -0
- package/dist/rpc/dump.d.mts +77 -1
- package/dist/rpc/dump.mjs +1 -1
- package/dist/rpc/index.d.mts +3 -3
- package/dist/rpc/index.mjs +4 -18
- package/dist/rpc/transports/sse-client.d.mts +2 -0
- package/dist/rpc/transports/sse-client.mjs +142 -0
- package/dist/rpc/transports/sse-server.d.mts +61 -0
- package/dist/rpc/transports/sse-server.mjs +209 -0
- package/dist/rpc/transports/ws-bun.d.mts +35 -0
- package/dist/rpc/transports/ws-bun.mjs +31 -0
- package/dist/rpc/transports/ws-client.d.mts +1 -1
- package/dist/rpc/transports/ws-client.mjs +10 -18
- package/dist/rpc/transports/ws-server.d.mts +2 -2
- package/dist/rpc/transports/ws-server.mjs +2 -235
- package/dist/rpc-core-Cc4lucI0.d.mts +48 -0
- package/dist/rpc-core-DMTe-hLo.mjs +81 -0
- package/dist/{serialization-C8Mnw9hK.mjs → serialization-BGzEwAdr.mjs} +2 -2
- package/dist/{shared-state-6kHolYZy.mjs → shared-state-fRRbRUtD.mjs} +1 -1
- package/dist/sse-client-CFBOIaUi.d.mts +37 -0
- package/dist/state-Cc1IeSmQ.mjs +1291 -0
- package/dist/{dump-CgZShDRB.mjs → static-BPZ1_OPA.mjs} +3 -266
- package/dist/storage-CYye7P7L.mjs +137 -0
- package/dist/types/index.d.mts +6 -4
- package/dist/types/index.mjs +1 -6
- package/dist/{types-CnJSgRVa.d.mts → types-Djq7CBXh.d.mts} +0 -7
- package/dist/utils/agent-tool-name.d.mts +0 -3
- package/dist/utils/agent-tool-name.mjs +0 -3
- package/dist/utils/events.d.mts +1 -1
- package/dist/utils/get-port.d.mts +17 -0
- package/dist/utils/get-port.mjs +2 -0
- package/dist/utils/launch-editor.mjs +1 -25
- package/dist/utils/nostics.d.mts +2 -0
- package/dist/utils/nostics.mjs +2 -0
- package/dist/utils/open.d.mts +2 -10
- package/dist/utils/open.mjs +56 -1
- package/dist/utils/remote-assets.d.mts +15 -0
- package/dist/utils/remote-assets.mjs +2 -0
- package/dist/utils/serve-static.d.mts +13 -5
- package/dist/utils/serve-static.mjs +119 -9
- package/dist/utils/shared-state.d.mts +1 -1
- package/dist/utils/shared-state.mjs +1 -1
- package/dist/utils/simple-schema.d.mts +101 -1
- package/dist/utils/streaming-channel.d.mts +1 -1
- package/dist/validation-CpXFB6Dz.mjs +266 -0
- package/dist/wire-codec-0K-o5MYW.mjs +56 -0
- package/dist/{ws-client-B6Tnr0ic.d.mts → ws-client-DhjNyQo3.d.mts} +7 -2
- package/dist/ws-server-BdSLrhxE.mjs +267 -0
- package/dist/{ws-server-uKQcClcJ.d.mts → ws-server-D1d3QM9f.d.mts} +90 -9
- package/package.json +13 -12
- package/skills/devframe/SKILL.md +91 -93
- package/dist/_shared-bWRzeSa0.mjs +0 -19
- package/dist/adapters/cli.d.mts +0 -11
- package/dist/adapters/cli.mjs +0 -6
- package/dist/cac-D4_9ok0z.mjs +0 -157
- package/dist/dev-Bc49u3qg.mjs +0 -439
- package/dist/diagnostics-reporter-CsIG85Q5.mjs +0 -38
- package/dist/helpers/vite.d.mts +0 -100
- package/dist/helpers/vite.mjs +0 -105
- package/dist/http-C4T68YV6.mjs +0 -38
- package/dist/index-vAX6bYuc.d.mts +0 -78
- package/dist/open-Deb5xmIT.mjs +0 -547
- package/dist/recipes/open-helpers.d.mts +0 -6
- package/dist/recipes/open-helpers.mjs +0 -6
- package/dist/server-CD8XmBXl.mjs +0 -167
- package/dist/server-UHWae43Q.d.mts +0 -149
- package/dist/simple-schema-BDzLeJDk.d.mts +0 -102
- package/dist/state-BeUHDDjk.mjs +0 -108
- package/dist/storage-CTNVbuFB.mjs +0 -1122
- package/dist/utils/promise.d.mts +0 -8
- package/dist/utils/promise.mjs +0 -15
- package/dist/utils/scope.d.mts +0 -11
- package/dist/utils/scope.mjs +0 -15
- package/skills/devframe/templates/spa-devframe.ts +0 -38
package/dist/cac-D4_9ok0z.mjs
DELETED
|
@@ -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 };
|
package/dist/dev-Bc49u3qg.mjs
DELETED
|
@@ -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 };
|