@vertz/ui-server 0.2.29 → 0.2.31

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.
@@ -0,0 +1,227 @@
1
+ import {
2
+ escapeAttr,
3
+ injectIntoTemplate,
4
+ precomputeHandlerState,
5
+ resolveRouteModulepreload,
6
+ resolveSession,
7
+ safeSerialize,
8
+ ssrRenderProgressive,
9
+ ssrRenderSinglePass,
10
+ ssrStreamNavQueries
11
+ } from "./chunk-34fexgex.js";
12
+
13
+ // src/node-handler.ts
14
+ function createNodeHandler(options) {
15
+ const {
16
+ module,
17
+ ssrTimeout,
18
+ nonce,
19
+ fallbackMetrics,
20
+ routeChunkManifest,
21
+ cacheControl,
22
+ sessionResolver,
23
+ manifest,
24
+ progressiveHTML
25
+ } = options;
26
+ const { template, linkHeader, modulepreloadTags, splitResult } = precomputeHandlerState(options);
27
+ const useProgressive = progressiveHTML && splitResult && !(manifest?.routeEntries && Object.keys(manifest.routeEntries).length > 0);
28
+ return (req, res) => {
29
+ (async () => {
30
+ try {
31
+ const url = req.url ?? "/";
32
+ if (req.headers["x-vertz-nav"] === "1") {
33
+ const pathname = url.split("?")[0];
34
+ await handleNavRequest(req, res, module, pathname, ssrTimeout);
35
+ return;
36
+ }
37
+ let sessionScript = "";
38
+ let ssrAuth;
39
+ if (sessionResolver) {
40
+ const fullUrl = `http://${req.headers.host ?? "localhost"}${url}`;
41
+ const webRequest = new Request(fullUrl, {
42
+ method: req.method ?? "GET",
43
+ headers: req.headers
44
+ });
45
+ const result2 = await resolveSession(webRequest, sessionResolver, nonce);
46
+ sessionScript = result2.sessionScript;
47
+ ssrAuth = result2.ssrAuth;
48
+ }
49
+ if (useProgressive) {
50
+ await handleProgressiveRequest(req, res, module, splitResult, url, ssrTimeout, nonce, fallbackMetrics, linkHeader, modulepreloadTags, routeChunkManifest, cacheControl, sessionScript, ssrAuth, manifest);
51
+ return;
52
+ }
53
+ const result = await ssrRenderSinglePass(module, url, {
54
+ ssrTimeout,
55
+ fallbackMetrics,
56
+ ssrAuth,
57
+ manifest
58
+ });
59
+ if (result.redirect) {
60
+ res.writeHead(302, { Location: result.redirect.to });
61
+ res.end();
62
+ return;
63
+ }
64
+ const resolvedModulepreloadTags = resolveRouteModulepreload(routeChunkManifest, result.matchedRoutePatterns, modulepreloadTags);
65
+ const allHeadTags = [result.headTags, resolvedModulepreloadTags].filter(Boolean).join(`
66
+ `);
67
+ const html = injectIntoTemplate({
68
+ template,
69
+ appHtml: result.html,
70
+ appCss: result.css,
71
+ ssrData: result.ssrData,
72
+ nonce,
73
+ headTags: allHeadTags || undefined,
74
+ sessionScript
75
+ });
76
+ const headers = {
77
+ "Content-Type": "text/html; charset=utf-8"
78
+ };
79
+ if (linkHeader)
80
+ headers.Link = linkHeader;
81
+ if (cacheControl)
82
+ headers["Cache-Control"] = cacheControl;
83
+ res.writeHead(200, headers);
84
+ res.end(html);
85
+ } catch (err) {
86
+ console.error("[SSR] Render failed:", err instanceof Error ? err.message : err);
87
+ if (!res.headersSent) {
88
+ res.writeHead(500, { "Content-Type": "text/plain" });
89
+ }
90
+ res.end("Internal Server Error");
91
+ }
92
+ })();
93
+ };
94
+ }
95
+ async function handleProgressiveRequest(req, res, module, split, url, ssrTimeout, nonce, fallbackMetrics, linkHeader, staticModulepreloadTags, routeChunkManifest, cacheControl, sessionScript, ssrAuth, manifest) {
96
+ const result = await ssrRenderProgressive(module, url, {
97
+ ssrTimeout,
98
+ fallbackMetrics,
99
+ ssrAuth,
100
+ manifest
101
+ });
102
+ if (result.redirect) {
103
+ res.writeHead(302, { Location: result.redirect.to });
104
+ res.end();
105
+ return;
106
+ }
107
+ const resolvedModulepreloadTags = resolveRouteModulepreload(routeChunkManifest, result.matchedRoutePatterns, staticModulepreloadTags);
108
+ let headChunk = split.headTemplate;
109
+ const headCloseIdx = headChunk.lastIndexOf("</head>");
110
+ if (headCloseIdx !== -1) {
111
+ const injections = [];
112
+ if (result.css)
113
+ injections.push(result.css);
114
+ if (result.headTags)
115
+ injections.push(result.headTags);
116
+ if (resolvedModulepreloadTags)
117
+ injections.push(resolvedModulepreloadTags);
118
+ if (sessionScript)
119
+ injections.push(sessionScript);
120
+ if (injections.length > 0) {
121
+ headChunk = headChunk.slice(0, headCloseIdx) + injections.join(`
122
+ `) + `
123
+ ` + headChunk.slice(headCloseIdx);
124
+ }
125
+ } else {
126
+ if (result.css)
127
+ headChunk += result.css;
128
+ if (result.headTags)
129
+ headChunk += result.headTags;
130
+ if (resolvedModulepreloadTags)
131
+ headChunk += resolvedModulepreloadTags;
132
+ if (sessionScript)
133
+ headChunk += sessionScript;
134
+ }
135
+ const headers = {
136
+ "Content-Type": "text/html; charset=utf-8"
137
+ };
138
+ if (linkHeader)
139
+ headers.Link = linkHeader;
140
+ if (cacheControl)
141
+ headers["Cache-Control"] = cacheControl;
142
+ res.writeHead(200, headers);
143
+ res.write(headChunk);
144
+ let clientDisconnected = false;
145
+ req.on("close", () => {
146
+ clientDisconnected = true;
147
+ });
148
+ if (result.renderStream) {
149
+ const reader = result.renderStream.getReader();
150
+ let renderError;
151
+ try {
152
+ for (;; ) {
153
+ if (clientDisconnected) {
154
+ reader.cancel();
155
+ break;
156
+ }
157
+ const { done, value } = await reader.read();
158
+ if (done)
159
+ break;
160
+ const canContinue = res.write(value);
161
+ if (!canContinue && !clientDisconnected) {
162
+ await new Promise((resolve) => res.once("drain", resolve));
163
+ }
164
+ }
165
+ } catch (err) {
166
+ renderError = err instanceof Error ? err : new Error(String(err));
167
+ } finally {
168
+ reader.releaseLock();
169
+ }
170
+ if (renderError && !clientDisconnected) {
171
+ console.error("[SSR] Render error after head sent:", renderError.message);
172
+ const nonceAttr = nonce != null ? ` nonce="${escapeAttr(nonce)}"` : "";
173
+ const errorScript = `<script${nonceAttr}>document.dispatchEvent(new CustomEvent('vertz:ssr-error',` + `{detail:{message:${safeSerialize(renderError.message)}}}))</script>`;
174
+ res.write(errorScript);
175
+ }
176
+ }
177
+ if (clientDisconnected)
178
+ return;
179
+ let tail = "";
180
+ if (result.ssrData.length > 0) {
181
+ const nonceAttr = nonce != null ? ` nonce="${escapeAttr(nonce)}"` : "";
182
+ tail += `<script${nonceAttr}>window.__VERTZ_SSR_DATA__=${safeSerialize(result.ssrData)};</script>`;
183
+ }
184
+ tail += split.tailTemplate;
185
+ res.end(tail);
186
+ }
187
+ async function handleNavRequest(req, res, module, url, ssrTimeout) {
188
+ res.writeHead(200, {
189
+ "Content-Type": "text/event-stream",
190
+ "Cache-Control": "no-cache"
191
+ });
192
+ try {
193
+ const stream = await ssrStreamNavQueries(module, url, { ssrTimeout });
194
+ let clientDisconnected = false;
195
+ req.on("close", () => {
196
+ clientDisconnected = true;
197
+ });
198
+ const reader = stream.getReader();
199
+ try {
200
+ for (;; ) {
201
+ if (clientDisconnected) {
202
+ reader.cancel();
203
+ break;
204
+ }
205
+ const { done, value } = await reader.read();
206
+ if (done)
207
+ break;
208
+ const canContinue = res.write(value);
209
+ if (!canContinue && !clientDisconnected) {
210
+ await new Promise((resolve) => res.once("drain", resolve));
211
+ }
212
+ }
213
+ } finally {
214
+ reader.releaseLock();
215
+ }
216
+ } catch {
217
+ res.write(`event: done
218
+ data: {}
219
+
220
+ `);
221
+ }
222
+ if (!res.writableEnded) {
223
+ res.end();
224
+ }
225
+ }
226
+
227
+ export { createNodeHandler };
@@ -0,0 +1,216 @@
1
+ import {
2
+ encodeChunk,
3
+ escapeAttr,
4
+ injectIntoTemplate,
5
+ precomputeHandlerState,
6
+ resolveRouteModulepreload,
7
+ resolveSession,
8
+ safeSerialize,
9
+ ssrRenderProgressive,
10
+ ssrRenderSinglePass,
11
+ ssrStreamNavQueries
12
+ } from "./chunk-34fexgex.js";
13
+
14
+ // src/ssr-progressive-response.ts
15
+ function buildProgressiveResponse(options) {
16
+ const { headChunk, renderStream, tailChunk, ssrData, nonce, headers } = options;
17
+ const stream = new ReadableStream({
18
+ async start(controller) {
19
+ controller.enqueue(encodeChunk(headChunk));
20
+ const reader = renderStream.getReader();
21
+ let renderError;
22
+ try {
23
+ for (;; ) {
24
+ const { done, value } = await reader.read();
25
+ if (done)
26
+ break;
27
+ controller.enqueue(value);
28
+ }
29
+ } catch (err) {
30
+ renderError = err instanceof Error ? err : new Error(String(err));
31
+ }
32
+ if (renderError) {
33
+ console.error("[SSR] Render error after head sent:", renderError.message);
34
+ const nonceAttr = nonce != null ? ` nonce="${escapeAttr(nonce)}"` : "";
35
+ const errorScript = `<script${nonceAttr}>document.dispatchEvent(new CustomEvent('vertz:ssr-error',` + `{detail:{message:${safeSerialize(renderError.message)}}}))</script>`;
36
+ controller.enqueue(encodeChunk(errorScript));
37
+ }
38
+ let tail = "";
39
+ if (ssrData.length > 0) {
40
+ const nonceAttr = nonce != null ? ` nonce="${escapeAttr(nonce)}"` : "";
41
+ tail += `<script${nonceAttr}>window.__VERTZ_SSR_DATA__=${safeSerialize(ssrData)};</script>`;
42
+ }
43
+ tail += tailChunk;
44
+ controller.enqueue(encodeChunk(tail));
45
+ controller.close();
46
+ }
47
+ });
48
+ const responseHeaders = {
49
+ "Content-Type": "text/html; charset=utf-8",
50
+ ...headers
51
+ };
52
+ return new Response(stream, { status: 200, headers: responseHeaders });
53
+ }
54
+
55
+ // src/ssr-handler.ts
56
+ function createSSRHandler(options) {
57
+ const {
58
+ module,
59
+ ssrTimeout,
60
+ nonce,
61
+ fallbackMetrics,
62
+ routeChunkManifest,
63
+ cacheControl,
64
+ sessionResolver,
65
+ manifest,
66
+ progressiveHTML
67
+ } = options;
68
+ const { template, linkHeader, modulepreloadTags, splitResult } = precomputeHandlerState(options);
69
+ return async (request) => {
70
+ const url = new URL(request.url);
71
+ const pathname = url.pathname;
72
+ if (request.headers.get("x-vertz-nav") === "1") {
73
+ return handleNavRequest(module, pathname, ssrTimeout);
74
+ }
75
+ let sessionScript = "";
76
+ let ssrAuth;
77
+ if (sessionResolver) {
78
+ const result = await resolveSession(request, sessionResolver, nonce);
79
+ sessionScript = result.sessionScript;
80
+ ssrAuth = result.ssrAuth;
81
+ }
82
+ const useProgressive = progressiveHTML && splitResult && !(manifest?.routeEntries && Object.keys(manifest.routeEntries).length > 0);
83
+ if (useProgressive) {
84
+ return handleProgressiveHTMLRequest(module, splitResult, pathname + url.search, ssrTimeout, nonce, fallbackMetrics, linkHeader, modulepreloadTags, routeChunkManifest, cacheControl, sessionScript, ssrAuth, manifest);
85
+ }
86
+ return handleHTMLRequest(module, template, pathname + url.search, ssrTimeout, nonce, fallbackMetrics, linkHeader, modulepreloadTags, routeChunkManifest, cacheControl, sessionScript, ssrAuth, manifest);
87
+ };
88
+ }
89
+ async function handleNavRequest(module, url, ssrTimeout) {
90
+ try {
91
+ const stream = await ssrStreamNavQueries(module, url, { ssrTimeout });
92
+ return new Response(stream, {
93
+ status: 200,
94
+ headers: {
95
+ "Content-Type": "text/event-stream",
96
+ "Cache-Control": "no-cache"
97
+ }
98
+ });
99
+ } catch {
100
+ return new Response(`event: done
101
+ data: {}
102
+
103
+ `, {
104
+ status: 200,
105
+ headers: {
106
+ "Content-Type": "text/event-stream",
107
+ "Cache-Control": "no-cache"
108
+ }
109
+ });
110
+ }
111
+ }
112
+ async function handleProgressiveHTMLRequest(module, split, url, ssrTimeout, nonce, fallbackMetrics, linkHeader, staticModulepreloadTags, routeChunkManifest, cacheControl, sessionScript, ssrAuth, manifest) {
113
+ try {
114
+ const result = await ssrRenderProgressive(module, url, {
115
+ ssrTimeout,
116
+ fallbackMetrics,
117
+ ssrAuth,
118
+ manifest
119
+ });
120
+ if (result.redirect) {
121
+ return new Response(null, {
122
+ status: 302,
123
+ headers: { Location: result.redirect.to }
124
+ });
125
+ }
126
+ const modulepreloadTags = resolveRouteModulepreload(routeChunkManifest, result.matchedRoutePatterns, staticModulepreloadTags);
127
+ let headChunk = split.headTemplate;
128
+ const headCloseIdx = headChunk.lastIndexOf("</head>");
129
+ if (headCloseIdx !== -1) {
130
+ const injections = [];
131
+ if (result.css)
132
+ injections.push(result.css);
133
+ if (result.headTags)
134
+ injections.push(result.headTags);
135
+ if (modulepreloadTags)
136
+ injections.push(modulepreloadTags);
137
+ if (sessionScript)
138
+ injections.push(sessionScript);
139
+ if (injections.length > 0) {
140
+ headChunk = headChunk.slice(0, headCloseIdx) + injections.join(`
141
+ `) + `
142
+ ` + headChunk.slice(headCloseIdx);
143
+ }
144
+ } else {
145
+ if (result.css)
146
+ headChunk += result.css;
147
+ if (result.headTags)
148
+ headChunk += result.headTags;
149
+ if (modulepreloadTags)
150
+ headChunk += modulepreloadTags;
151
+ if (sessionScript)
152
+ headChunk += sessionScript;
153
+ }
154
+ const headers = {};
155
+ if (linkHeader)
156
+ headers.Link = linkHeader;
157
+ if (cacheControl)
158
+ headers["Cache-Control"] = cacheControl;
159
+ return buildProgressiveResponse({
160
+ headChunk,
161
+ renderStream: result.renderStream,
162
+ tailChunk: split.tailTemplate,
163
+ ssrData: result.ssrData,
164
+ nonce,
165
+ headers
166
+ });
167
+ } catch (err) {
168
+ console.error("[SSR] Render failed:", err instanceof Error ? err.message : err);
169
+ return new Response("Internal Server Error", {
170
+ status: 500,
171
+ headers: { "Content-Type": "text/plain" }
172
+ });
173
+ }
174
+ }
175
+ async function handleHTMLRequest(module, template, url, ssrTimeout, nonce, fallbackMetrics, linkHeader, staticModulepreloadTags, routeChunkManifest, cacheControl, sessionScript, ssrAuth, manifest) {
176
+ try {
177
+ const result = await ssrRenderSinglePass(module, url, {
178
+ ssrTimeout,
179
+ fallbackMetrics,
180
+ ssrAuth,
181
+ manifest
182
+ });
183
+ if (result.redirect) {
184
+ return new Response(null, {
185
+ status: 302,
186
+ headers: { Location: result.redirect.to }
187
+ });
188
+ }
189
+ const modulepreloadTags = resolveRouteModulepreload(routeChunkManifest, result.matchedRoutePatterns, staticModulepreloadTags);
190
+ const allHeadTags = [result.headTags, modulepreloadTags].filter(Boolean).join(`
191
+ `);
192
+ const html = injectIntoTemplate({
193
+ template,
194
+ appHtml: result.html,
195
+ appCss: result.css,
196
+ ssrData: result.ssrData,
197
+ nonce,
198
+ headTags: allHeadTags || undefined,
199
+ sessionScript
200
+ });
201
+ const headers = { "Content-Type": "text/html; charset=utf-8" };
202
+ if (linkHeader)
203
+ headers.Link = linkHeader;
204
+ if (cacheControl)
205
+ headers["Cache-Control"] = cacheControl;
206
+ return new Response(html, { status: 200, headers });
207
+ } catch (err) {
208
+ console.error("[SSR] Render failed:", err instanceof Error ? err.message : err);
209
+ return new Response("Internal Server Error", {
210
+ status: 500,
211
+ headers: { "Content-Type": "text/plain" }
212
+ });
213
+ }
214
+ }
215
+
216
+ export { createSSRHandler };
@@ -707,4 +707,4 @@ function toVNode(element) {
707
707
  return { tag: "span", attrs: {}, children: [String(element)] };
708
708
  }
