@aerobuilt/core 0.3.2 → 0.3.3

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.
@@ -34,6 +34,8 @@ function isDirectiveAttr(attrName, config = defaultConfig) {
34
34
  * @remarks
35
35
  * Attribute names are used with optional `data-` prefix (e.g. `data-each`). Script taxonomy uses
36
36
  * `is:build`, `is:inline`, `is:blocking`; default scripts are treated as client (virtual module).
37
+ * When changing script taxonomy (is:build, is:inline, etc.), update all consumers per
38
+ * _reference/script-taxonomy-sync.md.
37
39
  */
38
40
  /** Prefix for data attributes (e.g. `data-each` → ATTR_PREFIX + ATTR_EACH). */
39
41
  const ATTR_PREFIX = "data-";
@@ -187,6 +189,92 @@ function analyzeBuildScript(script) {
187
189
  };
188
190
  }
189
191
  /**
192
+ * Extract the props type name from a build script that uses `Aero.props as TypeName`
193
+ * or `const { ... } = Aero.props as TypeName`.
194
+ *
195
+ * @param script - Raw build script content (JS or TS).
196
+ * @returns The type name and whether it was from destructuring, or null if not found.
197
+ */
198
+ function getPropsTypeFromBuildScript(script) {
199
+ if (!script.trim()) return null;
200
+ const result = parseSync(BUILD_SCRIPT_FILENAME, script, {
201
+ sourceType: "module",
202
+ range: true,
203
+ lang: "ts"
204
+ });
205
+ if (result.errors.length > 0) return null;
206
+ const body = result.program.body;
207
+ if (!body) return null;
208
+ for (const stmt of body) {
209
+ const found = findPropsTypeInNode(stmt);
210
+ if (found) return found;
211
+ }
212
+ return null;
213
+ }
214
+ function findPropsTypeInNode(node) {
215
+ if (!node || typeof node !== "object") return null;
216
+ const n = node;
217
+ if (n.type === "TSAsExpression") {
218
+ const expr = n.expression;
219
+ const typeAnnotation = n.typeAnnotation;
220
+ if (isAeroProps(expr)) {
221
+ const typeName = getTypeNameFromAnnotation(typeAnnotation);
222
+ if (typeName) return {
223
+ typeName,
224
+ isFromDestructuring: false
225
+ };
226
+ }
227
+ return null;
228
+ }
229
+ if (n.type === "VariableDeclaration") {
230
+ const declarations = n.declarations;
231
+ for (const decl of declarations ?? []) {
232
+ const d = decl;
233
+ const init = d.init;
234
+ const id = d.id;
235
+ const isDestructuring = id && typeof id === "object" && id.type === "ObjectPattern";
236
+ const found = findPropsTypeInNode(init);
237
+ if (found) return {
238
+ ...found,
239
+ isFromDestructuring: !!isDestructuring
240
+ };
241
+ }
242
+ return null;
243
+ }
244
+ for (const key of [
245
+ "init",
246
+ "expression",
247
+ "argument",
248
+ "body",
249
+ "consequent",
250
+ "alternate"
251
+ ]) {
252
+ const child = n[key];
253
+ if (Array.isArray(child)) for (const c of child) {
254
+ const found = findPropsTypeInNode(c);
255
+ if (found) return found;
256
+ }
257
+ else if (child) {
258
+ const found = findPropsTypeInNode(child);
259
+ if (found) return found;
260
+ }
261
+ }
262
+ return null;
263
+ }
264
+ function isAeroProps(expr) {
265
+ if (expr?.type !== "MemberExpression") return false;
266
+ const obj = expr.object;
267
+ const prop = expr.property;
268
+ const objName = obj?.type === "Identifier" ? obj.name : obj?.name;
269
+ const propName = prop?.type === "Identifier" ? prop.name : prop?.name;
270
+ return objName === "Aero" && propName === "props";
271
+ }
272
+ function getTypeNameFromAnnotation(annotation) {
273
+ if (!annotation) return null;
274
+ if (annotation.type === "TSTypeReference") return annotation.typeName?.name;
275
+ return null;
276
+ }
277
+ /**
190
278
  * Analyze build script for editor use: same as analyzeBuildScript but returns imports with
191
279
  * source ranges (full statement and per-binding) so the extension can map to vscode.Range.
192
280
  *
@@ -249,4 +337,4 @@ function analyzeBuildScriptForEditor(script) {
249
337
  }
250
338
 
251
339
  //#endregion
252
- export { DEFAULT_DIRECTIVE_PREFIXES as C, tokenizeCurlyInterpolation as E, VOID_TAGS as S, compileInterpolationFromSegments as T, EACH_REGEX as _, ATTR_ELSE_IF as a, SLOT_NAME_DEFAULT as b, ATTR_IS_BUILD as c, ATTR_PASS_DATA as d, ATTR_PREFIX as f, COMPONENT_SUFFIX_REGEX as g, ATTR_SRC as h, ATTR_ELSE as i, ATTR_IS_INLINE as l, ATTR_SLOT as m, analyzeBuildScriptForEditor as n, ATTR_IF as o, ATTR_PROPS as p, ATTR_EACH as r, ATTR_IS_BLOCKING as s, analyzeBuildScript as t, ATTR_NAME as u, SELF_CLOSING_TAG_REGEX as v, isDirectiveAttr as w, TAG_SLOT as x, SELF_CLOSING_TAIL_REGEX as y };
340
+ export { VOID_TAGS as C, tokenizeCurlyInterpolation as D, compileInterpolationFromSegments as E, TAG_SLOT as S, isDirectiveAttr as T, COMPONENT_SUFFIX_REGEX as _, ATTR_ELSE as a, SELF_CLOSING_TAIL_REGEX as b, ATTR_IS_BLOCKING as c, ATTR_NAME as d, ATTR_PASS_DATA as f, ATTR_SRC as g, ATTR_SLOT as h, ATTR_EACH as i, ATTR_IS_BUILD as l, ATTR_PROPS as m, analyzeBuildScriptForEditor as n, ATTR_ELSE_IF as o, ATTR_PREFIX as p, getPropsTypeFromBuildScript as r, ATTR_IF as s, analyzeBuildScript as t, ATTR_IS_INLINE as u, EACH_REGEX as v, DEFAULT_DIRECTIVE_PREFIXES as w, SLOT_NAME_DEFAULT as x, SELF_CLOSING_TAG_REGEX as y };
@@ -65,6 +65,19 @@ interface BuildScriptImportForEditor extends BuildScriptImport {
65
65
  interface BuildScriptAnalysisForEditorResult {
66
66
  imports: BuildScriptImportForEditor[];
67
67
  }
68
+ /** Result of getPropsTypeFromBuildScript: the type name used in `Aero.props as TypeName`. */
69
+ interface PropsTypeResult {
70
+ typeName: string;
71
+ isFromDestructuring: boolean;
72
+ }
73
+ /**
74
+ * Extract the props type name from a build script that uses `Aero.props as TypeName`
75
+ * or `const { ... } = Aero.props as TypeName`.
76
+ *
77
+ * @param script - Raw build script content (JS or TS).
78
+ * @returns The type name and whether it was from destructuring, or null if not found.
79
+ */
80
+ declare function getPropsTypeFromBuildScript(script: string): PropsTypeResult | null;
68
81
  /**
69
82
  * Analyze build script for editor use: same as analyzeBuildScript but returns imports with
70
83
  * source ranges (full statement and per-binding) so the extension can map to vscode.Range.
@@ -74,4 +87,4 @@ interface BuildScriptAnalysisForEditorResult {
74
87
  */
