@apex-stack/core 0.1.11 → 0.1.13
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/{chunk-2L2T47AH.js → chunk-7E5ZQ6UH.js} +12 -1
- package/dist/chunk-SH3XEJGV.js +239 -0
- package/dist/cli.js +4 -2
- package/dist/{dev-HDRJEPPN.js → dev-BIPK7O5N.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/{server-VOIXBL4I.js → server-ODH3M2IG.js} +1 -1
- package/package.json +1 -1
- package/dist/chunk-QZTDKUXK.js +0 -127
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
// src/ui.ts
|
|
2
|
+
import { readFileSync } from "fs";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
2
4
|
var TTY = Boolean(process.stdout.isTTY) && !process.env.NO_COLOR && process.env.TERM !== "dumb";
|
|
3
5
|
var RESET = "\x1B[0m";
|
|
6
|
+
var VERSION = (() => {
|
|
7
|
+
try {
|
|
8
|
+
return JSON.parse(readFileSync(fileURLToPath(new URL("../package.json", import.meta.url)), "utf8")).version || "";
|
|
9
|
+
} catch {
|
|
10
|
+
return "";
|
|
11
|
+
}
|
|
12
|
+
})();
|
|
4
13
|
function truecolor(r, g, b, s) {
|
|
5
14
|
return TTY ? `\x1B[38;2;${r};${g};${b}m${s}${RESET}` : s;
|
|
6
15
|
}
|
|
@@ -40,9 +49,10 @@ function banner(subtitle = "The full-stack, AI-native meta-framework for Alpine.
|
|
|
40
49
|
}
|
|
41
50
|
return out + RESET;
|
|
42
51
|
});
|
|
52
|
+
const ver = VERSION ? `${color.cyan(`v${VERSION}`)} ${color.gray("\xB7")} ` : "";
|
|
43
53
|
return `
|
|
44
54
|
${rows.join("\n")}
|
|
45
|
-
${color.gray(subtitle)}
|
|
55
|
+
${ver}${color.gray(subtitle)}
|
|
46
56
|
`;
|
|
47
57
|
}
|
|
48
58
|
var FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
@@ -86,6 +96,7 @@ function ready(rows) {
|
|
|
86
96
|
}
|
|
87
97
|
|
|
88
98
|
export {
|
|
99
|
+
VERSION,
|
|
89
100
|
color,
|
|
90
101
|
banner,
|
|
91
102
|
spinner,
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import {
|
|
2
|
+
loadComponents
|
|
3
|
+
} from "./chunk-4VG3CZ6H.js";
|
|
4
|
+
import {
|
|
5
|
+
createApiHandler,
|
|
6
|
+
createMcpHandler,
|
|
7
|
+
loadApiRoutes
|
|
8
|
+
} from "./chunk-DSUIB3JH.js";
|
|
9
|
+
import {
|
|
10
|
+
matchRoute,
|
|
11
|
+
renderIslandsPage,
|
|
12
|
+
renderPage,
|
|
13
|
+
scanPages
|
|
14
|
+
} from "./chunk-PAMD24NK.js";
|
|
15
|
+
|
|
16
|
+
// src/dev/server.ts
|
|
17
|
+
import { createServer as createHttpServer } from "http";
|
|
18
|
+
import { createRequire } from "module";
|
|
19
|
+
import { join } from "path";
|
|
20
|
+
import { fileURLToPath } from "url";
|
|
21
|
+
import { apex } from "@apex-stack/vite";
|
|
22
|
+
import {
|
|
23
|
+
createApp,
|
|
24
|
+
defineEventHandler,
|
|
25
|
+
fromNodeMiddleware,
|
|
26
|
+
setResponseHeader,
|
|
27
|
+
setResponseStatus,
|
|
28
|
+
toNodeListener
|
|
29
|
+
} from "h3";
|
|
30
|
+
import { createServer as createViteServer } from "vite";
|
|
31
|
+
|
|
32
|
+
// src/dev/errorPage.ts
|
|
33
|
+
import { existsSync, readFileSync } from "fs";
|
|
34
|
+
function esc(s) {
|
|
35
|
+
return s.replace(/[&<>"]/g, (c) => c === "&" ? "&" : c === "<" ? "<" : c === ">" ? ">" : """);
|
|
36
|
+
}
|
|
37
|
+
function firstFileFrame(stack, root) {
|
|
38
|
+
const re = /(?:file:\/\/\/?)?((?:[A-Za-z]:[\\/]|\/)[^\s():]+):(\d+):(\d+)/g;
|
|
39
|
+
let m;
|
|
40
|
+
const frames = [];
|
|
41
|
+
while (m = re.exec(stack)) {
|
|
42
|
+
let file = m[1];
|
|
43
|
+
if (/^[A-Za-z]:[\\/]/.test(file) === false && !file.startsWith("/")) continue;
|
|
44
|
+
file = file.replace(/\//g, process.platform === "win32" ? "\\" : "/");
|
|
45
|
+
if (existsSync(file) && !file.includes("node_modules")) {
|
|
46
|
+
frames.push({ file, line: Number(m[2]), col: Number(m[3]) });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return frames.find((f) => f.file.startsWith(root)) ?? frames[0];
|
|
50
|
+
}
|
|
51
|
+
function codeFrame(frame) {
|
|
52
|
+
let lines;
|
|
53
|
+
try {
|
|
54
|
+
lines = readFileSync(frame.file, "utf8").split("\n");
|
|
55
|
+
} catch {
|
|
56
|
+
return "";
|
|
57
|
+
}
|
|
58
|
+
const start = Math.max(0, frame.line - 4);
|
|
59
|
+
const end = Math.min(lines.length, frame.line + 3);
|
|
60
|
+
const rows = [];
|
|
61
|
+
for (let i = start; i < end; i++) {
|
|
62
|
+
const n = i + 1;
|
|
63
|
+
const active = n === frame.line;
|
|
64
|
+
const num = String(n).padStart(4, " ");
|
|
65
|
+
rows.push(
|
|
66
|
+
`<div class="cf-row${active ? " active" : ""}"><span class="cf-num">${num}</span><span class="cf-code">${esc(lines[i] || "")}</span></div>`
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
return `<div class="frame"><div class="frame-file">${esc(frame.file)}<span class="frame-pos">:${frame.line}:${frame.col}</span></div><pre class="cf">${rows.join("")}</pre></div>`;
|
|
70
|
+
}
|
|
71
|
+
var SHELL_CSS = `
|
|
72
|
+
:root{color-scheme:dark light}
|
|
73
|
+
*{box-sizing:border-box}
|
|
74
|
+
body{margin:0;min-height:100vh;background:#0a0e1a;color:#f4f7ff;
|
|
75
|
+
font:15px/1.6 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
|
|
76
|
+
display:flex;align-items:flex-start;justify-content:center;padding:clamp(1.5rem,6vh,5rem) 1.25rem}
|
|
77
|
+
@media(prefers-color-scheme:light){body{background:#f4f7ff;color:#0a0e1a}}
|
|
78
|
+
.wrap{width:100%;max-width:860px}
|
|
79
|
+
.brand{display:flex;align-items:center;gap:.55rem;font-weight:600;letter-spacing:-.01em;margin-bottom:1.6rem}
|
|
80
|
+
.mark{width:20px;height:20px}
|
|
81
|
+
.pill{font-size:.8rem;font-weight:600;padding:.15rem .6rem;border-radius:999px;margin-left:.4rem}
|
|
82
|
+
.pill.err{color:#fb7185;background:rgba(244,63,94,.12);border:1px solid rgba(244,63,94,.35)}
|
|
83
|
+
.pill.nf{color:#818cf8;background:rgba(129,140,248,.12);border:1px solid rgba(129,140,248,.35)}
|
|
84
|
+
.kind{font:600 .95rem/1 ui-monospace,SFMono-Regular,Menlo,monospace;color:#fb7185;margin:0 0 .5rem}
|
|
85
|
+
.kind.nf{color:#818cf8}
|
|
86
|
+
h1{font-size:clamp(1.4rem,3.2vw,2rem);line-height:1.2;letter-spacing:-.02em;margin:0 0 .7rem;word-break:break-word}
|
|
87
|
+
.sub{color:#9aa6c4;margin:0 0 1.8rem}
|
|
88
|
+
.sub code{background:rgba(130,140,200,.14);border-radius:.35rem;padding:.05rem .35rem;font-size:.9em}
|
|
89
|
+
.frame{border:1px solid rgba(130,140,200,.18);border-radius:12px;overflow:hidden;margin:0 0 1.4rem;background:#11172b}
|
|
90
|
+
@media(prefers-color-scheme:light){.frame{background:#fff}}
|
|
91
|
+
.frame-file{font:.8rem/1 ui-monospace,SFMono-Regular,Menlo,monospace;color:#9aa6c4;padding:.7rem .9rem;border-bottom:1px solid rgba(130,140,200,.18);overflow-x:auto;white-space:nowrap}
|
|
92
|
+
.frame-pos{color:#fb7185}
|
|
93
|
+
.cf{margin:0;padding:.6rem 0;overflow-x:auto;font:.82rem/1.7 ui-monospace,SFMono-Regular,Menlo,monospace}
|
|
94
|
+
.cf-row{display:flex;padding:0 .9rem;white-space:pre}
|
|
95
|
+
.cf-row.active{background:rgba(244,63,94,.12);box-shadow:inset 3px 0 0 #f43f5e}
|
|
96
|
+
.cf-num{color:#5b6890;-webkit-user-select:none;user-select:none;padding-right:1.1rem;text-align:right}
|
|
97
|
+
.cf-row.active .cf-num{color:#fb7185}
|
|
98
|
+
.cf-code{color:#f4f7ff}
|
|
99
|
+
@media(prefers-color-scheme:light){.cf-code{color:#0a0e1a}}
|
|
100
|
+
details{border:1px solid rgba(130,140,200,.18);border-radius:12px;background:#11172b;overflow:hidden}
|
|
101
|
+
@media(prefers-color-scheme:light){details{background:#fff}}
|
|
102
|
+
summary{cursor:pointer;padding:.7rem .9rem;font-size:.85rem;color:#9aa6c4;user-select:none}
|
|
103
|
+
summary:hover{color:#f4f7ff}
|
|
104
|
+
@media(prefers-color-scheme:light){summary:hover{color:#0a0e1a}}
|
|
105
|
+
.stack{margin:0;padding:0 .9rem 1rem;font:.78rem/1.7 ui-monospace,SFMono-Regular,Menlo,monospace;color:#9aa6c4;overflow-x:auto;white-space:pre-wrap;word-break:break-word}
|
|
106
|
+
.routes{list-style:none;padding:0;margin:0 0 1.4rem;display:flex;flex-wrap:wrap;gap:.5rem}
|
|
107
|
+
.routes li{font:.85rem/1 ui-monospace,SFMono-Regular,Menlo,monospace;color:#818cf8;background:rgba(129,140,248,.1);border:1px solid rgba(129,140,248,.25);border-radius:.45rem;padding:.35rem .6rem}
|
|
108
|
+
.foot{margin-top:1.8rem;color:#5b6890;font-size:.82rem}
|
|
109
|
+
`;
|
|
110
|
+
var MARK = `<svg class="mark" viewBox="0 0 64 64" aria-hidden="true"><defs><linearGradient id="g" x1="0" y1="1" x2="1" y2="0"><stop offset="0" stop-color="#22d3ee"/><stop offset="1" stop-color="#6366f1"/></linearGradient></defs><path d="M32 7 L32 35 L20 56 L4 56 Z" fill="url(#g)"/><path d="M32 7 L60 56 L44 56 L32 35 Z" fill="#6366f1"/></svg>`;
|
|
111
|
+
function page(title, bodyInner) {
|
|
112
|
+
return `<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>${esc(title)}</title><style>${SHELL_CSS}</style></head><body><div class="wrap">${bodyInner}</div></body></html>`;
|
|
113
|
+
}
|
|
114
|
+
function renderErrorPage(error, opts) {
|
|
115
|
+
const kind = error.name || "Error";
|
|
116
|
+
const message = error.message || String(error);
|
|
117
|
+
const stack = error.stack || "";
|
|
118
|
+
const frame = stack ? firstFileFrame(stack, opts.root) : void 0;
|
|
119
|
+
const frameHtml = frame ? codeFrame(frame) : "";
|
|
120
|
+
const body = `
|
|
121
|
+
<div class="brand">${MARK} Apex JS <span class="pill err">Dev error</span></div>
|
|
122
|
+
<p class="kind">${esc(kind)}</p>
|
|
123
|
+
<h1>${esc(message)}</h1>
|
|
124
|
+
<p class="sub">While rendering <code>${esc(opts.url)}</code></p>
|
|
125
|
+
${frameHtml}
|
|
126
|
+
<details${frameHtml ? "" : " open"}><summary>Stack trace</summary><pre class="stack">${esc(stack)}</pre></details>
|
|
127
|
+
<p class="foot">Fix the error and save \u2014 this page reloads automatically.</p>`;
|
|
128
|
+
return page(`${kind} \u2014 Apex JS`, body);
|
|
129
|
+
}
|
|
130
|
+
function renderNotFoundPage(url, routes) {
|
|
131
|
+
const list = routes.length ? routes.map((r) => `<li>${esc(r.pattern)}</li>`).join("") : "<li>no pages yet \u2014 add pages/index.alpine</li>";
|
|
132
|
+
const body = `
|
|
133
|
+
<div class="brand">${MARK} Apex JS <span class="pill nf">404</span></div>
|
|
134
|
+
<p class="kind nf">404 \u2014 Not found</p>
|
|
135
|
+
<h1>No route matches <code>${esc(url)}</code></h1>
|
|
136
|
+
<p class="sub">These routes are available:</p>
|
|
137
|
+
<ul class="routes">${list}</ul>
|
|
138
|
+
<p class="foot">Add a file under <code>pages/</code> to create a new route.</p>`;
|
|
139
|
+
return page("404 \u2014 Apex JS", body);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// src/dev/server.ts
|
|
143
|
+
async function startDevServer(options) {
|
|
144
|
+
const port = options.port ?? 3e3;
|
|
145
|
+
const pageId = options.pageId ?? "/pages/index.alpine";
|
|
146
|
+
const req = createRequire(import.meta.url);
|
|
147
|
+
const tryResolve = (spec) => {
|
|
148
|
+
try {
|
|
149
|
+
return req.resolve(spec);
|
|
150
|
+
} catch {
|
|
151
|
+
return void 0;
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
const alpine = tryResolve("alpinejs");
|
|
155
|
+
const kit = tryResolve("@apex-stack/kit");
|
|
156
|
+
const coreClient = fileURLToPath(new URL("./client.js", import.meta.url));
|
|
157
|
+
const alias = { "@apex-stack/core/client": coreClient };
|
|
158
|
+
if (alpine) alias.alpinejs = alpine;
|
|
159
|
+
if (kit) alias["@apex-stack/kit"] = kit;
|
|
160
|
+
const vite = await createViteServer({
|
|
161
|
+
root: options.root,
|
|
162
|
+
appType: "custom",
|
|
163
|
+
// Derive the HMR port from the dev port so multiple `apex dev` instances
|
|
164
|
+
// don't all fight over Vite's default 24678.
|
|
165
|
+
server: { middlewareMode: true, fs: { strict: false }, hmr: { port: port + 1 } },
|
|
166
|
+
resolve: { alias },
|
|
167
|
+
// User apps depend on `@apex-stack/core`, so the client module imports the runtime
|
|
168
|
+
// from `@apex-stack/core/client` (a re-export) rather than the internal kit package.
|
|
169
|
+
plugins: [apex({ clientRuntime: "@apex-stack/core/client" })],
|
|
170
|
+
optimizeDeps: { include: ["alpinejs"] }
|
|
171
|
+
});
|
|
172
|
+
const ssrLoad = (id) => {
|
|
173
|
+
const resolved = id[0] === "/" && !id.startsWith(options.root) ? join(options.root, id).replace(/\\/g, "/") : id;
|
|
174
|
+
return vite.ssrLoadModule(resolved);
|
|
175
|
+
};
|
|
176
|
+
const app = createApp();
|
|
177
|
+
app.use(fromNodeMiddleware(vite.middlewares));
|
|
178
|
+
const loadEntries = () => loadApiRoutes(options.root, (id) => ssrLoad(id));
|
|
179
|
+
app.use("/api", defineEventHandler((event) => loadEntries().then((e) => createApiHandler(e)(event))));
|
|
180
|
+
app.use("/mcp", defineEventHandler((event) => loadEntries().then((e) => createMcpHandler(e)(event))));
|
|
181
|
+
app.use(
|
|
182
|
+
defineEventHandler(async (event) => {
|
|
183
|
+
const url = event.path || "/";
|
|
184
|
+
try {
|
|
185
|
+
const routes = scanPages(options.root);
|
|
186
|
+
const matched = routes.length ? matchRoute(routes, url) : { pageId, params: {} };
|
|
187
|
+
if (!matched) {
|
|
188
|
+
setResponseStatus(event, 404);
|
|
189
|
+
setResponseHeader(event, "Content-Type", "text/html");
|
|
190
|
+
return await vite.transformIndexHtml(url, renderNotFoundPage(url, routes));
|
|
191
|
+
}
|
|
192
|
+
const { registry, css: componentCss } = await loadComponents(
|
|
193
|
+
options.root,
|
|
194
|
+
(id) => ssrLoad(id)
|
|
195
|
+
);
|
|
196
|
+
const render = options.islands ? renderIslandsPage : renderPage;
|
|
197
|
+
const html = await render({
|
|
198
|
+
loadModule: (id) => ssrLoad(id),
|
|
199
|
+
pageId: matched.pageId,
|
|
200
|
+
params: matched.params,
|
|
201
|
+
url,
|
|
202
|
+
registry,
|
|
203
|
+
componentCss,
|
|
204
|
+
transformHtml: (u, doc) => vite.transformIndexHtml(u, doc)
|
|
205
|
+
});
|
|
206
|
+
setResponseHeader(event, "Content-Type", "text/html");
|
|
207
|
+
return html;
|
|
208
|
+
} catch (err) {
|
|
209
|
+
const error = err;
|
|
210
|
+
vite.ssrFixStacktrace(error);
|
|
211
|
+
setResponseStatus(event, 500);
|
|
212
|
+
setResponseHeader(event, "Content-Type", "text/html");
|
|
213
|
+
const html = renderErrorPage(error, { url, root: options.root });
|
|
214
|
+
try {
|
|
215
|
+
return await vite.transformIndexHtml(url, html);
|
|
216
|
+
} catch {
|
|
217
|
+
return html;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
})
|
|
221
|
+
);
|
|
222
|
+
const server = createHttpServer(toNodeListener(app));
|
|
223
|
+
await new Promise((resolve) => server.listen(port, resolve));
|
|
224
|
+
return {
|
|
225
|
+
vite,
|
|
226
|
+
server,
|
|
227
|
+
port,
|
|
228
|
+
close: async () => {
|
|
229
|
+
await vite.close();
|
|
230
|
+
await new Promise(
|
|
231
|
+
(resolve, reject) => server.close((e) => e ? reject(e) : resolve())
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export {
|
|
238
|
+
startDevServer
|
|
239
|
+
};
|
package/dist/cli.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
VERSION,
|
|
3
4
|
banner,
|
|
4
5
|
color,
|
|
5
6
|
spinner
|
|
6
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-7E5ZQ6UH.js";
|
|
7
8
|
|
|
8
9
|
// src/cli.ts
|
|
9
10
|
import { defineCommand as defineCommand2, runMain } from "citty";
|
|
@@ -103,11 +104,12 @@ var COMMANDS = [
|
|
|
103
104
|
var main = defineCommand2({
|
|
104
105
|
meta: {
|
|
105
106
|
name: "apex",
|
|
107
|
+
version: VERSION,
|
|
106
108
|
description: "The full-stack meta-framework for Alpine.js"
|
|
107
109
|
},
|
|
108
110
|
subCommands: {
|
|
109
111
|
new: newCommand,
|
|
110
|
-
dev: () => import("./dev-
|
|
112
|
+
dev: () => import("./dev-BIPK7O5N.js").then((m) => m.devCommand),
|
|
111
113
|
build: () => import("./build-QRHQUUZC.js").then((m) => m.buildCommand),
|
|
112
114
|
start: () => import("./start-VJJXI4W3.js").then((m) => m.startCommand),
|
|
113
115
|
make: () => import("./make-4LINTKZH.js").then((m) => m.makeCommand),
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
banner,
|
|
3
3
|
ready,
|
|
4
4
|
spinner
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-7E5ZQ6UH.js";
|
|
6
6
|
|
|
7
7
|
// src/commands/dev.ts
|
|
8
8
|
import { resolve } from "path";
|
|
@@ -20,7 +20,7 @@ var devCommand = defineCommand({
|
|
|
20
20
|
process.stdout.write(banner());
|
|
21
21
|
const sp = spinner(`Starting dev server${args.islands ? " (islands mode)" : ""}\u2026`);
|
|
22
22
|
try {
|
|
23
|
-
const { startDevServer } = await import("./server-
|
|
23
|
+
const { startDevServer } = await import("./server-ODH3M2IG.js");
|
|
24
24
|
const { port: actual } = await startDevServer({ root, port, islands: Boolean(args.islands) });
|
|
25
25
|
sp.succeed("Dev server ready");
|
|
26
26
|
ready([
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
package/dist/chunk-QZTDKUXK.js
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
loadComponents
|
|
3
|
-
} from "./chunk-4VG3CZ6H.js";
|
|
4
|
-
import {
|
|
5
|
-
createApiHandler,
|
|
6
|
-
createMcpHandler,
|
|
7
|
-
loadApiRoutes
|
|
8
|
-
} from "./chunk-DSUIB3JH.js";
|
|
9
|
-
import {
|
|
10
|
-
matchRoute,
|
|
11
|
-
renderIslandsPage,
|
|
12
|
-
renderPage,
|
|
13
|
-
scanPages
|
|
14
|
-
} from "./chunk-PAMD24NK.js";
|
|
15
|
-
|
|
16
|
-
// src/dev/server.ts
|
|
17
|
-
import { createServer as createHttpServer } from "http";
|
|
18
|
-
import { createRequire } from "module";
|
|
19
|
-
import { fileURLToPath } from "url";
|
|
20
|
-
import { apex } from "@apex-stack/vite";
|
|
21
|
-
import {
|
|
22
|
-
createApp,
|
|
23
|
-
defineEventHandler,
|
|
24
|
-
fromNodeMiddleware,
|
|
25
|
-
setResponseHeader,
|
|
26
|
-
setResponseStatus,
|
|
27
|
-
toNodeListener
|
|
28
|
-
} from "h3";
|
|
29
|
-
import { createServer as createViteServer } from "vite";
|
|
30
|
-
async function startDevServer(options) {
|
|
31
|
-
const port = options.port ?? 3e3;
|
|
32
|
-
const pageId = options.pageId ?? "/pages/index.alpine";
|
|
33
|
-
const req = createRequire(import.meta.url);
|
|
34
|
-
const tryResolve = (spec) => {
|
|
35
|
-
try {
|
|
36
|
-
return req.resolve(spec);
|
|
37
|
-
} catch {
|
|
38
|
-
return void 0;
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
const alpine = tryResolve("alpinejs");
|
|
42
|
-
const kit = tryResolve("@apex-stack/kit");
|
|
43
|
-
const coreClient = fileURLToPath(new URL("./client.js", import.meta.url));
|
|
44
|
-
const alias = { "@apex-stack/core/client": coreClient };
|
|
45
|
-
if (alpine) alias.alpinejs = alpine;
|
|
46
|
-
if (kit) alias["@apex-stack/kit"] = kit;
|
|
47
|
-
const vite = await createViteServer({
|
|
48
|
-
root: options.root,
|
|
49
|
-
appType: "custom",
|
|
50
|
-
server: { middlewareMode: true, fs: { strict: false } },
|
|
51
|
-
resolve: { alias },
|
|
52
|
-
// User apps depend on `@apex-stack/core`, so the client module imports the runtime
|
|
53
|
-
// from `@apex-stack/core/client` (a re-export) rather than the internal kit package.
|
|
54
|
-
plugins: [apex({ clientRuntime: "@apex-stack/core/client" })],
|
|
55
|
-
optimizeDeps: { include: ["alpinejs"] }
|
|
56
|
-
});
|
|
57
|
-
const app = createApp();
|
|
58
|
-
app.use(fromNodeMiddleware(vite.middlewares));
|
|
59
|
-
const loadEntries = () => loadApiRoutes(options.root, (id) => vite.ssrLoadModule(id));
|
|
60
|
-
app.use("/api", defineEventHandler((event) => loadEntries().then((e) => createApiHandler(e)(event))));
|
|
61
|
-
app.use("/mcp", defineEventHandler((event) => loadEntries().then((e) => createMcpHandler(e)(event))));
|
|
62
|
-
app.use(
|
|
63
|
-
defineEventHandler(async (event) => {
|
|
64
|
-
const url = event.path || "/";
|
|
65
|
-
try {
|
|
66
|
-
const routes = scanPages(options.root);
|
|
67
|
-
const matched = routes.length ? matchRoute(routes, url) : { pageId, params: {} };
|
|
68
|
-
if (!matched) {
|
|
69
|
-
setResponseStatus(event, 404);
|
|
70
|
-
setResponseHeader(event, "Content-Type", "text/html");
|
|
71
|
-
return notFoundPage(url, routes);
|
|
72
|
-
}
|
|
73
|
-
const { registry, css: componentCss } = await loadComponents(
|
|
74
|
-
options.root,
|
|
75
|
-
(id) => vite.ssrLoadModule(id)
|
|
76
|
-
);
|
|
77
|
-
const render = options.islands ? renderIslandsPage : renderPage;
|
|
78
|
-
const html = await render({
|
|
79
|
-
loadModule: (id) => vite.ssrLoadModule(id),
|
|
80
|
-
pageId: matched.pageId,
|
|
81
|
-
params: matched.params,
|
|
82
|
-
url,
|
|
83
|
-
registry,
|
|
84
|
-
componentCss,
|
|
85
|
-
transformHtml: (u, doc) => vite.transformIndexHtml(u, doc)
|
|
86
|
-
});
|
|
87
|
-
setResponseHeader(event, "Content-Type", "text/html");
|
|
88
|
-
return html;
|
|
89
|
-
} catch (err) {
|
|
90
|
-
const error = err;
|
|
91
|
-
vite.ssrFixStacktrace(error);
|
|
92
|
-
setResponseStatus(event, 500);
|
|
93
|
-
setResponseHeader(event, "Content-Type", "text/html");
|
|
94
|
-
return `<pre>${escapeHtml(error.stack ?? error.message)}</pre>`;
|
|
95
|
-
}
|
|
96
|
-
})
|
|
97
|
-
);
|
|
98
|
-
const server = createHttpServer(toNodeListener(app));
|
|
99
|
-
await new Promise((resolve) => server.listen(port, resolve));
|
|
100
|
-
return {
|
|
101
|
-
vite,
|
|
102
|
-
server,
|
|
103
|
-
port,
|
|
104
|
-
close: async () => {
|
|
105
|
-
await vite.close();
|
|
106
|
-
await new Promise(
|
|
107
|
-
(resolve, reject) => server.close((e) => e ? reject(e) : resolve())
|
|
108
|
-
);
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
function escapeHtml(s) {
|
|
113
|
-
return s.replace(/[&<>]/g, (c) => c === "&" ? "&" : c === "<" ? "<" : ">");
|
|
114
|
-
}
|
|
115
|
-
function notFoundPage(url, routes) {
|
|
116
|
-
const list = routes.map((r) => `<li><code>${escapeHtml(r.pattern)}</code></li>`).join("");
|
|
117
|
-
return `<!DOCTYPE html><html><head><title>404 \u2014 Apex JS</title></head>
|
|
118
|
-
<body style="font-family: system-ui, sans-serif; max-width: 40rem; margin: 3rem auto;">
|
|
119
|
-
<h1>404 \u2014 no route for <code>${escapeHtml(url)}</code></h1>
|
|
120
|
-
<p>Available routes:</p>
|
|
121
|
-
<ul>${list || "<li>(no pages found \u2014 add <code>pages/index.alpine</code>)</li>"}</ul>
|
|
122
|
-
</body></html>`;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export {
|
|
126
|
-
startDevServer
|
|
127
|
-
};
|