@apex-stack/core 0.1.10 → 0.1.12
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-QRHQUUZC.js +235 -0
- package/dist/chunk-2L2T47AH.js +93 -0
- package/dist/chunk-4VG3CZ6H.js +21 -0
- package/dist/chunk-DSUIB3JH.js +144 -0
- package/dist/chunk-PAMD24NK.js +171 -0
- package/dist/chunk-SH3XEJGV.js +239 -0
- package/dist/cli.js +23 -664
- package/dist/dev-V3LVSS5L.js +38 -0
- package/dist/index.js +8 -3
- package/dist/make-4LINTKZH.js +89 -0
- package/dist/mcp-DL4J6JFJ.js +56 -0
- package/dist/migrate-NOGFOFV2.js +38 -0
- package/dist/server-ODH3M2IG.js +9 -0
- package/dist/start-VJJXI4W3.js +132 -0
- package/package.json +1 -1
- package/dist/chunk-IEXQ7E5C.js +0 -426
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {
|
|
2
|
+
banner,
|
|
3
|
+
ready,
|
|
4
|
+
spinner
|
|
5
|
+
} from "./chunk-2L2T47AH.js";
|
|
6
|
+
|
|
7
|
+
// src/commands/dev.ts
|
|
8
|
+
import { resolve } from "path";
|
|
9
|
+
import { defineCommand } from "citty";
|
|
10
|
+
var devCommand = defineCommand({
|
|
11
|
+
meta: { name: "dev", description: "Start the Apex JS development server" },
|
|
12
|
+
args: {
|
|
13
|
+
root: { type: "positional", required: false, description: "Project root", default: "." },
|
|
14
|
+
port: { type: "string", description: "Port to listen on", default: "3000" },
|
|
15
|
+
islands: { type: "boolean", description: "Render in islands mode (static-first)", default: false }
|
|
16
|
+
},
|
|
17
|
+
async run({ args }) {
|
|
18
|
+
const root = resolve(process.cwd(), String(args.root));
|
|
19
|
+
const port = Number(args.port);
|
|
20
|
+
process.stdout.write(banner());
|
|
21
|
+
const sp = spinner(`Starting dev server${args.islands ? " (islands mode)" : ""}\u2026`);
|
|
22
|
+
try {
|
|
23
|
+
const { startDevServer } = await import("./server-ODH3M2IG.js");
|
|
24
|
+
const { port: actual } = await startDevServer({ root, port, islands: Boolean(args.islands) });
|
|
25
|
+
sp.succeed("Dev server ready");
|
|
26
|
+
ready([
|
|
27
|
+
["Local", `http://localhost:${actual}/`],
|
|
28
|
+
["MCP", `http://localhost:${actual}/mcp`]
|
|
29
|
+
]);
|
|
30
|
+
} catch (err) {
|
|
31
|
+
sp.fail("Failed to start the dev server");
|
|
32
|
+
throw err;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
export {
|
|
37
|
+
devCommand
|
|
38
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
-
isApexResource,
|
|
3
|
-
renderPage,
|
|
4
2
|
startDevServer
|
|
5
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-SH3XEJGV.js";
|
|
4
|
+
import "./chunk-4VG3CZ6H.js";
|
|
5
|
+
import {
|
|
6
|
+
isApexResource
|
|
7
|
+
} from "./chunk-DSUIB3JH.js";
|
|
8
|
+
import {
|
|
9
|
+
renderPage
|
|
10
|
+
} from "./chunk-PAMD24NK.js";
|
|
6
11
|
|
|
7
12
|
// src/api/defineRoute.ts
|
|
8
13
|
function defineApexRoute(config) {
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// src/commands/make.ts
|
|
2
|
+
import { existsSync, mkdirSync, writeFileSync } from "fs";
|
|
3
|
+
import { dirname, join, resolve } from "path";
|
|
4
|
+
import { defineCommand } from "citty";
|
|
5
|
+
function pageTemplate(name) {
|
|
6
|
+
return `<script server lang="ts">
|
|
7
|
+
export function loader() {
|
|
8
|
+
return { title: '${name}' }
|
|
9
|
+
}
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<template x-data>
|
|
13
|
+
<main>
|
|
14
|
+
<h1 x-text="title"></h1>
|
|
15
|
+
</main>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<style scoped>
|
|
19
|
+
main { max-width: 40rem; margin: 3rem auto; font-family: system-ui, sans-serif; }
|
|
20
|
+
</style>
|
|
21
|
+
`;
|
|
22
|
+
}
|
|
23
|
+
function componentTemplate() {
|
|
24
|
+
return `<template x-data="{ count: 0 }">
|
|
25
|
+
<button @click="count++" x-text="count"></button>
|
|
26
|
+
</template>
|
|
27
|
+
|
|
28
|
+
<style scoped>
|
|
29
|
+
button { cursor: pointer; }
|
|
30
|
+
</style>
|
|
31
|
+
`;
|
|
32
|
+
}
|
|
33
|
+
function apiTemplate(name) {
|
|
34
|
+
return `import { defineApexRoute } from '@apex-stack/core'
|
|
35
|
+
import { z } from 'zod'
|
|
36
|
+
|
|
37
|
+
// GET /api/${name} \xB7 MCP tool "${name}"
|
|
38
|
+
export default defineApexRoute({
|
|
39
|
+
method: 'GET',
|
|
40
|
+
description: 'Describe what ${name} does',
|
|
41
|
+
input: { name: z.string() },
|
|
42
|
+
mcp: true,
|
|
43
|
+
handler: ({ input }) => ({ message: \`Hello, \${input.name}!\` }),
|
|
44
|
+
})
|
|
45
|
+
`;
|
|
46
|
+
}
|
|
47
|
+
function plan(kind, name, root) {
|
|
48
|
+
switch (kind) {
|
|
49
|
+
case "page":
|
|
50
|
+
return { path: join(root, "pages", `${name}.alpine`), contents: pageTemplate(name) };
|
|
51
|
+
case "component":
|
|
52
|
+
return { path: join(root, "components", `${name}.alpine`), contents: componentTemplate() };
|
|
53
|
+
case "api":
|
|
54
|
+
return { path: join(root, "server", "api", `${name}.ts`), contents: apiTemplate(name) };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
var makeCommand = defineCommand({
|
|
58
|
+
meta: { name: "make", description: "Generate a page, component, or API route" },
|
|
59
|
+
args: {
|
|
60
|
+
kind: { type: "positional", required: true, description: "page | component | api" },
|
|
61
|
+
name: { type: "positional", required: true, description: "Name (about, Counter, todos, \u2026)" },
|
|
62
|
+
root: { type: "string", description: "Project root", default: "." }
|
|
63
|
+
},
|
|
64
|
+
run({ args }) {
|
|
65
|
+
const kind = args.kind;
|
|
66
|
+
if (kind !== "page" && kind !== "component" && kind !== "api") {
|
|
67
|
+
console.error(`
|
|
68
|
+
Unknown type "${args.kind}". Use: page | component | api
|
|
69
|
+
`);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
const root = resolve(process.cwd(), args.root);
|
|
73
|
+
const { path, contents } = plan(kind, args.name, root);
|
|
74
|
+
if (existsSync(path)) {
|
|
75
|
+
console.error(`
|
|
76
|
+
\u2717 Already exists: ${path}
|
|
77
|
+
`);
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
81
|
+
writeFileSync(path, contents);
|
|
82
|
+
console.log(`
|
|
83
|
+
\u2713 Created ${path.replace(`${root}/`, "")}
|
|
84
|
+
`);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
export {
|
|
88
|
+
makeCommand
|
|
89
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// src/commands/mcp.ts
|
|
2
|
+
import { defineCommand } from "citty";
|
|
3
|
+
var mcpCommand = defineCommand({
|
|
4
|
+
meta: { name: "mcp", description: "Inspect the local MCP server (list or call tools)" },
|
|
5
|
+
args: {
|
|
6
|
+
url: { type: "string", description: "MCP endpoint URL", default: "http://localhost:3000/mcp" },
|
|
7
|
+
call: { type: "string", description: "Name of a tool to call" },
|
|
8
|
+
args: { type: "string", description: "JSON arguments for --call", default: "{}" }
|
|
9
|
+
},
|
|
10
|
+
async run({ args }) {
|
|
11
|
+
const { Client } = await import("@modelcontextprotocol/sdk/client/index.js");
|
|
12
|
+
const { StreamableHTTPClientTransport } = await import("@modelcontextprotocol/sdk/client/streamableHttp.js");
|
|
13
|
+
const client = new Client({ name: "apex-mcp-cli", version: "0.0.0" });
|
|
14
|
+
try {
|
|
15
|
+
await client.connect(new StreamableHTTPClientTransport(new URL(args.url)));
|
|
16
|
+
} catch (err) {
|
|
17
|
+
console.error(
|
|
18
|
+
`
|
|
19
|
+
Could not reach an MCP server at ${args.url}
|
|
20
|
+
Is \`apex dev\` running? ${err.message}
|
|
21
|
+
`
|
|
22
|
+
);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
if (args.call) {
|
|
26
|
+
const result = await client.callTool({
|
|
27
|
+
name: args.call,
|
|
28
|
+
arguments: JSON.parse(args.args)
|
|
29
|
+
});
|
|
30
|
+
console.log(`
|
|
31
|
+
\x1B[36m${args.call}\x1B[0m(${args.args}) \u2192`);
|
|
32
|
+
for (const part of result.content) {
|
|
33
|
+
console.log(" " + (part.text ?? JSON.stringify(part)));
|
|
34
|
+
}
|
|
35
|
+
console.log();
|
|
36
|
+
} else {
|
|
37
|
+
const { tools } = await client.listTools();
|
|
38
|
+
console.log(`
|
|
39
|
+
\x1B[36mMCP tools\x1B[0m at ${args.url} (${tools.length})
|
|
40
|
+
`);
|
|
41
|
+
for (const t of tools) {
|
|
42
|
+
const props = t.inputSchema?.properties;
|
|
43
|
+
const sig = props ? Object.entries(props).map(([k, v]) => `${k}: ${v.type ?? "any"}`).join(", ") : "";
|
|
44
|
+
console.log(` \u2022 \x1B[1m${t.name}\x1B[0m(${sig})`);
|
|
45
|
+
if (t.description) console.log(` ${t.description}`);
|
|
46
|
+
}
|
|
47
|
+
console.log(`
|
|
48
|
+
Call one: apex mcp --call <name> --args '{...}'
|
|
49
|
+
`);
|
|
50
|
+
}
|
|
51
|
+
await client.close();
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
export {
|
|
55
|
+
mcpCommand
|
|
56
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// src/commands/migrate.ts
|
|
2
|
+
import { createRequire } from "module";
|
|
3
|
+
import { join, resolve } from "path";
|
|
4
|
+
import { pathToFileURL } from "url";
|
|
5
|
+
import { defineCommand } from "citty";
|
|
6
|
+
var migrateCommand = defineCommand({
|
|
7
|
+
meta: { name: "migrate", description: "Apply pending SQL migrations (db/migrations/*.sql)" },
|
|
8
|
+
args: {
|
|
9
|
+
db: { type: "string", description: "SQLite file path (libSQL)", default: "data.db" },
|
|
10
|
+
driver: { type: "string", description: "sqlite | postgres | pglite", default: "sqlite" },
|
|
11
|
+
url: { type: "string", description: "Connection URL (postgres) \u2014 overrides --db" },
|
|
12
|
+
dir: { type: "string", description: "Migrations directory", default: "db/migrations" },
|
|
13
|
+
root: { type: "string", description: "Project root", default: "." }
|
|
14
|
+
},
|
|
15
|
+
async run({ args }) {
|
|
16
|
+
const root = resolve(process.cwd(), args.root);
|
|
17
|
+
let data;
|
|
18
|
+
try {
|
|
19
|
+
const require2 = createRequire(join(root, "package.json"));
|
|
20
|
+
data = await import(pathToFileURL(require2.resolve("@apex-stack/data")).href);
|
|
21
|
+
} catch {
|
|
22
|
+
console.error("\n @apex-stack/data is not installed in this project. Run: npm i @apex-stack/data\n");
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
const config = args.driver === "postgres" ? { driver: "postgres", url: args.url } : args.driver === "pglite" ? { driver: "pglite", dir: args.url } : resolve(root, args.db);
|
|
26
|
+
const handle = await data.createDb(config);
|
|
27
|
+
const applied = await data.applyMigrations(handle, resolve(root, args.dir));
|
|
28
|
+
await handle.close();
|
|
29
|
+
console.log(
|
|
30
|
+
applied.length ? `
|
|
31
|
+
\u2713 Applied ${applied.length} migration(s): ${applied.join(", ")}
|
|
32
|
+
` : "\n \u2713 Up to date \u2014 no pending migrations.\n"
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
export {
|
|
37
|
+
migrateCommand
|
|
38
|
+
};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createApiHandler,
|
|
3
|
+
createMcpHandler,
|
|
4
|
+
expandApiModule,
|
|
5
|
+
hasMcpRoutes
|
|
6
|
+
} from "./chunk-DSUIB3JH.js";
|
|
7
|
+
import {
|
|
8
|
+
matchRoute,
|
|
9
|
+
renderIslandsPage,
|
|
10
|
+
renderPage
|
|
11
|
+
} from "./chunk-PAMD24NK.js";
|
|
12
|
+
|
|
13
|
+
// src/commands/start.ts
|
|
14
|
+
import { existsSync as existsSync2 } from "fs";
|
|
15
|
+
import { join as join2, resolve } from "path";
|
|
16
|
+
import { defineCommand } from "citty";
|
|
17
|
+
|
|
18
|
+
// src/prod/server.ts
|
|
19
|
+
import { createServer as createHttpServer } from "http";
|
|
20
|
+
import { existsSync, readFileSync, statSync } from "fs";
|
|
21
|
+
import { join } from "path";
|
|
22
|
+
import { pathToFileURL } from "url";
|
|
23
|
+
import {
|
|
24
|
+
createApp,
|
|
25
|
+
defineEventHandler,
|
|
26
|
+
getRequestURL,
|
|
27
|
+
setResponseHeader,
|
|
28
|
+
setResponseStatus,
|
|
29
|
+
toNodeListener
|
|
30
|
+
} from "h3";
|
|
31
|
+
var MIME = {
|
|
32
|
+
".js": "text/javascript",
|
|
33
|
+
".mjs": "text/javascript",
|
|
34
|
+
".css": "text/css",
|
|
35
|
+
".html": "text/html",
|
|
36
|
+
".json": "application/json",
|
|
37
|
+
".svg": "image/svg+xml",
|
|
38
|
+
".png": "image/png",
|
|
39
|
+
".jpg": "image/jpeg",
|
|
40
|
+
".ico": "image/x-icon",
|
|
41
|
+
".woff2": "font/woff2"
|
|
42
|
+
};
|
|
43
|
+
async function startProdServer(options) {
|
|
44
|
+
const dir = options.dir;
|
|
45
|
+
const port = options.port ?? 3e3;
|
|
46
|
+
const manifest = JSON.parse(readFileSync(join(dir, "apex-manifest.json"), "utf8"));
|
|
47
|
+
const importServer = (relFile) => import(pathToFileURL(join(dir, "server", relFile)).href);
|
|
48
|
+
const registry = {};
|
|
49
|
+
let componentCss = "";
|
|
50
|
+
for (const [name, file] of Object.entries(manifest.components)) {
|
|
51
|
+
const mod = await importServer(file);
|
|
52
|
+
registry[name] = { template: mod.template, rootXData: mod.rootXData, scopeId: mod.scopeId };
|
|
53
|
+
if (mod.css) componentCss += `${mod.css}
|
|
54
|
+
`;
|
|
55
|
+
}
|
|
56
|
+
const apiEntries = [];
|
|
57
|
+
for (const { name, serverFile } of manifest.api) {
|
|
58
|
+
const mod = await importServer(serverFile);
|
|
59
|
+
apiEntries.push(...expandApiModule(name, mod.default));
|
|
60
|
+
}
|
|
61
|
+
const serverFileFor = new Map(manifest.routes.map((r) => [r.pageId, r.serverFile]));
|
|
62
|
+
const loadModule = (id) => importServer(serverFileFor.get(id));
|
|
63
|
+
const app = createApp();
|
|
64
|
+
app.use(
|
|
65
|
+
defineEventHandler((event) => {
|
|
66
|
+
if (event.method !== "GET") return;
|
|
67
|
+
const path = decodeURIComponent(getRequestURL(event).pathname);
|
|
68
|
+
if (path === "/" || path.startsWith("/api") || path === "/mcp") return;
|
|
69
|
+
const file = join(dir, path);
|
|
70
|
+
if (!file.startsWith(dir) || !existsSync(file) || !statSync(file).isFile()) return;
|
|
71
|
+
const ext = path.slice(path.lastIndexOf("."));
|
|
72
|
+
setResponseHeader(event, "Content-Type", MIME[ext] ?? "application/octet-stream");
|
|
73
|
+
if (path.startsWith("/assets/")) setResponseHeader(event, "Cache-Control", "public, max-age=31536000, immutable");
|
|
74
|
+
return readFileSync(file);
|
|
75
|
+
})
|
|
76
|
+
);
|
|
77
|
+
if (apiEntries.length) app.use("/api", createApiHandler(apiEntries));
|
|
78
|
+
if (hasMcpRoutes(apiEntries)) app.use("/mcp", createMcpHandler(apiEntries));
|
|
79
|
+
app.use(
|
|
80
|
+
defineEventHandler(async (event) => {
|
|
81
|
+
const url = getRequestURL(event).pathname;
|
|
82
|
+
const matched = matchRoute(manifest.routes, url);
|
|
83
|
+
if (!matched) {
|
|
84
|
+
setResponseStatus(event, 404);
|
|
85
|
+
setResponseHeader(event, "Content-Type", "text/html");
|
|
86
|
+
return `<!DOCTYPE html><h1>404 \u2014 ${url}</h1>`;
|
|
87
|
+
}
|
|
88
|
+
const route = manifest.routes.find((r) => r.pageId === matched.pageId);
|
|
89
|
+
const render = manifest.islands ? renderIslandsPage : renderPage;
|
|
90
|
+
const html = await render({
|
|
91
|
+
loadModule,
|
|
92
|
+
pageId: matched.pageId,
|
|
93
|
+
params: matched.params,
|
|
94
|
+
url,
|
|
95
|
+
registry,
|
|
96
|
+
componentCss,
|
|
97
|
+
clientHref: route?.clientHref
|
|
98
|
+
});
|
|
99
|
+
setResponseHeader(event, "Content-Type", "text/html");
|
|
100
|
+
return html;
|
|
101
|
+
})
|
|
102
|
+
);
|
|
103
|
+
const server = createHttpServer(toNodeListener(app));
|
|
104
|
+
await new Promise((resolve2) => server.listen(port, resolve2));
|
|
105
|
+
return { server, port };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// src/commands/start.ts
|
|
109
|
+
var startCommand = defineCommand({
|
|
110
|
+
meta: { name: "start", description: "Run a production build (from `apex build --server`)" },
|
|
111
|
+
args: {
|
|
112
|
+
dir: { type: "positional", required: false, description: "Build directory", default: "dist" },
|
|
113
|
+
port: { type: "string", description: "Port to listen on", default: "3000" }
|
|
114
|
+
},
|
|
115
|
+
async run({ args }) {
|
|
116
|
+
const dir = resolve(process.cwd(), args.dir);
|
|
117
|
+
if (!existsSync2(join2(dir, "apex-manifest.json"))) {
|
|
118
|
+
console.error(`
|
|
119
|
+
No build found in ${args.dir}/. Run \`apex build --server\` first.
|
|
120
|
+
`);
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
const { port } = await startProdServer({ dir, port: Number(args.port) });
|
|
124
|
+
console.log(`
|
|
125
|
+
\x1B[36mApex JS\x1B[0m production server
|
|
126
|
+
\u2192 http://localhost:${port}
|
|
127
|
+
`);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
export {
|
|
131
|
+
startCommand
|
|
132
|
+
};
|