@apex-stack/core 0.1.19 → 0.2.0
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/{build-J47A3B4Y.js → build-VHS6KZBK.js} +91 -27
- package/dist/chunk-2C2HRLIY.js +18 -0
- package/dist/chunk-CHBSGOB3.js +42 -0
- package/dist/{chunk-JWYNLP4L.js → chunk-HCNNKT4A.js} +51 -9
- package/dist/chunk-JLIAISWM.js +48 -0
- package/dist/{chunk-XSN6NDWP.js → chunk-XDKJO6ZC.js} +159 -25
- package/dist/cli.js +65 -24
- package/dist/client.d.ts +1 -1
- package/dist/client.js +2 -1
- package/dist/{dev-OCVQRCCE.js → dev-G7HPP6KW.js} +6 -2
- package/dist/index.d.ts +88 -5
- package/dist/index.js +12 -4
- package/dist/{make-JAW22LQZ.js → make-VAYO5GWA.js} +71 -5
- package/dist/{mcp-DL4J6JFJ.js → mcp-CH7L4GF3.js} +1 -1
- package/dist/{migrate-NOGFOFV2.js → migrate-X6LIHMIE.js} +3 -1
- package/dist/{server-L3V34B5X.js → server-PTHGOE42.js} +63 -19
- package/dist/{start-AUJJ7HAY.js → start-3O3E43PT.js} +47 -10
- package/dist/upgrade-WC5F5FKY.js +168 -0
- package/package.json +5 -4
- package/templates/default/.env.example +9 -0
- package/templates/default/README.md +63 -17
- package/templates/default/_gitignore +5 -0
- package/templates/default/apex.config.ts +22 -0
- package/templates/default/components/Counter.alpine +15 -0
- package/templates/default/composables/useToggle.ts +14 -0
- package/templates/default/db/README.md +18 -0
- package/templates/default/layouts/default.alpine +16 -0
- package/templates/default/package.json +11 -2
- package/templates/default/pages/index.alpine +23 -92
- package/templates/default/public/.gitkeep +0 -0
- package/templates/default/server/api/hello.ts +10 -2
- package/templates/default/services/GreetingService.ts +12 -0
- package/templates/default/shared/types.ts +11 -0
- package/templates/default/stores/ui.ts +9 -0
- package/templates/default/tests/greeting.test.ts +12 -0
- package/templates/default/tsconfig.json +15 -0
- package/templates/default/vitest.config.ts +7 -0
- package/vscode/apex-alpine.vsix +0 -0
- package/dist/chunk-HRJTOSYH.js +0 -8
- package/dist/chunk-MZVLRU3R.js +0 -15
|
@@ -2,21 +2,23 @@ import {
|
|
|
2
2
|
loadComponents
|
|
3
3
|
} from "./chunk-4VG3CZ6H.js";
|
|
4
4
|
import {
|
|
5
|
+
loadStores,
|
|
5
6
|
renderIslandsPage,
|
|
6
7
|
renderPage,
|
|
8
|
+
resolveApexConfig,
|
|
7
9
|
scanPages
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
+
} from "./chunk-XDKJO6ZC.js";
|
|
11
|
+
import "./chunk-JLIAISWM.js";
|
|
10
12
|
|
|
11
13
|
// src/commands/build.ts
|
|
12
|
-
import { cpSync, existsSync as
|
|
14
|
+
import { cpSync, existsSync as existsSync3, mkdirSync, readdirSync as readdirSync3, rmSync, writeFileSync } from "fs";
|
|
13
15
|
import { dirname, join as join3, resolve } from "path";
|
|
14
16
|
import { apex as apex3 } from "@apex-stack/vite";
|
|
15
17
|
import { defineCommand } from "citty";
|
|
16
18
|
import { createServer as createViteServer } from "vite";
|
|
17
19
|
|
|
18
20
|
// src/build/buildClient.ts
|
|
19
|
-
import { readFileSync } from "fs";
|
|
21
|
+
import { existsSync, readFileSync, readdirSync } from "fs";
|
|
20
22
|
import { join } from "path";
|
|
21
23
|
import { apex } from "@apex-stack/vite";
|
|
22
24
|
import { build } from "vite";
|
|
@@ -24,9 +26,11 @@ var VIRT = "virtual:apex-client:";
|
|
|
24
26
|
function entryName(pageId) {
|
|
25
27
|
return pageId.replace(/^\/pages\//, "").replace(/\.alpine$/, "").replace(/[^a-zA-Z0-9]+/g, "_");
|
|
26
28
|
}
|
|
27
|
-
async function buildClient(root, routes, outDir) {
|
|
29
|
+
async function buildClient(root, routes, outDir, base = "/") {
|
|
28
30
|
const input = {};
|
|
29
31
|
for (const r of routes) input[entryName(r.pageId)] = `${VIRT}${r.pageId}`;
|
|
32
|
+
const storesDir = join(root, "stores");
|
|
33
|
+
const storeIds = existsSync(storesDir) ? readdirSync(storesDir).filter((f) => f.endsWith(".ts") || f.endsWith(".js")).map((f) => `/stores/${f}`) : [];
|
|
30
34
|
const entryPlugin = {
|
|
31
35
|
name: "apex:client-entries",
|
|
32
36
|
resolveId(id) {
|
|
@@ -37,15 +41,18 @@ async function buildClient(root, routes, outDir) {
|
|
|
37
41
|
const pageId = id.slice(`\0${VIRT}`.length);
|
|
38
42
|
return [
|
|
39
43
|
`import Alpine from 'alpinejs'`,
|
|
44
|
+
...storeIds.map((sid, i) => `import __s${i} from ${JSON.stringify(sid)}`),
|
|
40
45
|
`import ${JSON.stringify(pageId)}`,
|
|
41
|
-
|
|
42
|
-
`Alpine.
|
|
46
|
+
"window.Alpine = Alpine",
|
|
47
|
+
...storeIds.map((_, i) => `Alpine.store(__s${i}.name, __s${i}.factory())`),
|
|
48
|
+
"Alpine.start()"
|
|
43
49
|
].join("\n");
|
|
44
50
|
}
|
|
45
51
|
}
|
|
46
52
|
};
|
|
47
53
|
await build({
|
|
48
54
|
root,
|
|
55
|
+
base,
|
|
49
56
|
logLevel: "warn",
|
|
50
57
|
plugins: [apex({ clientRuntime: "@apex-stack/core/client" }), entryPlugin],
|
|
51
58
|
build: {
|
|
@@ -55,37 +62,46 @@ async function buildClient(root, routes, outDir) {
|
|
|
55
62
|
rollupOptions: { input }
|
|
56
63
|
}
|
|
57
64
|
});
|
|
58
|
-
const manifest = JSON.parse(
|
|
65
|
+
const manifest = JSON.parse(
|
|
66
|
+
readFileSync(join(outDir, ".vite", "manifest.json"), "utf8")
|
|
67
|
+
);
|
|
68
|
+
const prefix = base.endsWith("/") ? base : `${base}/`;
|
|
59
69
|
const hrefs = /* @__PURE__ */ new Map();
|
|
60
70
|
for (const r of routes) {
|
|
61
71
|
const virt = `${VIRT}${r.pageId}`;
|
|
62
72
|
const entry = Object.values(manifest).find(
|
|
63
|
-
(m) => m.isEntry &&
|
|
73
|
+
(m) => m.isEntry && typeof m.src === "string" && (m.src === virt || m.src.endsWith(virt))
|
|
64
74
|
);
|
|
65
|
-
if (entry) hrefs.set(r.pageId,
|
|
75
|
+
if (entry) hrefs.set(r.pageId, `${prefix}${entry.file}`);
|
|
66
76
|
}
|
|
67
77
|
return hrefs;
|
|
68
78
|
}
|
|
69
79
|
|
|
70
80
|
// src/build/buildServer.ts
|
|
71
|
-
import { existsSync, readdirSync } from "fs";
|
|
81
|
+
import { existsSync as existsSync2, readdirSync as readdirSync2 } from "fs";
|
|
72
82
|
import { isAbsolute, join as join2 } from "path";
|
|
73
83
|
import { apex as apex2 } from "@apex-stack/vite";
|
|
74
84
|
import { build as build2 } from "vite";
|
|
75
85
|
async function buildServer(root, routes, outDir) {
|
|
76
86
|
const ids = routes.map((r) => r.pageId);
|
|
77
87
|
const compDir = join2(root, "components");
|
|
78
|
-
if (
|
|
79
|
-
for (const f of
|
|
88
|
+
if (existsSync2(compDir)) {
|
|
89
|
+
for (const f of readdirSync2(compDir).filter((f2) => f2.endsWith(".alpine"))) {
|
|
80
90
|
ids.push(`/components/${f}`);
|
|
81
91
|
}
|
|
82
92
|
}
|
|
83
93
|
const apiDir = join2(root, "server", "api");
|
|
84
|
-
if (
|
|
85
|
-
for (const f of
|
|
94
|
+
if (existsSync2(apiDir)) {
|
|
95
|
+
for (const f of readdirSync2(apiDir).filter((f2) => /\.(ts|js|mjs)$/.test(f2))) {
|
|
86
96
|
ids.push(`/server/api/${f}`);
|
|
87
97
|
}
|
|
88
98
|
}
|
|
99
|
+
const mwDir = join2(root, "middleware");
|
|
100
|
+
if (existsSync2(mwDir)) {
|
|
101
|
+
for (const f of readdirSync2(mwDir).filter((f2) => /\.(ts|js|mjs)$/.test(f2))) {
|
|
102
|
+
ids.push(`/middleware/${f}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
89
105
|
const input = {};
|
|
90
106
|
for (const id of ids) input[entryName2(id)] = join2(root, id.slice(1));
|
|
91
107
|
const result = await build2({
|
|
@@ -136,8 +152,21 @@ var buildCommand = defineCommand({
|
|
|
136
152
|
args: {
|
|
137
153
|
root: { type: "positional", required: false, description: "Project root", default: "." },
|
|
138
154
|
outDir: { type: "string", description: "Output directory", default: "dist" },
|
|
139
|
-
islands: {
|
|
140
|
-
|
|
155
|
+
islands: {
|
|
156
|
+
type: "boolean",
|
|
157
|
+
description: "Static-first islands mode (zero-JS static)",
|
|
158
|
+
default: false
|
|
159
|
+
},
|
|
160
|
+
server: {
|
|
161
|
+
type: "boolean",
|
|
162
|
+
description: "Build a Node server (dynamic routes + API/MCP)",
|
|
163
|
+
default: false
|
|
164
|
+
},
|
|
165
|
+
base: {
|
|
166
|
+
type: "string",
|
|
167
|
+
description: "Public base path for a subpath deploy (e.g. /demo/)",
|
|
168
|
+
default: "/"
|
|
169
|
+
}
|
|
141
170
|
},
|
|
142
171
|
async run({ args }) {
|
|
143
172
|
const root = resolve(process.cwd(), args.root);
|
|
@@ -149,7 +178,7 @@ var buildCommand = defineCommand({
|
|
|
149
178
|
if (args.server) {
|
|
150
179
|
return buildServerTarget(root, outDir, args.outDir, routes);
|
|
151
180
|
}
|
|
152
|
-
const hrefs = args.islands ? /* @__PURE__ */ new Map() : await buildClient(root, staticRoutes, outDir);
|
|
181
|
+
const hrefs = args.islands ? /* @__PURE__ */ new Map() : await buildClient(root, staticRoutes, outDir, args.base);
|
|
153
182
|
const vite = await createViteServer({
|
|
154
183
|
root,
|
|
155
184
|
appType: "custom",
|
|
@@ -161,13 +190,24 @@ var buildCommand = defineCommand({
|
|
|
161
190
|
root,
|
|
162
191
|
(id) => vite.ssrLoadModule(id)
|
|
163
192
|
);
|
|
193
|
+
const stores = await loadStores(root, (id) => vite.ssrLoadModule(id));
|
|
194
|
+
const { runtimeConfig, publicConfig } = await resolveApexConfig(
|
|
195
|
+
root,
|
|
196
|
+
(id) => vite.ssrLoadModule(id)
|
|
197
|
+
);
|
|
198
|
+
const layoutsDir = join3(root, "layouts");
|
|
199
|
+
const layouts = existsSync3(layoutsDir) ? readdirSync3(layoutsDir).filter((f) => f.endsWith(".alpine")).map((f) => f.replace(/\.alpine$/, "")) : [];
|
|
164
200
|
for (const route of staticRoutes) {
|
|
165
201
|
const common = {
|
|
166
202
|
loadModule: (id) => vite.ssrLoadModule(id),
|
|
167
203
|
pageId: route.pageId,
|
|
168
204
|
url: route.pattern,
|
|
169
205
|
registry,
|
|
170
|
-
componentCss
|
|
206
|
+
componentCss,
|
|
207
|
+
stores,
|
|
208
|
+
layouts,
|
|
209
|
+
runtimeConfig,
|
|
210
|
+
publicConfig
|
|
171
211
|
};
|
|
172
212
|
const html = args.islands ? await renderIslandsPage(common) : await renderPage({ ...common, clientHref: hrefs.get(route.pageId) });
|
|
173
213
|
const dest = join3(outDir, outFile(route.pattern));
|
|
@@ -176,10 +216,10 @@ var buildCommand = defineCommand({
|
|
|
176
216
|
console.log(` \u2713 ${route.pattern} \u2192 ${outFile(route.pattern)}`);
|
|
177
217
|
}
|
|
178
218
|
const pub = join3(root, "public");
|
|
179
|
-
if (
|
|
219
|
+
if (existsSync3(pub)) cpSync(pub, outDir, { recursive: true });
|
|
180
220
|
console.log(
|
|
181
221
|
`
|
|
182
|
-
Built ${staticRoutes.length} page(s) \u2192 ${args.outDir}
|
|
222
|
+
Built ${staticRoutes.length} page(s) \u2192 ${args.outDir}/${args.islands ? " (islands / static-first)" : " (prerendered + hydrated)"}`
|
|
183
223
|
);
|
|
184
224
|
if (dynamic.length) {
|
|
185
225
|
console.log(
|
|
@@ -195,22 +235,44 @@ var buildCommand = defineCommand({
|
|
|
195
235
|
async function buildServerTarget(root, outDir, outLabel, routes) {
|
|
196
236
|
const clientHrefs = await buildClient(root, routes, outDir);
|
|
197
237
|
const server = await buildServer(root, routes, outDir);
|
|
238
|
+
let runtimeConfig = { public: {} };
|
|
239
|
+
const cfgVite = await createViteServer({
|
|
240
|
+
root,
|
|
241
|
+
appType: "custom",
|
|
242
|
+
server: { middlewareMode: true },
|
|
243
|
+
plugins: [apex3({ clientRuntime: "@apex-stack/core/client" })]
|
|
244
|
+
});
|
|
245
|
+
try {
|
|
246
|
+
const resolved = await resolveApexConfig(root, (id) => cfgVite.ssrLoadModule(id));
|
|
247
|
+
runtimeConfig = { public: {}, ...resolved.config.runtimeConfig ?? {} };
|
|
248
|
+
if (!runtimeConfig.public) runtimeConfig.public = {};
|
|
249
|
+
} finally {
|
|
250
|
+
await cfgVite.close();
|
|
251
|
+
}
|
|
198
252
|
const components = {};
|
|
199
253
|
const compDir = join3(root, "components");
|
|
200
|
-
if (
|
|
201
|
-
for (const f of
|
|
254
|
+
if (existsSync3(compDir)) {
|
|
255
|
+
for (const f of readdirSync3(compDir).filter((f2) => f2.endsWith(".alpine"))) {
|
|
202
256
|
const sf = server.modules[`/components/${f}`];
|
|
203
257
|
if (sf) components[f.replace(/\.alpine$/, "")] = sf;
|
|
204
258
|
}
|
|
205
259
|
}
|
|
206
260
|
const api = [];
|
|
207
261
|
const apiDir = join3(root, "server", "api");
|
|
208
|
-
if (
|
|
209
|
-
for (const f of
|
|
262
|
+
if (existsSync3(apiDir)) {
|
|
263
|
+
for (const f of readdirSync3(apiDir).filter((f2) => /\.(ts|js|mjs)$/.test(f2))) {
|
|
210
264
|
const sf = server.modules[`/server/api/${f}`];
|
|
211
265
|
if (sf) api.push({ name: f.replace(/\.(ts|js|mjs)$/, ""), serverFile: sf });
|
|
212
266
|
}
|
|
213
267
|
}
|
|
268
|
+
const middleware = [];
|
|
269
|
+
const mwDir = join3(root, "middleware");
|
|
270
|
+
if (existsSync3(mwDir)) {
|
|
271
|
+
for (const f of readdirSync3(mwDir).filter((f2) => /\.(ts|js|mjs)$/.test(f2)).sort()) {
|
|
272
|
+
const sf = server.modules[`/middleware/${f}`];
|
|
273
|
+
if (sf) middleware.push({ serverFile: sf });
|
|
274
|
+
}
|
|
275
|
+
}
|
|
214
276
|
const manifest = {
|
|
215
277
|
islands: false,
|
|
216
278
|
routes: routes.map((r) => ({
|
|
@@ -219,11 +281,13 @@ async function buildServerTarget(root, outDir, outLabel, routes) {
|
|
|
219
281
|
clientHref: clientHrefs.get(r.pageId)
|
|
220
282
|
})),
|
|
221
283
|
components,
|
|
222
|
-
api
|
|
284
|
+
api,
|
|
285
|
+
middleware,
|
|
286
|
+
runtimeConfig
|
|
223
287
|
};
|
|
224
288
|
writeFileSync(join3(outDir, "apex-manifest.json"), JSON.stringify(manifest, null, 2));
|
|
225
289
|
const pub = join3(root, "public");
|
|
226
|
-
if (
|
|
290
|
+
if (existsSync3(pub)) cpSync(pub, outDir, { recursive: true });
|
|
227
291
|
console.log(
|
|
228
292
|
`
|
|
229
293
|
Built server target \u2192 ${outLabel}/ (${routes.length} route(s), ${api.length} API module(s))
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// src/api/resource.ts
|
|
2
|
+
function isApexResource(x) {
|
|
3
|
+
return typeof x === "object" && x !== null && x.__apexResource === true;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// src/middleware/define.ts
|
|
7
|
+
function defineMiddleware(fn) {
|
|
8
|
+
return fn;
|
|
9
|
+
}
|
|
10
|
+
function isRedirect(value) {
|
|
11
|
+
return !!value && typeof value === "object" && value.__apexRedirect === true;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export {
|
|
15
|
+
isApexResource,
|
|
16
|
+
defineMiddleware,
|
|
17
|
+
isRedirect
|
|
18
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// src/vscode.ts
|
|
2
|
+
import { spawnSync } from "child_process";
|
|
3
|
+
import { existsSync } from "fs";
|
|
4
|
+
import { createInterface } from "readline";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
var VSIX = fileURLToPath(new URL("../vscode/apex-alpine.vsix", import.meta.url));
|
|
7
|
+
var WIN = process.platform === "win32";
|
|
8
|
+
function extensionBundled() {
|
|
9
|
+
return existsSync(VSIX);
|
|
10
|
+
}
|
|
11
|
+
function hasCodeCli() {
|
|
12
|
+
try {
|
|
13
|
+
return spawnSync("code", ["--version"], { stdio: "ignore", shell: WIN }).status === 0;
|
|
14
|
+
} catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function installExtension() {
|
|
19
|
+
if (!existsSync(VSIX)) return false;
|
|
20
|
+
return spawnSync("code", ["--install-extension", VSIX, "--force"], { stdio: "inherit", shell: WIN }).status === 0;
|
|
21
|
+
}
|
|
22
|
+
function promptYesNo(question, def = true) {
|
|
23
|
+
if (!process.stdin.isTTY) return Promise.resolve(def);
|
|
24
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
25
|
+
return new Promise((resolve) => {
|
|
26
|
+
rl.question(`${question} ${def ? "(Y/n) " : "(y/N) "}`, (answer) => {
|
|
27
|
+
rl.close();
|
|
28
|
+
const a = answer.trim().toLowerCase();
|
|
29
|
+
resolve(a === "" ? def : a === "y" || a === "yes");
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
async function offerExtension(choice) {
|
|
34
|
+
if (!extensionBundled() || !hasCodeCli()) return null;
|
|
35
|
+
const yes = choice ?? await promptYesNo("Install the Apex .alpine VS Code extension (syntax highlighting)?");
|
|
36
|
+
if (!yes) return null;
|
|
37
|
+
return installExtension() ? "VS Code extension installed" : "VS Code extension install failed";
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export {
|
|
41
|
+
offerExtension
|
|
42
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
isApexResource
|
|
3
|
-
|
|
2
|
+
isApexResource,
|
|
3
|
+
isRedirect
|
|
4
|
+
} from "./chunk-2C2HRLIY.js";
|
|
4
5
|
|
|
5
6
|
// src/api/routes.ts
|
|
6
7
|
import { existsSync, readdirSync } from "fs";
|
|
@@ -66,7 +67,7 @@ function matchApi(entries, path, method) {
|
|
|
66
67
|
}
|
|
67
68
|
return null;
|
|
68
69
|
}
|
|
69
|
-
function createApiHandler(entries) {
|
|
70
|
+
function createApiHandler(entries, config) {
|
|
70
71
|
return defineEventHandler(async (event) => {
|
|
71
72
|
const url = getRequestURL(event);
|
|
72
73
|
const matched = matchApi(entries, url.pathname, event.method);
|
|
@@ -88,7 +89,12 @@ function createApiHandler(entries) {
|
|
|
88
89
|
}
|
|
89
90
|
input = parsed.data;
|
|
90
91
|
}
|
|
91
|
-
const result = await entry.route.handler({
|
|
92
|
+
const result = await entry.route.handler({
|
|
93
|
+
input,
|
|
94
|
+
url: url.toString(),
|
|
95
|
+
config: config ?? { public: {} },
|
|
96
|
+
locals: event.context.apexLocals ?? {}
|
|
97
|
+
});
|
|
92
98
|
setResponseHeader(event, "Content-Type", "application/json");
|
|
93
99
|
return result;
|
|
94
100
|
});
|
|
@@ -101,7 +107,7 @@ import { defineEventHandler as defineEventHandler2, toWebRequest } from "h3";
|
|
|
101
107
|
function hasMcpRoutes(entries) {
|
|
102
108
|
return entries.some((e) => e.route.mcp);
|
|
103
109
|
}
|
|
104
|
-
function buildServer(entries) {
|
|
110
|
+
function buildServer(entries, config) {
|
|
105
111
|
const server = new McpServer({ name: "apexjs", version: "0.0.0" });
|
|
106
112
|
for (const entry of entries) {
|
|
107
113
|
server.registerTool(
|
|
@@ -111,17 +117,21 @@ function buildServer(entries) {
|
|
|
111
117
|
inputSchema: entry.route.inputShape ?? {}
|
|
112
118
|
},
|
|
113
119
|
async (args) => {
|
|
114
|
-
const result = await entry.route.handler({
|
|
120
|
+
const result = await entry.route.handler({
|
|
121
|
+
input: args ?? {},
|
|
122
|
+
url: `mcp://${entry.mcpName}`,
|
|
123
|
+
config: config ?? { public: {} }
|
|
124
|
+
});
|
|
115
125
|
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
116
126
|
}
|
|
117
127
|
);
|
|
118
128
|
}
|
|
119
129
|
return server;
|
|
120
130
|
}
|
|
121
|
-
function createMcpHandler(entries) {
|
|
131
|
+
function createMcpHandler(entries, config) {
|
|
122
132
|
const mcpEntries = entries.filter((e) => e.route.mcp);
|
|
123
133
|
return defineEventHandler2(async (event) => {
|
|
124
|
-
const server = buildServer(mcpEntries);
|
|
134
|
+
const server = buildServer(mcpEntries, config);
|
|
125
135
|
const transport = new WebStandardStreamableHTTPServerTransport({
|
|
126
136
|
sessionIdGenerator: void 0,
|
|
127
137
|
enableJsonResponse: true
|
|
@@ -133,10 +143,42 @@ function createMcpHandler(entries) {
|
|
|
133
143
|
});
|
|
134
144
|
}
|
|
135
145
|
|
|
146
|
+
// src/middleware/run.ts
|
|
147
|
+
import { existsSync as existsSync2, readdirSync as readdirSync2 } from "fs";
|
|
148
|
+
import { join as join2 } from "path";
|
|
149
|
+
async function loadMiddleware(root, loadModule) {
|
|
150
|
+
const dir = join2(root, "middleware");
|
|
151
|
+
if (!existsSync2(dir)) return [];
|
|
152
|
+
const files = readdirSync2(dir).filter((f) => /\.(ts|js|mjs)$/.test(f)).sort();
|
|
153
|
+
const out = [];
|
|
154
|
+
for (const f of files) {
|
|
155
|
+
const mod = await loadModule(`/middleware/${f}`);
|
|
156
|
+
if (typeof mod.default === "function") out.push(mod.default);
|
|
157
|
+
}
|
|
158
|
+
return out;
|
|
159
|
+
}
|
|
160
|
+
async function runMiddleware(middleware, input) {
|
|
161
|
+
const locals = {};
|
|
162
|
+
for (const mw of middleware) {
|
|
163
|
+
const result = await mw({
|
|
164
|
+
url: input.url,
|
|
165
|
+
method: input.method,
|
|
166
|
+
config: input.config,
|
|
167
|
+
headers: input.headers,
|
|
168
|
+
locals,
|
|
169
|
+
redirect: (to, status = 302) => ({ __apexRedirect: true, to, status })
|
|
170
|
+
});
|
|
171
|
+
if (isRedirect(result)) return { redirect: result, locals };
|
|
172
|
+
}
|
|
173
|
+
return { locals };
|
|
174
|
+
}
|
|
175
|
+
|
|
136
176
|
export {
|
|
137
177
|
expandApiModule,
|
|
138
178
|
loadApiRoutes,
|
|
139
179
|
createApiHandler,
|
|
140
180
|
hasMcpRoutes,
|
|
141
|
-
createMcpHandler
|
|
181
|
+
createMcpHandler,
|
|
182
|
+
loadMiddleware,
|
|
183
|
+
runMiddleware
|
|
142
184
|
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// src/store.ts
|
|
2
|
+
function defineStore(name, factory) {
|
|
3
|
+
if (!name || /[^a-zA-Z0-9_$]/.test(name)) {
|
|
4
|
+
throw new Error(`defineStore: invalid store name "${name}" \u2014 use letters, digits, _ or $.`);
|
|
5
|
+
}
|
|
6
|
+
return { __apexStore: true, name, factory };
|
|
7
|
+
}
|
|
8
|
+
function isApexStore(x) {
|
|
9
|
+
return typeof x === "object" && x !== null && x.__apexStore === true;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// src/config/runtime.ts
|
|
13
|
+
function defineConfig(config) {
|
|
14
|
+
return config;
|
|
15
|
+
}
|
|
16
|
+
var SERVER_KEY = "__APEX_RUNTIME_CONFIG__";
|
|
17
|
+
var CLIENT_KEY = "__APEX_CONFIG__";
|
|
18
|
+
function setRuntimeConfig(cfg) {
|
|
19
|
+
;
|
|
20
|
+
globalThis[SERVER_KEY] = cfg;
|
|
21
|
+
}
|
|
22
|
+
function clientConfigScript(publicConfig) {
|
|
23
|
+
return `<script>window.${CLIENT_KEY}=${JSON.stringify({ public: publicConfig }).replace(/</g, "\\u003c")}</script>`;
|
|
24
|
+
}
|
|
25
|
+
function useRuntimeConfig() {
|
|
26
|
+
if (typeof window !== "undefined") {
|
|
27
|
+
return window[CLIENT_KEY] ?? {
|
|
28
|
+
public: {}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
return globalThis[SERVER_KEY] ?? { public: {} };
|
|
32
|
+
}
|
|
33
|
+
function env(key, fallback) {
|
|
34
|
+
if (typeof process !== "undefined" && process.env && process.env[key] !== void 0) {
|
|
35
|
+
return process.env[key];
|
|
36
|
+
}
|
|
37
|
+
return fallback;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export {
|
|
41
|
+
defineStore,
|
|
42
|
+
isApexStore,
|
|
43
|
+
defineConfig,
|
|
44
|
+
setRuntimeConfig,
|
|
45
|
+
clientConfigScript,
|
|
46
|
+
useRuntimeConfig,
|
|
47
|
+
env
|
|
48
|
+
};
|