@aerobuilt/core 0.2.9 → 0.3.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.
Files changed (39) hide show
  1. package/dist/build-script-analysis-Bd9EyItC.mjs +193 -0
  2. package/dist/{entry-dev.d.ts → entry-dev.d.mts} +6 -16
  3. package/dist/entry-dev.mjs +127 -0
  4. package/dist/{entry-editor.d.ts → entry-editor.d.mts} +24 -22
  5. package/dist/entry-editor.mjs +3 -0
  6. package/dist/entry-prod.d.mts +10 -0
  7. package/dist/entry-prod.mjs +15 -0
  8. package/dist/routing-Bai79LCq.mjs +198 -0
  9. package/dist/runtime/index.d.mts +65 -0
  10. package/dist/runtime/index.mjs +207 -0
  11. package/dist/runtime/instance.d.mts +19 -0
  12. package/dist/runtime/instance.mjs +45 -0
  13. package/dist/types-CLHGhnGA.d.mts +209 -0
  14. package/dist/types.d.mts +2 -0
  15. package/dist/types.mjs +1 -0
  16. package/dist/utils/aliases.d.mts +38 -0
  17. package/dist/utils/aliases.mjs +117 -0
  18. package/dist/utils/{redirects.d.ts → redirects.d.mts} +7 -12
  19. package/dist/utils/redirects.mjs +21 -0
  20. package/dist/vite/{index.d.ts → index.d.mts} +5 -12
  21. package/dist/vite/index.mjs +1890 -0
  22. package/package.json +25 -20
  23. package/dist/chunk-4DAK56WB.js +0 -36
  24. package/dist/chunk-5ZNUGZOW.js +0 -238
  25. package/dist/chunk-F7MXQXLM.js +0 -15
  26. package/dist/chunk-JAMYN2VX.js +0 -133
  27. package/dist/chunk-VTEG2UU3.js +0 -184
  28. package/dist/entry-dev.js +0 -101
  29. package/dist/entry-editor.js +0 -14
  30. package/dist/entry-prod.d.ts +0 -19
  31. package/dist/entry-prod.js +0 -19
  32. package/dist/runtime/index.d.ts +0 -74
  33. package/dist/runtime/index.js +0 -7
  34. package/dist/runtime/instance.d.ts +0 -31
  35. package/dist/runtime/instance.js +0 -10
  36. package/dist/types.d.ts +0 -202
  37. package/dist/types.js +0 -0
  38. package/dist/utils/redirects.js +0 -6
  39. package/dist/vite/index.js +0 -1991
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aerobuilt/core",
3
- "version": "0.2.9",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "author": "Jamie Wilson",
@@ -11,43 +11,48 @@
11
11
  },
12
12
  "homepage": "https://github.com/aerobuilt/aero",
13
13
  "private": false,
14
- "types": "./dist/entry-dev.d.ts",
14
+ "types": "./dist/entry-dev.d.mts",
15
15
  "files": [
16
16
  "dist"
17
17
  ],