75
88
  declare function analyzeBuildScriptForEditor(script: string): BuildScriptAnalysisForEditorResult;
76
89
  //#endregion
77
- export { type BuildScriptAnalysisForEditorResult, type BuildScriptImportForEditor, COMPONENT_SUFFIX_REGEX, DEFAULT_DIRECTIVE_PREFIXES, type DirectiveAttrConfig, type InterpolationSegment, type LiteralSegment, type Segment, type TokenizeOptions, analyzeBuildScriptForEditor, compileInterpolationFromSegments, isDirectiveAttr, tokenizeCurlyInterpolation };
90
+ export { type BuildScriptAnalysisForEditorResult, type BuildScriptImportForEditor, COMPONENT_SUFFIX_REGEX, DEFAULT_DIRECTIVE_PREFIXES, type DirectiveAttrConfig, type InterpolationSegment, type LiteralSegment, type PropsTypeResult, type Segment, type TokenizeOptions, analyzeBuildScriptForEditor, compileInterpolationFromSegments, getPropsTypeFromBuildScript, isDirectiveAttr, tokenizeCurlyInterpolation };
@@ -1,3 +1,3 @@
1
- import { C as DEFAULT_DIRECTIVE_PREFIXES, E as tokenizeCurlyInterpolation, T as compileInterpolationFromSegments, g as COMPONENT_SUFFIX_REGEX, n as analyzeBuildScriptForEditor, w as isDirectiveAttr } from "./build-script-analysis-Bll0Ujh4.mjs";
1
+ import { D as tokenizeCurlyInterpolation, E as compileInterpolationFromSegments, T as isDirectiveAttr, _ as COMPONENT_SUFFIX_REGEX, n as analyzeBuildScriptForEditor, r as getPropsTypeFromBuildScript, w as DEFAULT_DIRECTIVE_PREFIXES } from "./build-script-analysis-1t1wROdQ.mjs";
2
2
 
