@apex-stack/core 0.1.17 → 0.1.19
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-KJF4LJWP.js → build-J47A3B4Y.js} +1 -1
- package/dist/{chunk-7GPCNGGO.js → chunk-XSN6NDWP.js} +39 -6
- package/dist/cli.js +4 -4
- package/dist/{dev-WS52CGSE.js → dev-OCVQRCCE.js} +1 -1
- package/dist/{make-62PPHZQY.js → make-JAW22LQZ.js} +26 -4
- package/dist/{server-5QQGUF3R.js → server-L3V34B5X.js} +5 -2
- package/dist/{start-XYVCDMPJ.js → start-AUJJ7HAY.js} +1 -1
- package/package.json +2 -2
|
@@ -89,14 +89,17 @@ function scanPages(root) {
|
|
|
89
89
|
const parts = rel.replace(/\.alpine$/, "").split("/");
|
|
90
90
|
if (parts[parts.length - 1] === "index") parts.pop();
|
|
91
91
|
const segments = parts.map((p) => {
|
|
92
|
+
const catchAll = /^\[\.\.\.(.+)\]$/.exec(p);
|
|
93
|
+
if (catchAll) return { catchAll: catchAll[1] };
|
|
92
94
|
const m = /^\[(.+)\]$/.exec(p);
|
|
93
95
|
return m ? { param: m[1] } : { literal: p };
|
|
94
96
|
});
|
|
95
|
-
const isDynamic = segments.some((s) => s.param !== void 0);
|
|
96
|
-
const pattern = `/${segments.map((s) => s.param ? `:${s.param}` : s.literal).join("/")}`;
|
|
97
|
+
const isDynamic = segments.some((s) => s.param !== void 0 || s.catchAll !== void 0);
|
|
98
|
+
const pattern = `/${segments.map((s) => s.catchAll ? `:${s.catchAll}*` : s.param ? `:${s.param}` : s.literal).join("/")}`;
|
|
97
99
|
return { pageId, pattern, segments, isDynamic };
|
|
98
100
|
});
|
|
99
|
-
|
|
101
|
+
const rank = (r) => r.segments.some((s) => s.catchAll) ? 2 : r.isDynamic ? 1 : 0;
|
|
102
|
+
return routes.sort((a, b) => rank(a) - rank(b));
|
|
100
103
|
}
|
|
101
104
|
function pathSegments(url) {
|
|
102
105
|
const path = url.split("?")[0] ?? "/";
|
|
@@ -105,6 +108,26 @@ function pathSegments(url) {
|
|
|
105
108
|
function matchRoute(routes, url) {
|
|
106
109
|
const segs = pathSegments(url);
|
|
107
110
|
for (const route of routes) {
|
|
111
|
+
const last = route.segments[route.segments.length - 1];
|
|
112
|
+
const isCatchAll = Boolean(last?.catchAll);
|
|
113
|
+
if (isCatchAll) {
|
|
114
|
+
const lead = route.segments.slice(0, -1);
|
|
115
|
+
if (segs.length < lead.length + 1) continue;
|
|
116
|
+
const params2 = {};
|
|
117
|
+
let ok2 = true;
|
|
118
|
+
for (let i = 0; i < lead.length; i++) {
|
|
119
|
+
const rs = lead[i];
|
|
120
|
+
const value = segs[i];
|
|
121
|
+
if (rs.param) params2[rs.param] = decodeURIComponent(value);
|
|
122
|
+
else if (rs.literal !== value) {
|
|
123
|
+
ok2 = false;
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (!ok2) continue;
|
|
128
|
+
params2[last?.catchAll] = segs.slice(lead.length).map(decodeURIComponent).join("/");
|
|
129
|
+
return { pageId: route.pageId, params: params2 };
|
|
130
|
+
}
|
|
108
131
|
if (route.segments.length !== segs.length) continue;
|
|
109
132
|
const params = {};
|
|
110
133
|
let ok = true;
|
|
@@ -153,7 +176,7 @@ function storesInitialState(stores) {
|
|
|
153
176
|
}
|
|
154
177
|
|
|
155
178
|
// src/dev/renderPage.ts
|
|
156
|
-
import { renderComponent, stateIsland } from "@apex-stack/kit";
|
|
179
|
+
import { renderComponent, renderFragment, stateIsland } from "@apex-stack/kit";
|
|
157
180
|
function escAttr(s) {
|
|
158
181
|
return String(s).replace(
|
|
159
182
|
/[&<>"]/g,
|
|
@@ -185,10 +208,20 @@ async function renderPage(opts) {
|
|
|
185
208
|
stores: storesInitialState(stores),
|
|
186
209
|
authoredDefaults: mod.rootData ? mod.rootData() : void 0
|
|
187
210
|
});
|
|
211
|
+
const available = opts.layouts ?? [];
|
|
212
|
+
const layoutName = mod.layout === false ? null : typeof mod.layout === "string" ? mod.layout : available.includes("default") ? "default" : null;
|
|
213
|
+
let body = html;
|
|
214
|
+
let layoutCss = "";
|
|
215
|
+
if (layoutName && available.includes(layoutName)) {
|
|
216
|
+
const layoutMod = await opts.loadModule(`/layouts/${layoutName}.alpine`);
|
|
217
|
+
const chrome = renderFragment(layoutMod.template, {}, layoutMod.scopeId, opts.registry);
|
|
218
|
+
body = /<slot\b[^>]*>[\s\S]*?<\/slot>/.test(chrome) ? chrome.replace(/<slot\b[^>]*>[\s\S]*?<\/slot>/, () => html) : chrome + html;
|
|
219
|
+
layoutCss = layoutMod.css;
|
|
220
|
+
}
|
|
188
221
|
const doc = shell({
|
|
189
|
-
body
|
|
222
|
+
body,
|
|
190
223
|
island: stateIsland(mod.componentId, loaderData),
|
|
191
|
-
css: mod.css + (opts.componentCss ?? ""),
|
|
224
|
+
css: mod.css + layoutCss + (opts.componentCss ?? ""),
|
|
192
225
|
pageId: opts.pageId,
|
|
193
226
|
clientHref: opts.clientHref,
|
|
194
227
|
storeIds: stores.map((s) => s.id),
|
package/dist/cli.js
CHANGED
|
@@ -109,10 +109,10 @@ var main = defineCommand2({
|
|
|
109
109
|
},
|
|
110
110
|
subCommands: {
|
|
111
111
|
new: newCommand,
|
|
112
|
-
dev: () => import("./dev-
|
|
113
|
-
build: () => import("./build-
|
|
114
|
-
start: () => import("./start-
|
|
115
|
-
make: () => import("./make-
|
|
112
|
+
dev: () => import("./dev-OCVQRCCE.js").then((m) => m.devCommand),
|
|
113
|
+
build: () => import("./build-J47A3B4Y.js").then((m) => m.buildCommand),
|
|
114
|
+
start: () => import("./start-AUJJ7HAY.js").then((m) => m.startCommand),
|
|
115
|
+
make: () => import("./make-JAW22LQZ.js").then((m) => m.makeCommand),
|
|
116
116
|
migrate: () => import("./migrate-NOGFOFV2.js").then((m) => m.migrateCommand),
|
|
117
117
|
mcp: () => import("./mcp-DL4J6JFJ.js").then((m) => m.mcpCommand)
|
|
118
118
|
},
|
|
@@ -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-L3V34B5X.js");
|
|
24
24
|
const { port: actual } = await startDevServer({ root, port, islands: Boolean(args.islands) });
|
|
25
25
|
sp.succeed("Dev server ready");
|
|
26
26
|
ready([
|
|
@@ -33,6 +33,26 @@ function componentTemplate() {
|
|
|
33
33
|
</style>
|
|
34
34
|
`;
|
|
35
35
|
}
|
|
36
|
+
function layoutTemplate() {
|
|
37
|
+
return `<template>
|
|
38
|
+
<header class="site-header">
|
|
39
|
+
<nav><a href="/">Home</a></nav>
|
|
40
|
+
</header>
|
|
41
|
+
<main>
|
|
42
|
+
<slot></slot>
|
|
43
|
+
</main>
|
|
44
|
+
<footer class="site-footer">
|
|
45
|
+
<p>Built with Apex JS</p>
|
|
46
|
+
</footer>
|
|
47
|
+
</template>
|
|
48
|
+
|
|
49
|
+
<style scoped>
|
|
50
|
+
.site-header { padding: 1rem 1.5rem; border-bottom: 1px solid #e5e7eb; }
|
|
51
|
+
main { max-width: 60rem; margin: 0 auto; padding: 2rem 1.5rem; }
|
|
52
|
+
.site-footer { padding: 1.5rem; border-top: 1px solid #e5e7eb; color: #6b7280; }
|
|
53
|
+
</style>
|
|
54
|
+
`;
|
|
55
|
+
}
|
|
36
56
|
function storeTemplate(name) {
|
|
37
57
|
return `import { defineStore } from '@apex-stack/core'
|
|
38
58
|
|
|
@@ -69,20 +89,22 @@ function plan(kind, name, root) {
|
|
|
69
89
|
return { path: join(root, "server", "api", `${name}.ts`), contents: apiTemplate(name) };
|
|
70
90
|
case "store":
|
|
71
91
|
return { path: join(root, "stores", `${name}.ts`), contents: storeTemplate(name) };
|
|
92
|
+
case "layout":
|
|
93
|
+
return { path: join(root, "layouts", `${name}.alpine`), contents: layoutTemplate() };
|
|
72
94
|
}
|
|
73
95
|
}
|
|
74
96
|
var makeCommand = defineCommand({
|
|
75
|
-
meta: { name: "make", description: "Generate a page, component, API route, or
|
|
97
|
+
meta: { name: "make", description: "Generate a page, component, API route, store, or layout" },
|
|
76
98
|
args: {
|
|
77
|
-
kind: { type: "positional", required: true, description: "page | component | api | store" },
|
|
99
|
+
kind: { type: "positional", required: true, description: "page | component | api | store | layout" },
|
|
78
100
|
name: { type: "positional", required: true, description: "Name (about, Counter, todos, \u2026)" },
|
|
79
101
|
root: { type: "string", description: "Project root", default: "." }
|
|
80
102
|
},
|
|
81
103
|
run({ args }) {
|
|
82
104
|
const kind = args.kind;
|
|
83
|
-
if (kind !== "page" && kind !== "component" && kind !== "api" && kind !== "store") {
|
|
105
|
+
if (kind !== "page" && kind !== "component" && kind !== "api" && kind !== "store" && kind !== "layout") {
|
|
84
106
|
console.error(`
|
|
85
|
-
Unknown type "${args.kind}". Use: page | component | api | store
|
|
107
|
+
Unknown type "${args.kind}". Use: page | component | api | store | layout
|
|
86
108
|
`);
|
|
87
109
|
process.exit(1);
|
|
88
110
|
}
|
|
@@ -13,11 +13,11 @@ import {
|
|
|
13
13
|
renderIslandsPage,
|
|
14
14
|
renderPage,
|
|
15
15
|
scanPages
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-XSN6NDWP.js";
|
|
17
17
|
import "./chunk-MZVLRU3R.js";
|
|
18
18
|
|
|
19
19
|
// src/dev/server.ts
|
|
20
|
-
import { existsSync as existsSync2 } from "fs";
|
|
20
|
+
import { existsSync as existsSync2, readdirSync } from "fs";
|
|
21
21
|
import { createServer as createHttpServer } from "http";
|
|
22
22
|
import { createRequire } from "module";
|
|
23
23
|
import { join } from "path";
|
|
@@ -213,6 +213,8 @@ async function startDevServer(options) {
|
|
|
213
213
|
(id) => ssrLoad(id)
|
|
214
214
|
);
|
|
215
215
|
const stores = await loadStores(options.root, (id) => ssrLoad(id));
|
|
216
|
+
const layoutsDir = join(options.root, "layouts");
|
|
217
|
+
const layouts = existsSync2(layoutsDir) ? readdirSync(layoutsDir).filter((f) => f.endsWith(".alpine")).map((f) => f.replace(/\.alpine$/, "")) : [];
|
|
216
218
|
const render = options.islands ? renderIslandsPage : renderPage;
|
|
217
219
|
const html = await render({
|
|
218
220
|
loadModule: (id) => ssrLoad(id),
|
|
@@ -223,6 +225,7 @@ async function startDevServer(options) {
|
|
|
223
225
|
componentCss,
|
|
224
226
|
stores,
|
|
225
227
|
appCss,
|
|
228
|
+
layouts,
|
|
226
229
|
transformHtml: (u, doc) => vite.transformIndexHtml(u, doc)
|
|
227
230
|
});
|
|
228
231
|
setResponseHeader(event, "Content-Type", "text/html");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apex-stack/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.19",
|
|
4
4
|
"description": "The full-stack meta-framework for Alpine.js — CLI and runtime",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"h3": "^1.13.0",
|
|
46
46
|
"vite": "^6.0.7",
|
|
47
47
|
"zod": "^4.4.3",
|
|
48
|
-
"@apex-stack/kit": "0.1.
|
|
48
|
+
"@apex-stack/kit": "0.1.5",
|
|
49
49
|
"@apex-stack/vite": "0.1.5"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|