18
18
  "exports": {
19
19
  ".": {
20
- "types": "./dist/entry-dev.d.ts",
21
- "default": "./dist/entry-dev.js"
20
+ "types": "./dist/entry-dev.d.mts",
21
+ "default": "./dist/entry-dev.mjs"
22
22
  },
23
23
  "./entry-prod": {
24
- "types": "./dist/entry-prod.d.ts",
25
- "default": "./dist/entry-prod.js"
24
+ "types": "./dist/entry-prod.d.mts",
25
+ "default": "./dist/entry-prod.mjs"
26
26
  },
27
27
  "./vite": {
28
- "types": "./dist/vite/index.d.ts",
29
- "default": "./dist/vite/index.js"
28
+ "types": "./dist/vite/index.d.mts",
29
+ "default": "./dist/vite/index.mjs"
30
30
  },
31
31
  "./runtime": {
32
- "types": "./dist/runtime/index.d.ts",
33
- "default": "./dist/runtime/index.js"
32
+ "types": "./dist/runtime/index.d.mts",
33
+ "default": "./dist/runtime/index.mjs"
34
34
  },
35
35
  "./runtime/instance": {
36
- "types": "./dist/runtime/instance.d.ts",
37
- "default": "./dist/runtime/instance.js"
36
+ "types": "./dist/runtime/instance.d.mts",
37
+ "default": "./dist/runtime/instance.mjs"
38
+ },
39
+ "./types": "./dist/types.d.mts",
40
+ "./utils/aliases": {
41
+ "types": "./dist/utils/aliases.d.mts",
42
+ "default": "./dist/utils/aliases.mjs"
38
43
  },
39
- "./types": "./dist/types.d.ts",
40
44
  "./utils/redirects": {
41
- "types": "./dist/utils/redirects.d.ts",
42
- "default": "./dist/utils/redirects.js"
45
+ "types": "./dist/utils/redirects.d.mts",
46
+ "default": "./dist/utils/redirects.mjs"
43
47
  },
44
48
  "./editor": {
45
- "types": "./dist/entry-editor.d.ts",
46
- "default": "./dist/entry-editor.js"
49
+ "types": "./dist/entry-editor.d.mts",
50
+ "default": "./dist/entry-editor.mjs"
47
51
  }
48
52
  },
49
53
  "dependencies": {
50
54
  "get-tsconfig": "^4.13.6",
55
+ "oxc-resolver": "^11.19.0",
51
56
  "html-minifier-next": "^5.1.1",
52
57
  "linkedom": "^0.18.12",
53
58
  "nitro": "^3.0.1-alpha.2",
@@ -55,7 +60,7 @@
55
60
  "sharp": "^0.34.5",
56
61
  "svgo": "^4.0.0",
57
62
  "vite-plugin-image-optimizer": "^2.0.3",
58
- "@aerobuilt/interpolation": "0.2.9"
63
+ "@aerobuilt/interpolation": "0.3.0"
59
64
  },
60
65
  "peerDependencies": {
61
66
  "vite": "^8.0.0-0"
@@ -67,12 +72,12 @@
67
72
  },
68
73
  "devDependencies": {
69
74
  "@types/node": "^25.3.0",
70
- "tsup": "^8.5.1",
75
+ "tsdown": "^0.21.0-beta.2",
71
76
  "typescript": "^5.9.3",
72
77
  "vitest": "^4.0.18"
73
78
  },
74
79
  "scripts": {
75
- "build": "tsup src/entry-dev.ts src/entry-prod.ts src/entry-editor.ts src/types.ts src/vite/index.ts src/utils/redirects.ts src/runtime/index.ts src/runtime/instance.ts --format esm --dts --clean --out-dir dist --external @content/site",
80
+ "build": "tsdown src/entry-dev.ts src/entry-prod.ts src/entry-editor.ts src/types.ts src/vite/index.ts src/utils/aliases.ts src/utils/redirects.ts src/runtime/index.ts src/runtime/instance.ts --format esm --dts --clean --out-dir dist --external @content/site",
76
81
  "typecheck": "tsc --noEmit",
77
82
  "test": "vitest run"
78
83
  }