709
709
 
710
- export { ssrStorage, isInSSR, getSSRUrl, registerSSRQuery, getSSRQueries, setGlobalSSRTimeout, clearGlobalSSRTimeout, getGlobalSSRTimeout, SSRNode, SSRComment, rawHtml, SSRTextNode, SSRDocumentFragment, SSRElement, createSSRAdapter, installDomShim, removeDomShim, toVNode };
710
+ export { SSRNode, SSRComment, rawHtml, SSRTextNode, SSRDocumentFragment, SSRElement, createSSRAdapter, ssrStorage, isInSSR, getSSRUrl, registerSSRQuery, getSSRQueries, setGlobalSSRTimeout, clearGlobalSSRTimeout, getGlobalSSRTimeout, installDomShim, removeDomShim, toVNode };
@@ -128,7 +128,59 @@ declare function stripScriptsFromStaticHTML(html: string): string;
128
128
  * - Routes without `prerender` or `generateParams` are not collected
129
129
  */
130
130
  declare function collectPrerenderPaths(routes: CompiledRoute2[], prefix?: string): Promise<string[]>;
131
- import { FontFallbackMetrics as FontFallbackMetrics3 } from "@vertz/ui";
131
+ import { FontFallbackMetrics as FontFallbackMetrics4 } from "@vertz/ui";
132
+ import { ExtractedQuery } from "@vertz/ui-compiler";
133
+ /**
134
+ * SSR prefetch access rule evaluator.
135
+ *
136
+ * Evaluates serialized entity access rules against the current session
137
+ * to determine whether a query should be prefetched during SSR.
138
+ *
139
+ * The serialized rules come from the prefetch manifest (generated at build time).
140
+ * The session comes from the JWT decoded at request time.
141
+ */
142
+ /**
143
+ * Serialized access rule — the JSON-friendly format stored in the manifest.
144
+ * Mirrors SerializedRule from @vertz/server/auth/rules but defined here
145
+ * to avoid importing the server package into the SSR pipeline.
146
+ */
147
+ type SerializedAccessRule = {
148
+ type: "public";
149
+ } | {
150
+ type: "authenticated";
151
+ } | {
152
+ type: "role";
153
+ roles: string[];
154
+ } | {
155
+ type: "entitlement";
156
+ value: string;
157
+ } | {
158
+ type: "where";
159
+ conditions: Record<string, unknown>;
160
+ } | {
161
+ type: "all";
162
+ rules: SerializedAccessRule[];
163
+ } | {
164
+ type: "any";
165
+ rules: SerializedAccessRule[];
166
+ } | {
167
+ type: "fva";
168
+ maxAge: number;
169
+ } | {
170
+ type: "deny";
171
+ };
172
+ /** Serialized entity access rules from the prefetch manifest. */
173
+ type EntityAccessMap = Record<string, Partial<Record<string, SerializedAccessRule>>>;
174
+ interface SSRPrefetchManifest {
175
+ /** Route patterns present in the manifest. */
176
+ routePatterns: string[];
177
+ /** Entity access rules keyed by entity name → operation → serialized rule. */
178
+ entityAccess?: EntityAccessMap;
179
+ /** Route entries with query binding metadata for zero-discovery prefetch. */
180
+ routeEntries?: Record<string, {
181
+ queries: ExtractedQuery[];
182
+ }>;
183
+ }
132
184
  import { AccessSet } from "@vertz/ui/auth";
