@apex-stack/core 0.1.1 → 0.1.2
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-XB5ZYPPE.js → chunk-GC3WNE6M.js} +13 -8
- package/dist/cli.js +159 -27
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -1
- package/package.json +3 -3
|
@@ -20,11 +20,18 @@ async function renderPage(opts) {
|
|
|
20
20
|
body: html,
|
|
21
21
|
island: stateIsland(mod.componentId, loaderData),
|
|
22
22
|
css: mod.css + (opts.componentCss ?? ""),
|
|
23
|
-
pageId: opts.pageId
|
|
23
|
+
pageId: opts.pageId,
|
|
24
|
+
clientHref: opts.clientHref
|
|
24
25
|
});
|
|
25
26
|
return opts.transformHtml ? opts.transformHtml(opts.url, doc) : doc;
|
|
26
27
|
}
|
|
27
|
-
function shell({ body, island, css, pageId }) {
|
|
28
|
+
function shell({ body, island, css, pageId, clientHref }) {
|
|
29
|
+
const clientScript = clientHref ? `<script type="module" src="${clientHref}"></script>` : `<script type="module">
|
|
30
|
+
import Alpine from 'alpinejs'
|
|
31
|
+
import ${JSON.stringify(pageId)}
|
|
32
|
+
window.Alpine = Alpine
|
|
33
|
+
Alpine.start()
|
|
34
|
+
</script>`;
|
|
28
35
|
return `<!DOCTYPE html>
|
|
29
36
|
<html lang="en">
|
|
30
37
|
<head>
|
|
@@ -36,12 +43,7 @@ function shell({ body, island, css, pageId }) {
|
|
|
36
43
|
<body>
|
|
37
44
|
${body}
|
|
38
45
|
${island}
|
|
39
|
-
|
|
40
|
-
import Alpine from 'alpinejs'
|
|
41
|
-
import ${JSON.stringify(pageId)}
|
|
42
|
-
window.Alpine = Alpine
|
|
43
|
-
Alpine.start()
|
|
44
|
-
</script>
|
|
46
|
+
${clientScript}
|
|
45
47
|
</body>
|
|
46
48
|
</html>`;
|
|
47
49
|
}
|
|
@@ -408,6 +410,9 @@ function notFoundPage(url, routes) {
|
|
|
408
410
|
|
|
409
411
|
export {
|
|
410
412
|
isApexResource,
|
|
413
|
+
loadComponents,
|
|
414
|
+
renderIslandsPage,
|
|
415
|
+
scanPages,
|
|
411
416
|
renderPage,
|
|
412
417
|
startDevServer
|
|
413
418
|
};
|
package/dist/cli.js
CHANGED
|
@@ -1,15 +1,141 @@
|
|
|
1
1
|
import {
|
|
2
|
+
loadComponents,
|
|
3
|
+
renderIslandsPage,
|
|
4
|
+
renderPage,
|
|
5
|
+
scanPages,
|
|
2
6
|
startDevServer
|
|
3
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-GC3WNE6M.js";
|
|
4
8
|
|
|
5
9
|
// src/cli.ts
|
|
6
|
-
import { resolve as
|
|
7
|
-
import { defineCommand as
|
|
10
|
+
import { resolve as resolve4 } from "path";
|
|
11
|
+
import { defineCommand as defineCommand5, runMain } from "citty";
|
|
8
12
|
|
|
9
|
-
// src/commands/
|
|
10
|
-
import { existsSync, mkdirSync, writeFileSync } from "fs";
|
|
11
|
-
import { dirname, join, resolve } from "path";
|
|
13
|
+
// src/commands/build.ts
|
|
14
|
+
import { cpSync, existsSync, mkdirSync, rmSync, writeFileSync } from "fs";
|
|
15
|
+
import { dirname, join as join2, resolve } from "path";
|
|
16
|
+
import { apex as apex2 } from "@apex-stack/vite";
|
|
12
17
|
import { defineCommand } from "citty";
|
|
18
|
+
import { createServer as createViteServer } from "vite";
|
|
19
|
+
|
|
20
|
+
// src/build/buildClient.ts
|
|
21
|
+
import { readFileSync } from "fs";
|
|
22
|
+
import { join } from "path";
|
|
23
|
+
import { apex } from "@apex-stack/vite";
|
|
24
|
+
import { build } from "vite";
|
|
25
|
+
var VIRT = "virtual:apex-client:";
|
|
26
|
+
function entryName(pageId) {
|
|
27
|
+
return pageId.replace(/^\/pages\//, "").replace(/\.alpine$/, "").replace(/[^a-zA-Z0-9]+/g, "_");
|
|
28
|
+
}
|
|
29
|
+
async function buildClient(root, routes, outDir) {
|
|
30
|
+
const input = {};
|
|
31
|
+
for (const r of routes) input[entryName(r.pageId)] = `${VIRT}${r.pageId}`;
|
|
32
|
+
const entryPlugin = {
|
|
33
|
+
name: "apex:client-entries",
|
|
34
|
+
resolveId(id) {
|
|
35
|
+
if (id.startsWith(VIRT)) return `\0${id}`;
|
|
36
|
+
},
|
|
37
|
+
load(id) {
|
|
38
|
+
if (id.startsWith(`\0${VIRT}`)) {
|
|
39
|
+
const pageId = id.slice(`\0${VIRT}`.length);
|
|
40
|
+
return [
|
|
41
|
+
`import Alpine from 'alpinejs'`,
|
|
42
|
+
`import ${JSON.stringify(pageId)}`,
|
|
43
|
+
`window.Alpine = Alpine`,
|
|
44
|
+
`Alpine.start()`
|
|
45
|
+
].join("\n");
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
await build({
|
|
50
|
+
root,
|
|
51
|
+
logLevel: "warn",
|
|
52
|
+
plugins: [apex({ clientRuntime: "@apex-stack/core/client" }), entryPlugin],
|
|
53
|
+
build: {
|
|
54
|
+
outDir,
|
|
55
|
+
emptyOutDir: false,
|
|
56
|
+
manifest: true,
|
|
57
|
+
rollupOptions: { input }
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
const manifest = JSON.parse(readFileSync(join(outDir, ".vite", "manifest.json"), "utf8"));
|
|
61
|
+
const hrefs = /* @__PURE__ */ new Map();
|
|
62
|
+
for (const r of routes) {
|
|
63
|
+
const virt = `${VIRT}${r.pageId}`;
|
|
64
|
+
const entry = Object.values(manifest).find(
|
|
65
|
+
(m) => m.isEntry && (m.src === virt || m.src === `\0${virt}`)
|
|
66
|
+
);
|
|
67
|
+
if (entry) hrefs.set(r.pageId, `/${entry.file}`);
|
|
68
|
+
}
|
|
69
|
+
return hrefs;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// src/commands/build.ts
|
|
73
|
+
function outFile(pattern) {
|
|
74
|
+
const clean = pattern.replace(/^\//, "");
|
|
75
|
+
return clean === "" ? "index.html" : `${clean}/index.html`;
|
|
76
|
+
}
|
|
77
|
+
var buildCommand = defineCommand({
|
|
78
|
+
meta: { name: "build", description: "Prerender pages to deployable HTML + client bundles" },
|
|
79
|
+
args: {
|
|
80
|
+
root: { type: "positional", required: false, description: "Project root", default: "." },
|
|
81
|
+
outDir: { type: "string", description: "Output directory", default: "dist" },
|
|
82
|
+
islands: { type: "boolean", description: "Static-first islands mode (zero-JS static)", default: false }
|
|
83
|
+
},
|
|
84
|
+
async run({ args }) {
|
|
85
|
+
const root = resolve(process.cwd(), args.root);
|
|
86
|
+
const outDir = resolve(root, args.outDir);
|
|
87
|
+
rmSync(outDir, { recursive: true, force: true });
|
|
88
|
+
const routes = scanPages(root);
|
|
89
|
+
const staticRoutes = routes.filter((r) => !r.isDynamic);
|
|
90
|
+
const dynamic = routes.filter((r) => r.isDynamic);
|
|
91
|
+
const hrefs = args.islands ? /* @__PURE__ */ new Map() : await buildClient(root, staticRoutes, outDir);
|
|
92
|
+
const vite = await createViteServer({
|
|
93
|
+
root,
|
|
94
|
+
appType: "custom",
|
|
95
|
+
server: { middlewareMode: true },
|
|
96
|
+
plugins: [apex2({ clientRuntime: "@apex-stack/core/client" })]
|
|
97
|
+
});
|
|
98
|
+
try {
|
|
99
|
+
const { registry, css: componentCss } = await loadComponents(
|
|
100
|
+
root,
|
|
101
|
+
(id) => vite.ssrLoadModule(id)
|
|
102
|
+
);
|
|
103
|
+
for (const route of staticRoutes) {
|
|
104
|
+
const common = {
|
|
105
|
+
loadModule: (id) => vite.ssrLoadModule(id),
|
|
106
|
+
pageId: route.pageId,
|
|
107
|
+
url: route.pattern,
|
|
108
|
+
registry,
|
|
109
|
+
componentCss
|
|
110
|
+
};
|
|
111
|
+
const html = args.islands ? await renderIslandsPage(common) : await renderPage({ ...common, clientHref: hrefs.get(route.pageId) });
|
|
112
|
+
const dest = join2(outDir, outFile(route.pattern));
|
|
113
|
+
mkdirSync(dirname(dest), { recursive: true });
|
|
114
|
+
writeFileSync(dest, html);
|
|
115
|
+
console.log(` \u2713 ${route.pattern} \u2192 ${outFile(route.pattern)}`);
|
|
116
|
+
}
|
|
117
|
+
const pub = join2(root, "public");
|
|
118
|
+
if (existsSync(pub)) cpSync(pub, outDir, { recursive: true });
|
|
119
|
+
console.log(
|
|
120
|
+
`
|
|
121
|
+
Built ${staticRoutes.length} page(s) \u2192 ${args.outDir}/` + (args.islands ? " (islands / static-first)" : " (prerendered + hydrated)")
|
|
122
|
+
);
|
|
123
|
+
if (dynamic.length) {
|
|
124
|
+
console.log(
|
|
125
|
+
` Skipped ${dynamic.length} dynamic route(s): ${dynamic.map((r) => r.pattern).join(", ")} (server target on the roadmap).`
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
console.log();
|
|
129
|
+
} finally {
|
|
130
|
+
await vite.close();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// src/commands/make.ts
|
|
136
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
137
|
+
import { dirname as dirname2, join as join3, resolve as resolve2 } from "path";
|
|
138
|
+
import { defineCommand as defineCommand2 } from "citty";
|
|
13
139
|
function pageTemplate(name) {
|
|
14
140
|
return `<script server lang="ts">
|
|
15
141
|
export function loader() {
|
|
@@ -55,14 +181,14 @@ export default defineApexRoute({
|
|
|
55
181
|
function plan(kind, name, root) {
|
|
56
182
|
switch (kind) {
|
|
57
183
|
case "page":
|
|
58
|
-
return { path:
|
|
184
|
+
return { path: join3(root, "pages", `${name}.alpine`), contents: pageTemplate(name) };
|
|
59
185
|
case "component":
|
|
60
|
-
return { path:
|
|
186
|
+
return { path: join3(root, "components", `${name}.alpine`), contents: componentTemplate() };
|
|
61
187
|
case "api":
|
|
62
|
-
return { path:
|
|
188
|
+
return { path: join3(root, "server", "api", `${name}.ts`), contents: apiTemplate(name) };
|
|
63
189
|
}
|
|
64
190
|
}
|
|
65
|
-
var makeCommand =
|
|
191
|
+
var makeCommand = defineCommand2({
|
|
66
192
|
meta: { name: "make", description: "Generate a page, component, or API route" },
|
|
67
193
|
args: {
|
|
68
194
|
kind: { type: "positional", required: true, description: "page | component | api" },
|
|
@@ -77,16 +203,16 @@ var makeCommand = defineCommand({
|
|
|
77
203
|
`);
|
|
78
204
|
process.exit(1);
|
|
79
205
|
}
|
|
80
|
-
const root =
|
|
206
|
+
const root = resolve2(process.cwd(), args.root);
|
|
81
207
|
const { path, contents } = plan(kind, args.name, root);
|
|
82
|
-
if (
|
|
208
|
+
if (existsSync2(path)) {
|
|
83
209
|
console.error(`
|
|
84
210
|
\u2717 Already exists: ${path}
|
|
85
211
|
`);
|
|
86
212
|
process.exit(1);
|
|
87
213
|
}
|
|
88
|
-
|
|
89
|
-
|
|
214
|
+
mkdirSync2(dirname2(path), { recursive: true });
|
|
215
|
+
writeFileSync2(path, contents);
|
|
90
216
|
console.log(`
|
|
91
217
|
\u2713 Created ${path.replace(`${root}/`, "")}
|
|
92
218
|
`);
|
|
@@ -94,8 +220,8 @@ var makeCommand = defineCommand({
|
|
|
94
220
|
});
|
|
95
221
|
|
|
96
222
|
// src/commands/mcp.ts
|
|
97
|
-
import { defineCommand as
|
|
98
|
-
var mcpCommand =
|
|
223
|
+
import { defineCommand as defineCommand3 } from "citty";
|
|
224
|
+
var mcpCommand = defineCommand3({
|
|
99
225
|
meta: { name: "mcp", description: "Inspect the local MCP server (list or call tools)" },
|
|
100
226
|
args: {
|
|
101
227
|
url: { type: "string", description: "MCP endpoint URL", default: "http://localhost:3000/mcp" },
|
|
@@ -149,10 +275,10 @@ var mcpCommand = defineCommand2({
|
|
|
149
275
|
|
|
150
276
|
// src/commands/migrate.ts
|
|
151
277
|
import { createRequire } from "module";
|
|
152
|
-
import { join as
|
|
278
|
+
import { join as join4, resolve as resolve3 } from "path";
|
|
153
279
|
import { pathToFileURL } from "url";
|
|
154
|
-
import { defineCommand as
|
|
155
|
-
var migrateCommand =
|
|
280
|
+
import { defineCommand as defineCommand4 } from "citty";
|
|
281
|
+
var migrateCommand = defineCommand4({
|
|
156
282
|
meta: { name: "migrate", description: "Apply pending SQL migrations (db/migrations/*.sql)" },
|
|
157
283
|
args: {
|
|
158
284
|
db: { type: "string", description: "SQLite file path", default: "data.db" },
|
|
@@ -160,17 +286,17 @@ var migrateCommand = defineCommand3({
|
|
|
160
286
|
root: { type: "string", description: "Project root", default: "." }
|
|
161
287
|
},
|
|
162
288
|
async run({ args }) {
|
|
163
|
-
const root =
|
|
289
|
+
const root = resolve3(process.cwd(), args.root);
|
|
164
290
|
let data;
|
|
165
291
|
try {
|
|
166
|
-
const require2 = createRequire(
|
|
292
|
+
const require2 = createRequire(join4(root, "package.json"));
|
|
167
293
|
data = await import(pathToFileURL(require2.resolve("@apex-stack/data")).href);
|
|
168
294
|
} catch {
|
|
169
295
|
console.error("\n @apex-stack/data is not installed in this project. Run: npm i @apex-stack/data\n");
|
|
170
296
|
process.exit(1);
|
|
171
297
|
}
|
|
172
|
-
const { sqlite } = data.createDb(
|
|
173
|
-
const applied = data.applyMigrations(sqlite,
|
|
298
|
+
const { sqlite } = data.createDb(resolve3(root, args.db));
|
|
299
|
+
const applied = data.applyMigrations(sqlite, resolve3(root, args.dir));
|
|
174
300
|
console.log(
|
|
175
301
|
applied.length ? `
|
|
176
302
|
\u2713 Applied ${applied.length} migration(s): ${applied.join(", ")}
|
|
@@ -180,7 +306,7 @@ var migrateCommand = defineCommand3({
|
|
|
180
306
|
});
|
|
181
307
|
|
|
182
308
|
// src/cli.ts
|
|
183
|
-
var dev =
|
|
309
|
+
var dev = defineCommand5({
|
|
184
310
|
meta: { name: "dev", description: "Start the Apex JS development server" },
|
|
185
311
|
args: {
|
|
186
312
|
root: { type: "positional", required: false, description: "Project root", default: "." },
|
|
@@ -188,7 +314,7 @@ var dev = defineCommand4({
|
|
|
188
314
|
islands: { type: "boolean", description: "Render in islands mode (static-first)", default: false }
|
|
189
315
|
},
|
|
190
316
|
async run({ args }) {
|
|
191
|
-
const root =
|
|
317
|
+
const root = resolve4(process.cwd(), args.root);
|
|
192
318
|
const port = Number(args.port);
|
|
193
319
|
const { port: actual } = await startDevServer({ root, port, islands: args.islands });
|
|
194
320
|
console.log(`
|
|
@@ -197,11 +323,17 @@ var dev = defineCommand4({
|
|
|
197
323
|
`);
|
|
198
324
|
}
|
|
199
325
|
});
|
|
200
|
-
var main =
|
|
326
|
+
var main = defineCommand5({
|
|
201
327
|
meta: {
|
|
202
328
|
name: "apex",
|
|
203
329
|
description: "The full-stack meta-framework for Alpine.js"
|
|
204
330
|
},
|
|
205
|
-
subCommands: {
|
|
331
|
+
subCommands: {
|
|
332
|
+
dev,
|
|
333
|
+
build: buildCommand,
|
|
334
|
+
make: makeCommand,
|
|
335
|
+
migrate: migrateCommand,
|
|
336
|
+
mcp: mcpCommand
|
|
337
|
+
}
|
|
206
338
|
});
|
|
207
339
|
runMain(main);
|
package/dist/index.d.ts
CHANGED
|
@@ -121,6 +121,9 @@ interface RenderPageOptions {
|
|
|
121
121
|
componentCss?: string;
|
|
122
122
|
/** Post-process the shell HTML (dev: vite.transformIndexHtml). */
|
|
123
123
|
transformHtml?: (url: string, html: string) => string | Promise<string>;
|
|
124
|
+
/** In a production build, the href of the built client bundle for this page.
|
|
125
|
+
* When set, the shell references it instead of the inline dev module. */
|
|
126
|
+
clientHref?: string;
|
|
124
127
|
}
|
|
125
128
|
/**
|
|
126
129
|
* The framework's render seam — deliberately dev-server-agnostic so it can move
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apex-stack/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "The full-stack meta-framework for Alpine.js — CLI and runtime",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"h3": "^1.13.0",
|
|
41
41
|
"vite": "^6.0.7",
|
|
42
42
|
"zod": "^4.4.3",
|
|
43
|
-
"@apex-stack/
|
|
44
|
-
"@apex-stack/
|
|
43
|
+
"@apex-stack/kit": "0.1.1",
|
|
44
|
+
"@apex-stack/vite": "0.1.1"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
47
|
"alpinejs": "^3.14.0"
|