@@ -1,36 +0,0 @@
1
- import {
2
- Aero
3
- } from "./chunk-5ZNUGZOW.js";
4
-
5
- // src/runtime/instance.ts
6
- var instance = globalThis.__AERO_INSTANCE__ || new Aero();
7
- var listeners = globalThis.__AERO_LISTENERS__ || /* @__PURE__ */ new Set();
8
- var aero = instance;
9
- var onUpdate = (cb) => {
10
- listeners.add(cb);
11
- return () => listeners.delete(cb);
12
- };
13
- var notify = () => {
14
- listeners.forEach((cb) => cb());
15
- };
16
- if (!globalThis.__AERO_INSTANCE__) {
17
- globalThis.__AERO_INSTANCE__ = instance;
18
- }
19
- if (!globalThis.__AERO_LISTENERS__) {
20
- globalThis.__AERO_LISTENERS__ = listeners;
21
- }
22
- var components = import.meta.glob("@components/**/*.html", { eager: true });
23
- var layouts = import.meta.glob("@layouts/*.html", { eager: true });
24
- var pages = import.meta.glob("@pages/**/*.html", { eager: true });
25
- aero.registerPages(components);
26
- aero.registerPages(layouts);
27
- aero.registerPages(pages);
28
- notify();
29
- if (import.meta.hot) {
30
- import.meta.hot.accept();
31
- }
32
-
33
- export {
34
- aero,
35
- onUpdate
36
- };
@@ -1,238 +0,0 @@
1
- import {
2
- pagePathToKey,
3
- resolvePageTarget
4
- } from "./chunk-JAMYN2VX.js";
5
-
6
- // src/runtime/index.ts
7
- var Aero = class {
8
- /** Global values merged into template context (e.g. from content modules). */
9
- globals = {};
10
- /** Map from page name (or path) to module. Keys include both canonical name and full path for lookup. */
11
- pagesMap = {};
12
- /** Set by client entry when running in the browser; used to attach the app to a DOM root. */
13
- mount;
14
- /**
15
- * Register a global value available in all templates as `name`.
16
- *
17
- * @param name - Key used in templates (e.g. `site`).
18
- * @param value - Any value (object, string, etc.).
19
- */
20
- global(name, value) {
21
- this.globals[name] = value;
22
- }
23
- /**
24
- * Register page/layout modules from a Vite glob (e.g. `import.meta.glob('@pages/**\/*.html')`).
25
- * Derives a lookup key from each path via pagePathToKey; also stores by full path for resolution.
26
- *
27
- * @param pages - Record of resolved path → module (default export is the render function).
28
- */
29
- registerPages(pages) {
30
- for (const [path, mod] of Object.entries(pages)) {
31
- const key = pagePathToKey(path);
32
- this.pagesMap[key] = mod;
33
- this.pagesMap[path] = mod;
34
- }
35
- }
36
- /** Type guard: true if value looks like an `AeroRenderInput` (has at least one of props, slots, request, url, params, routePath). */
37
- isRenderInput(value) {
38
- if (!value || typeof value !== "object") return false;
39
- return ["props", "slots", "request", "url", "params", "routePath"].some(
40
- (key) => key in value
41
- );
42
- }
43
- /** Coerce various call signatures into a single `AeroRenderInput` (e.g. plain object → `{ props }`). */
44
- normalizeRenderInput(input) {
45
- if (!input) return {};
46
- if (this.isRenderInput(input)) return input;
47
- if (typeof input === "object") return { props: input };
48
- return { props: {} };
49
- }
50
- /** Convert a page name to a route path (e.g. `index` → `'/'`, `about` → `'/about'`). */
51
- toRoutePath(pageName = "index") {
52
- if (!pageName || pageName === "index" || pageName === "home") return "/";
53
- if (pageName.endsWith("/index")) {
54
- return "/" + pageName.slice(0, -"/index".length);
55
- }
56
- return pageName.startsWith("/") ? pageName : "/" + pageName;
57
- }
58
- /** Build a URL from route path and optional raw URL. Uses `http://localhost` as base when only a path is given. */
59
- toURL(routePath, rawUrl) {
60
- if (rawUrl instanceof URL) return rawUrl;
61
- if (typeof rawUrl === "string" && rawUrl.length > 0) {
62
- return new URL(rawUrl, "http://localhost");
63
- }
64
- return new URL(routePath, "http://localhost");
65
- }
66
- /** Build template context: globals, props, slots, request, url, params, site, and `renderComponent` / `nextPassDataId`. */
67
- createContext(input) {
68
- const routePath = input.routePath || "/";
69
- const url = this.toURL(routePath, input.url);
70
- const request = input.request || new Request(url.toString(), { method: "GET" });
71
- let _passDataId = 0;
72
- const context = {
73
- ...this.globals,
74
- props: input.props || {},
75
- slots: input.slots || {},
76
- request,
77
- url,
78
- params: input.params || {},
79
- site: input.site ?? "",
80
- styles: input.styles,
81
- scripts: input.scripts,
82
- headScripts: input.headScripts,
83
- nextPassDataId: () => `__aero_${_passDataId++}`,
84
- renderComponent: this.renderComponent.bind(this)
85
- };
86
- return context;
87
- }
88
- /** True if entry params and request params have the same keys and stringified values. */
89
- paramsMatch(entryParams, requestParams) {
90
- const entryKeys = Object.keys(entryParams);
91
- if (entryKeys.length !== Object.keys(requestParams).length) return false;
92
- for (const key of entryKeys) {
93
- if (String(entryParams[key]) !== String(requestParams[key])) return false;
94
- }
95
- return true;
96
- }
97
- /**
98
- * Render a page or layout to HTML.
99
- *
100
- * @remarks
101
- * Resolves `component` (page name string or module) via `pagesMap`, with fallbacks: directory index
102
- * (`foo` → `foo/index`), `index` → `home`, dynamic routes, and trailing-slash stripping. If the module
103
- * exports `getStaticPaths` and no props are provided, finds the matching static path and uses its props.
104
- * For root-level renders, injects accumulated styles and scripts into the document and fixes content
105
- * that ends up after `</html>` when using layouts (moves it into `</body>`).
106
- *
107
- * @param component - Page name (e.g. `'index'`, `'about'`) or the module object.
108
- * @param input - Render input (props, request, url, params, etc.). Can be a plain object (treated as props).
109
- * @returns HTML string, or `null` if the page is not found or no static path match.
110
- */
111
- async render(component, input = {}) {
112
- const renderInput = this.normalizeRenderInput(input);
113
- const isRootRender = !renderInput.styles;
114
- if (isRootRender) {
115
- renderInput.styles = /* @__PURE__ */ new Set();
116
- renderInput.scripts = /* @__PURE__ */ new Set();
117
- renderInput.headScripts = /* @__PURE__ */ new Set();
118
- }
119
- const resolved = resolvePageTarget(component, this.pagesMap);
120
- if (!resolved) return null;
121
- let target = resolved.module;
122
- const matchedPageName = resolved.pageName;
123
- const dynamicParams = resolved.params;
124
- if (typeof target === "function" && target.length === 0) {
125
- target = await target();
126
- }
127
- if (typeof target.getStaticPaths === "function" && Object.keys(renderInput.props || {}).length === 0) {
128
- const staticPaths = await target.getStaticPaths();
129
- const combinedParams = { ...dynamicParams, ...renderInput.params || {} };
130
- const match = staticPaths.find((entry) => this.paramsMatch(entry.params, combinedParams));
131
- if (!match) {
132
- console.warn(
133
- `[aero] 404: Route params ${JSON.stringify(combinedParams)} not found in getStaticPaths for ${matchedPageName}`
134
- );
135
- return null;
136
- }
137
- if (match.props) {
138
- renderInput.props = match.props;
139
- }
140
- }
141
- const routePath = renderInput.routePath || this.toRoutePath(matchedPageName);
142
- const context = this.createContext({
143
- props: renderInput.props || {},
144
- slots: renderInput.slots || {},
145
- request: renderInput.request,
146
- url: renderInput.url,
147
- params: { ...dynamicParams, ...renderInput.params || {} },
148
- routePath,
149
- site: renderInput.site,
150
- styles: renderInput.styles,
151
- scripts: renderInput.scripts,
152
- headScripts: renderInput.headScripts
153
- });
154
- let renderFn = target;
155
- if (target.default) renderFn = target.default;
156
- if (typeof renderFn === "function") {
157
- let html = await renderFn(context);
158
- if (isRootRender) {
159
- if (html.includes("</html>")) {
160
- const afterHtml = html.split("</html>")[1]?.trim();
161
- if (afterHtml && html.includes("</body>")) {
162
- html = html.split("</html>")[0] + "</html>";
163
- html = html.replace("</body>", `
164
- ${afterHtml}
165
- </body>`);
166
- }
167
- }
168
- let headInjections = "";
169
- if (context.styles && context.styles.size > 0) {
170
- headInjections += Array.from(context.styles).join("\n") + "\n";
171
- }
172
- if (context.headScripts && context.headScripts.size > 0) {
173
- headInjections += Array.from(context.headScripts).join("\n") + "\n";
174
- }
175
- if (headInjections) {
176
- if (html.includes("</head>")) {
177
- html = html.replace("</head>", `
178
- ${headInjections}</head>`);
179
- } else if (html.includes("<body")) {
180
- html = html.replace(/(<body[^>]*>)/i, `<head>
181
- ${headInjections}</head>
182
- $1`);
183
- } else {
184
- html = `${headInjections}${html}`;
185
- }
186
- }
187
- if (context.scripts && context.scripts.size > 0) {
188
- const scriptsHtml = Array.from(context.scripts).join("\n");
189
- if (html.includes("</body>")) {
190
- html = html.replace("</body>", `
191
- ${scriptsHtml}
192
- </body>`);
193
- } else {
194
- html = `${html}
195
- ${scriptsHtml}`;
196
- }
197
- }
198
- }
199
- return html;
200
- }
201
- return "";
202
- }
203
- /**
204
- * Render a child component (layout or component) with the given props and slots.
205
- * Used by compiled templates via context.renderComponent.
206
- *
207
- * @param component - Render function or module with `default` render function.
208
- * @param props - Props object for the component.
209
- * @param slots - Named slot content (key → HTML string).
210
- * @param input - Optional request/url/params for context; `headScripts` is not passed through.
211
- * @returns HTML string from the component's render function, or empty string if not invokable.
212
- */
213
- async renderComponent(component, props = {}, slots = {}, input = {}) {
214
- const context = this.createContext({
215
- props,
216
- slots,
217
- request: input.request,
218
- url: input.url,
219
- params: input.params,
220
- routePath: input.routePath || "/",
221
- site: input.site,
222
- styles: input.styles,
223
- scripts: input.scripts,
224
- headScripts: input.headScripts
225
- });
226
- if (typeof component === "function") {
227
- return await component(context);
228
- }
229
- if (component && typeof component.default === "function") {
230
- return await component.default(context);
231
- }
232
- return "";
233
- }
234
- };
235
-
236
- export {
237
- Aero
238
- };
@@ -1,15 +0,0 @@
1
- // src/utils/redirects.ts
2
- function redirectsToRouteRules(redirects) {
3
- const out = {};
4
- for (const rule of redirects) {
5
- const status = rule.status ?? 302;
6
- out[rule.from] = {
7
- redirect: status === 307 ? rule.to : { to: rule.to, statusCode: status }
8
- };
9
- }
10
- return out;
11
- }
12
-
13
- export {
14
- redirectsToRouteRules
15
- };
@@ -1,133 +0,0 @@
1
- // src/utils/path.ts
2
- function toPosix(value) {
3
- return value.replace(/\\/g, "/");
4
- }
5
- function toPosixRelative(value, root) {
6
- const valuePosix = toPosix(value);
7
- const rootPosix = toPosix(root);
8
- if (valuePosix.startsWith(rootPosix + "/")) {
9
- return valuePosix.slice(rootPosix.length + 1);
10
- }
11
- return valuePosix;
12
- }
13
-
14
- // src/utils/route-pattern.ts
15
- var PARAM_SEGMENT_REGEX = /^\[([^.\]\[]+)\]$/;
16
- function parseRoutePattern(pattern) {
17
- const rawSegments = pattern.split("/").filter(Boolean);
18
- const segments = rawSegments.map((seg) => {
19
- const paramMatch = seg.match(PARAM_SEGMENT_REGEX);
20
- if (paramMatch) {
21
- return { type: "param", name: paramMatch[1] };
22
- }
23
- return { type: "static", value: seg };
24
- });
25
- return { segments };
26
- }
27
- function isDynamicRoutePattern(pattern) {
28
- const { segments } = parseRoutePattern(pattern);
29
- return segments.some((s) => s.type === "param");
30
- }
31
- function matchRoutePattern(pattern, pageName) {
32
- const { segments } = parseRoutePattern(pattern);
33
- const requestedSegments = pageName.split("/").filter(Boolean);
34
- if (segments.length !== requestedSegments.length) return null;
35
- const params = {};
36
- for (let i = 0; i < segments.length; i++) {
37
- const seg = segments[i];
38
- const requestSeg = requestedSegments[i];
39
- if (seg.type === "param") {
40
- params[seg.name] = decodeURIComponent(requestSeg);
41
- } else if (seg.value !== requestSeg) {
42
- return null;
43
- }
44
- }
45
- return params;
46
- }
47
- function expandRoutePattern(pattern, params) {
48
- const { segments } = parseRoutePattern(pattern);
49
- const parts = [];
50
- for (const seg of segments) {
51
- if (seg.type === "param") {
52
- if (!(seg.name in params)) {
53
- throw new Error(
54
- `[aero] getStaticPaths: missing param "${seg.name}" for pattern "${pattern}". Provided params: ${JSON.stringify(params)}`
55
- );
56
- }
57
- parts.push(params[seg.name]);
58
- } else {
59
- parts.push(seg.value);
60
- }
61
- }
62
- return parts.join("/");
63
- }
64
-
65
- // src/utils/routing.ts
66
- function pagePathToKey(path) {
67
- const withoutExt = toPosix(path).replace(/\.html$/i, "");
68
- if (withoutExt.includes("pages/")) {
69
- return withoutExt.split("pages/").pop();
70
- }
71
- const segments = withoutExt.split("/").filter(Boolean);
72
- if (segments.length > 1) {
73
- return segments.join("/");
74
- }
75
- return segments.pop() || path;
76
- }
77
- function resolvePageName(url) {
78
- const [pathPart] = url.split("?");
79
- let clean = pathPart || "/";
80
- if (clean === "/" || clean === "") return "index";
81
- if (clean.endsWith("/")) {
82
- clean = clean + "index";
83
- }
84
- clean = clean.replace(/^\//, "");
85
- clean = clean.replace(/\.html$/, "");
86
- return clean || "index";
87
- }
88
- function resolveDynamicPage(pageName, pagesMap) {
89
- for (const [key, mod] of Object.entries(pagesMap)) {
90
- if (!key.includes("[") || !key.includes("]") || key.includes(".")) continue;
91
- const params = matchRoutePattern(key, pageName);
92
- if (params != null) {
93
- return { module: mod, pageName: key, params };
94
- }
95
- }
96
- return null;
97
- }
98
- function resolvePageTarget(component, pagesMap) {
99
- if (typeof component !== "string") {
100
- return component != null ? { module: component, pageName: "index", params: {} } : null;
101
- }
102
- const pageName = component;
103
- let target = pagesMap[pageName];
104
- if (!target) {
105
- target = pagesMap[`${pageName}/index`];
106
- }
107
- if (!target && pageName === "index") {
108
- target = pagesMap["home"];
109
- }
110
- if (!target) {
111
- const dynamicMatch = resolveDynamicPage(pageName, pagesMap) ?? resolveDynamicPage(`${pageName}/index`, pagesMap);
112
- if (dynamicMatch) return dynamicMatch;
113
- }
114
- if (!target && pageName.endsWith("/index")) {
115
- const stripped = pageName.slice(0, -"/index".length);
116
- target = pagesMap[stripped];
117
- if (target) return { module: target, pageName: stripped, params: {} };
118
- const dynamicMatch = resolveDynamicPage(stripped, pagesMap);
119
- if (dynamicMatch) return dynamicMatch;
120
- }
121
- if (!target) return null;
122
- return { module: target, pageName, params: {} };
123
- }
124
-
125
- export {
126
- toPosix,
127
- toPosixRelative,
128
- isDynamicRoutePattern,
129
- expandRoutePattern,
130
- pagePathToKey,
131
- resolvePageName,
132
- resolvePageTarget
133
- };