133
185
  interface SessionData {
134
186
  user: {
@@ -182,7 +234,7 @@ interface SSRHandlerOptions {
182
234
  */
183
235
  nonce?: string;
184
236
  /** Pre-computed font fallback metrics (computed at server startup). */
185
- fallbackMetrics?: Record<string, FontFallbackMetrics3>;
237
+ fallbackMetrics?: Record<string, FontFallbackMetrics4>;
186
238
  /** Paths to inject as `<link rel="modulepreload">` in `<head>`. */
187
239
  modulepreload?: string[];
188
240
  /**
@@ -200,6 +252,27 @@ interface SSRHandlerOptions {
200
252
  * optionally `window.__VERTZ_ACCESS_SET__` for instant auth hydration.
201
253
  */
202
254
  sessionResolver?: SessionResolver;
255
+ /**
256
+ * Prefetch manifest for single-pass SSR optimization.
257
+ *
258
+ * When provided with route entries and an API client export, enables
259
+ * zero-discovery rendering — queries are prefetched from the manifest
260
+ * without executing the component tree, then a single render pass
261
+ * produces the HTML. Without a manifest, SSR still uses the single-pass
262
+ * discovery-then-render approach (cheaper than two-pass).
263
+ */
264
+ manifest?: SSRPrefetchManifest;
265
+ /**
266
+ * Enable progressive HTML streaming. Default: false.
267
+ *
268
+ * When true, the Response body is a ReadableStream that sends `<head>`
269
+ * content (CSS, preloads, fonts) before `<body>` rendering is complete.
270
+ * This improves TTFB and FCP.
271
+ *
272
+ * Has no effect on zero-discovery routes (manifest with routeEntries),
273
+ * which always use buffered rendering.
274
+ */
275
+ progressiveHTML?: boolean;
203
276
  }
204
277
  declare function createSSRHandler(options: SSRHandlerOptions): (request: Request) => Promise<Response>;
205
278
  interface InjectIntoTemplateOptions {
package/dist/ssr/index.js CHANGED
@@ -1,10 +1,12 @@
1
1
  import {
2
- createSSRHandler,
2
+ createSSRHandler
3
+ } from "../shared/chunk-wb5fv233.js";
4
+ import {
3
5
  injectIntoTemplate,
4
6
  ssrDiscoverQueries,
5
7
  ssrRenderToString
6
- } from "../shared/chunk-yr65qdge.js";
7
- import"../shared/chunk-gcwqkynf.js";
8
+ } from "../shared/chunk-34fexgex.js";
9
+ import"../shared/chunk-ybftdw1r.js";
8
10
 
9
11
  // src/prerender.ts
10
12
  async function discoverRoutes(module) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vertz/ui-server",
3
- "version": "0.2.29",
3
+ "version": "0.2.31",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Vertz UI server-side rendering runtime",
@@ -43,6 +43,10 @@
43
43
  "./fetch-scope": {
44
44
  "import": "./dist/fetch-scope.js",
45
45
  "types": "./dist/fetch-scope.d.ts"
46
+ },
47
+ "./node": {
48
+ "import": "./dist/node-handler.js",
49
+ "types": "./dist/node-handler.d.ts"
46
50
  }
47
51
  },
48
52
  "files": [
@@ -58,15 +62,15 @@
58
62
  "@ampproject/remapping": "^2.3.0",
59
63
  "@capsizecss/unpack": "^4.0.0",
60
64
  "@jridgewell/trace-mapping": "^0.3.31",
61
- "@vertz/core": "^0.2.28",
62
- "@vertz/ui": "^0.2.28",
63
- "@vertz/ui-compiler": "^0.2.28",
65
+ "@vertz/core": "^0.2.30",
66
+ "@vertz/ui": "^0.2.30",
67
+ "@vertz/ui-compiler": "^0.2.30",
64
68
  "magic-string": "^0.30.0",
65
69
  "sharp": "^0.34.5",
66
70
  "ts-morph": "^27.0.2"
67
71
  },
68
72
  "devDependencies": {
69
- "@vertz/codegen": "^0.2.28",
73
+ "@vertz/codegen": "^0.2.30",
70
74
  "@vertz/ui-auth": "^0.2.19",
71
75
  "bun-types": "^1.3.10",
72
76
  "bunup": "^0.16.31",