3
- export { COMPONENT_SUFFIX_REGEX, DEFAULT_DIRECTIVE_PREFIXES, analyzeBuildScriptForEditor, compileInterpolationFromSegments, isDirectiveAttr, tokenizeCurlyInterpolation };
3
+ export { COMPONENT_SUFFIX_REGEX, DEFAULT_DIRECTIVE_PREFIXES, analyzeBuildScriptForEditor, compileInterpolationFromSegments, getPropsTypeFromBuildScript, isDirectiveAttr, tokenizeCurlyInterpolation };
@@ -1,5 +1,5 @@
1
1
  import { a as isDynamicRoutePattern, i as expandRoutePattern, n as resolvePageName, o as toPosix, s as toPosixRelative, t as pagePathToKey } from "../routing-Bai79LCq.mjs";
2
- import { E as tokenizeCurlyInterpolation, S as VOID_TAGS, T as compileInterpolationFromSegments, _ as EACH_REGEX, a as ATTR_ELSE_IF, b as SLOT_NAME_DEFAULT, c as ATTR_IS_BUILD, d as ATTR_PASS_DATA, f as ATTR_PREFIX, g as COMPONENT_SUFFIX_REGEX, h as ATTR_SRC, i as ATTR_ELSE, l as ATTR_IS_INLINE, m as ATTR_SLOT, o as ATTR_IF, p as ATTR_PROPS, r as ATTR_EACH, s as ATTR_IS_BLOCKING, t as analyzeBuildScript, u as ATTR_NAME, v as SELF_CLOSING_TAG_REGEX, w as isDirectiveAttr, x as TAG_SLOT, y as SELF_CLOSING_TAIL_REGEX } from "../build-script-analysis-Bll0Ujh4.mjs";
2
+ import { C as VOID_TAGS, D as tokenizeCurlyInterpolation, E as compileInterpolationFromSegments, S as TAG_SLOT, T as isDirectiveAttr, _ as COMPONENT_SUFFIX_REGEX, a as ATTR_ELSE, b as SELF_CLOSING_TAIL_REGEX, c as ATTR_IS_BLOCKING, d as ATTR_NAME, f as ATTR_PASS_DATA, g as ATTR_SRC, h as ATTR_SLOT, i as ATTR_EACH, l as ATTR_IS_BUILD, m as ATTR_PROPS, o as ATTR_ELSE_IF, p as ATTR_PREFIX, s as ATTR_IF, t as analyzeBuildScript, u as ATTR_IS_INLINE, v as EACH_REGEX, x as SLOT_NAME_DEFAULT, y as SELF_CLOSING_TAG_REGEX } from "../build-script-analysis-1t1wROdQ.mjs";
3
3
  import { loadTsconfigAliases, mergeWithDefaultAliases } from "../utils/aliases.mjs";
4
4
  import { redirectsToRouteRules } from "../utils/redirects.mjs";
5
5
  import { createRequire } from "node:module";
@@ -7,6 +7,7 @@ import { ViteImageOptimizer } from "vite-plugin-image-optimizer";
7
7
  import { nitro } from "nitro/vite";
8
8
  import { parseHTML } from "linkedom";
9
9
  import path from "path";
10
+ import { transformSync } from "oxc-transform";
10
11
  import path$1 from "node:path";
11
12
  import { minify } from "html-minifier-next";
12
13
  import fs, { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
@@ -64,17 +65,18 @@ function extractKeyFromEntry(entry) {
64
65
  /** Virtual URL prefix for extracted client scripts (e.g. `/@aero/client/client/pages/home.js`). Root-relative; no filesystem path. */
65
66
  const CLIENT_SCRIPT_PREFIX = "/@aero/client/";
66
67
  /**
67
- * Virtual URL for one client script. Single script uses `.js`, multiple use `.0.js`, `.1.js`, etc.
68
+ * Virtual URL for one client script.
69
+ * Single script uses `.ts`, multiple use `.0.ts`, `.1.ts`, etc.
68
70
  * Use this in the Vite transform and static build so URL generation is consistent.
69
71
  */
70
72
  function getClientScriptVirtualUrl(baseName, index, total) {
71
- const suffix = total === 1 ? ".js" : `.${index}.js`;
73
+ const suffix = total === 1 ? ".ts" : `.${index}.ts`;
72
74
  return CLIENT_SCRIPT_PREFIX + baseName + suffix;
73
75
  }
74
76
  /** Virtual module ID requested by the app; resolved to `RESOLVED_*` so `load()` can re-export from the real runtime instance. */
75
- const RUNTIME_INSTANCE_MODULE_ID = "virtual:aero/runtime-instance";
77
+ const RUNTIME_INSTANCE_MODULE_ID = "virtual:aero/runtime-instance.ts";
76
78
  /** Resolved ID (with `\0` prefix) so Vite treats it as an internal module. */
77
- const RESOLVED_RUNTIME_INSTANCE_MODULE_ID = "\0virtual:aero/runtime-instance";
79
+ const RESOLVED_RUNTIME_INSTANCE_MODULE_ID = "\0virtual:aero/runtime-instance.ts";
78
80
  /** Prefix for virtual empty-CSS modules used when Vite requests .html?html-proxy&inline-css (Aero .html are JS, not HTML with styles). */
79
81
  const AERO_EMPTY_INLINE_CSS_PREFIX = "\0aero:empty-inline-css:";
80
82
  /** Prefix for virtual HTML template modules. Resolving .html to this id returns compiled JS so vite:build-html never sees raw/compiled HTML. */
@@ -568,6 +570,11 @@ var Resolver = class {
568
570
 
569
571
  //#endregion
570
572
  //#region src/compiler/codegen.ts
573
+ /** Strip TypeScript syntax from a script string, returning plain JavaScript. */
574
+ function stripTypes(code, filename = "script.ts") {
575
+ if (!code.trim()) return code;
576
+ return transformSync(filename, code, { typescript: { onlyRemoveTypeImports: true } }).code.replace(/(?:^|\n)\s*export\s*\{\s*\}\s*;?/g, "");
577
+ }
571
578
  /** Internal lowerer: walks DOM nodes and builds IR; used by compile(). */
572
579
  var Lowerer = class {
573
580
  resolver;
@@ -953,7 +960,7 @@ function compile(parsed, options) {
953
960
  const lowerer = new Lowerer(resolver);
954
961
  let script = parsed.buildScript ? parsed.buildScript.content : "";
955
962
  const analysis = analyzeBuildScript(script);
956
- script = analysis.scriptWithoutImportsAndGetStaticPaths;
963
+ script = stripTypes(analysis.scriptWithoutImportsAndGetStaticPaths);
957
964
  const getStaticPathsFn = analysis.getStaticPathsFn;
958
965
  const importsLines = [];
959
966
  const quote = "\"";
@@ -1008,15 +1015,18 @@ function compile(parsed, options) {
1008
1015
  } else if (isHead) headScripts.push(tagExpr);
1009
1016
  else rootScripts.push(`scripts?.add(${tagExpr});`);
1010
1017
  }
1011
- if (options.blockingScripts) for (const blockingScript of options.blockingScripts) if (blockingScript.passDataExpr) {
1012
- const jsMapExpr = `Object.entries(${validateSingleBracedExpression(blockingScript.passDataExpr, {
1013
- directive: "pass:data",
1014
- tagName: "script"
1015
- })}).map(([k, v]) => "\\nconst " + k + " = " + JSON.stringify(v) + ";").join("")`;
1016
- headScripts.push(`\`<script${blockingScript.attrs ? " " + blockingScript.attrs : ""}>\${${jsMapExpr}}${blockingScript.content.replace(/`/g, "\\`")}<\/script>\``);
1017
- } else {
1018
- const escapedContent = blockingScript.content.replace(/'/g, "\\'");
1019
- headScripts.push(`'<script${blockingScript.attrs ? " " + blockingScript.attrs : ""}>${escapedContent}<\/script>'`);
1018
+ if (options.blockingScripts) for (const blockingScript of options.blockingScripts) {
1019
+ const strippedContent = stripTypes(blockingScript.content, "blocking.ts");
1020
+ if (blockingScript.passDataExpr) {
1021
+ const jsMapExpr = `Object.entries(${validateSingleBracedExpression(blockingScript.passDataExpr, {
1022
+ directive: "pass:data",
1023
+ tagName: "script"
1024
+ })}).map(([k, v]) => "\\nconst " + k + " = " + JSON.stringify(v) + ";").join("")`;
1025
+ headScripts.push(`\`<script${blockingScript.attrs ? " " + blockingScript.attrs : ""}>\${${jsMapExpr}}${strippedContent.replace(/`/g, "\\`")}<\/script>\``);
1026
+ } else {
1027
+ const escapedContent = strippedContent.replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
1028
+ headScripts.push(`\`<script${blockingScript.attrs ? " " + blockingScript.attrs : ""}>${escapedContent}<\/script>\``);
1029
+ }
1020
1030
  }
1021
1031
  const renderFn = emitRenderFunction(script, bodyCode, {
1022
1032
  getStaticPathsFn: getStaticPathsFn || void 0,
@@ -1556,7 +1566,7 @@ function clientGlobPrefix(clientDir) {
1556
1566
  * Ensures template resolution works for custom dirs (e.g. dirs.client === 'frontend').
1557
1567
  * runtimeImportPath: path that resolves to @aerobuilt/core/runtime from the generated file (e.g. relative to .aero/ for SSR).
1558
1568
  */
1559
- function getRuntimeInstanceVirtualSource(clientDir, runtimeImportPath = "@aerobuilt/core/runtime") {
1569
+ function getRuntimeInstanceVirtualSource(clientDir, runtimeImportPath = "aerobuilt/runtime") {
1560
1570
  const prefix = clientGlobPrefix(clientDir);
1561
1571
  const componentsPattern = `${prefix}/components/**/*.html`;
1562
1572
  const layoutsPattern = `${prefix}/layouts/*.html`;
@@ -1602,7 +1612,10 @@ function createAeroVirtualsPlugin(state) {
1602
1612
  discoverClientScriptContentMap(state.config.root, state.dirs.client).forEach((entry, url) => state.clientScripts.set(url, entry));
1603
1613
  },
1604
1614
  async resolveId(id, importer) {
1605
- if (id === RUNTIME_INSTANCE_MODULE_ID) return state.generatedRuntimeInstancePath ?? RESOLVED_RUNTIME_INSTANCE_MODULE_ID;
1615
+ if (id === RUNTIME_INSTANCE_MODULE_ID) {
1616
+ if (state.config?.command === "build" && state.generatedRuntimeInstancePath) return state.generatedRuntimeInstancePath;
1617
+ return RESOLVED_RUNTIME_INSTANCE_MODULE_ID;
1618
+ }
1606
1619
  if (id.startsWith(CLIENT_SCRIPT_PREFIX)) return "\0" + id;
1607
1620
  if (id.startsWith("\0" + CLIENT_SCRIPT_PREFIX)) return id;
1608
1621
  if (id.startsWith(AERO_HTML_VIRTUAL_PREFIX)) return id;
package/env.d.ts ADDED
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Ambient type declarations for Aero templates.
3
+ *
4
+ * Include in your project by adding `"types": ["@aerobuilt/core/env"]` to tsconfig.json,
5
+ * or via a triple-slash directive: `/// <reference types="@aerobuilt/core/env" />`
6
+ *
7
+ * These declarations type the globals available inside `<script is:build>` blocks.
8
+ *
9
+ * Single source of truth: the language server generates its preamble from this file.
10
+ * When changing globals (Aero, renderComponent, *.html, aero:content), run:
11
+ * pnpm --dir packages/language-server exec npm run prebuild
12
+ */
13
+
14
+ /**
15
+ * The `Aero` context object available in build scripts. Provides access to
16
+ * component props, request data, and rendering utilities.
17
+ *
18
+ * Use `Aero.props` (capital A). The lowercase `aero` is not defined at runtime.
19
+ */
20
+ declare const Aero: {
21
+ /** Props passed to the current component or page. */
22
+ props: Record<string, any>
23
+ /** Named slot content (key to HTML string). */
24
+ slots: Record<string, string>
25
+ /** The incoming request (available during SSR). */
26
+ request: Request
27
+ /** The request URL. */
28
+ url: URL
29
+ /** Dynamic route parameters (e.g. `{ id: '42' }` for `/posts/[id]`). */
30
+ params: Record<string, string>
31
+ /** Canonical site URL from `aero.config` (e.g. `'https://example.com'`). */
32
+ site?: string
33
+ }
34
+
35
+ /**
36
+ * Render a child component and return its HTML.
37
+ *
38
+ * @param component - The imported component (default import from an `.html` file).
39
+ * @param props - Props to pass to the component.
40
+ * @param slots - Named slot content.
41
+ * @returns The rendered HTML string.
42
+ */
43
+ declare function renderComponent(
44
+ component: any,
45
+ props?: Record<string, any>,
46
+ slots?: Record<string, string>,
47
+ ): Promise<string>
48
+
49
+ /** Allows importing `.html` component files in build scripts. */
50
+ declare module '*.html' {
51
+ const component: string
52
+ export default component
53
+ }
54
+
55
+ /** Content collections: getCollection, render. Used by the language server for IntelliSense. */
56
+ declare module 'aero:content' {
57
+ interface CollectionEntry {
58
+ id: string
59
+ data: Record<string, any>
60
+ body?: string
61
+ }
62
+ export function getCollection(name: string): Promise<CollectionEntry[]>
63
+ export function render(
64
+ entry: CollectionEntry | Record<string, any>,
65
+ ): Promise<{ html: string }>
66
+ }
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@aerobuilt/core",
3
- "version": "0.3.2",
4
- "type": "module",
3
+ "version": "0.3.3",
4
+ "private": false,
5
+ "homepage": "https://github.com/aerobuilt/aero",
5
6
  "license": "MIT",
6
7
  "author": "Jamie Wilson",
7
8
  "repository": {
@@ -9,12 +10,12 @@
9
10
  "url": "https://github.com/aerobuilt/aero.git",
10
11
  "directory": "packages/core"
11
12
  },
12
- "homepage": "https://github.com/aerobuilt/aero",
13
- "private": false,
14
- "types": "./dist/entry-dev.d.mts",
15
13
  "files": [
16
- "dist"
14
+ "dist",
15
+ "env.d.ts"
17
16
  ],
17
+ "type": "module",
18
+ "types": "./dist/entry-dev.d.mts",
18
19
  "exports": {
19
20
  ".": {
20
21
  "types": "./dist/entry-dev.d.mts",
@@ -48,19 +49,27 @@
48
49
  "./editor": {
49
50
  "types": "./dist/entry-editor.d.mts",
50
51
  "default": "./dist/entry-editor.mjs"
51
- }
52
+ },
53
+ "./env": "./env.d.ts"
52
54
  },
53
55
  "dependencies": {
54
56
  "get-tsconfig": "^4.13.6",
55
- "oxc-resolver": "^11.19.0",
56
57
  "html-minifier-next": "^5.1.1",
57
58
  "linkedom": "^0.18.12",
58
59
  "nitro": "^3.0.1-alpha.2",
59
60
  "oxc-parser": "^0.115.0",
61
+ "oxc-resolver": "^11.19.0",
62
+ "oxc-transform": "^0.116.0",
60
63
  "sharp": "^0.34.5",
61
64
  "svgo": "^4.0.0",
62
65
  "vite-plugin-image-optimizer": "^2.0.3",
63
- "@aerobuilt/interpolation": "0.3.2"
66
+ "@aerobuilt/interpolation": "0.3.3"
67
+ },
68
+ "devDependencies": {
69
+ "@types/node": "^25.3.0",
70
+ "tsdown": "^0.21.0-beta.2",
71
+ "typescript": "^5.9.3",
72
+ "vitest": "^4.0.18"
64
73
  },
65
74
  "peerDependencies": {
66
75
  "vite": "^8.0.0-0"
@@ -70,12 +79,6 @@
70
79
  "optional": true
71
80
  }
72
81
  },
73
- "devDependencies": {
74
- "@types/node": "^25.3.0",
75
- "tsdown": "^0.21.0-beta.2",
76
- "typescript": "^5.9.3",
77
- "vitest": "^4.0.18"
78
- },
79
82
  "scripts": {
80
83
  "build": "tsdown",
81
84
  "typecheck": "tsc --noEmit",