@vertz/ui-server 0.2.31 → 0.2.33

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.
@@ -5,10 +5,12 @@ import {
5
5
  resolveRouteModulepreload,
6
6
  resolveSession,
7
7
  safeSerialize,
8
+ ssrRenderAot,
8
9
  ssrRenderProgressive,
9
10
  ssrRenderSinglePass,
10
- ssrStreamNavQueries
11
- } from "./chunk-34fexgex.js";
11
+ ssrStreamNavQueries,
12
+ toPrefetchSession
13
+ } from "./chunk-hx7drzm3.js";
12
14
 
13
15
  // src/node-handler.ts
14
16
  function createNodeHandler(options) {
@@ -21,7 +23,8 @@ function createNodeHandler(options) {
21
23
  cacheControl,
22
24
  sessionResolver,
23
25
  manifest,
24
- progressiveHTML
26
+ progressiveHTML,
27
+ aotManifest
25
28
  } = options;
26
29
  const { template, linkHeader, modulepreloadTags, splitResult } = precomputeHandlerState(options);
27
30
  const useProgressive = progressiveHTML && splitResult && !(manifest?.routeEntries && Object.keys(manifest.routeEntries).length > 0);
@@ -50,11 +53,20 @@ function createNodeHandler(options) {
50
53
  await handleProgressiveRequest(req, res, module, splitResult, url, ssrTimeout, nonce, fallbackMetrics, linkHeader, modulepreloadTags, routeChunkManifest, cacheControl, sessionScript, ssrAuth, manifest);
51
54
  return;
52
55
  }
53
- const result = await ssrRenderSinglePass(module, url, {
56
+ const prefetchSession = ssrAuth ? toPrefetchSession(ssrAuth) : undefined;
57
+ const result = aotManifest ? await ssrRenderAot(module, url, {
58
+ aotManifest,
59
+ manifest,
54
60
  ssrTimeout,
55
61
  fallbackMetrics,
56
62
  ssrAuth,
57
- manifest
63
+ prefetchSession
64
+ }) : await ssrRenderSinglePass(module, url, {
65
+ ssrTimeout,
66
+ fallbackMetrics,
67
+ ssrAuth,
68
+ manifest,
69
+ prefetchSession
58
70
  });
59
71
  if (result.redirect) {
60
72
  res.writeHead(302, { Location: result.redirect.to });
@@ -1,4 +1,54 @@
1
- import { CompiledRoute as CompiledRoute2, FontFallbackMetrics as FontFallbackMetrics2 } from "@vertz/ui";
1
+ /**
2
+ * SSR prefetch access rule evaluator.
3
+ *
4
+ * Evaluates serialized entity access rules against the current session
5
+ * to determine whether a query should be prefetched during SSR.
6
+ *
7
+ * The serialized rules come from the prefetch manifest (generated at build time).
8
+ * The session comes from the JWT decoded at request time.
9
+ */
10
+ /**
11
+ * Serialized access rule — the JSON-friendly format stored in the manifest.
12
+ * Mirrors SerializedRule from @vertz/server/auth/rules but defined here
13
+ * to avoid importing the server package into the SSR pipeline.
14
+ */
15
+ type SerializedAccessRule = {
16
+ type: "public";
17
+ } | {
18
+ type: "authenticated";
19
+ } | {
20
+ type: "role";
21
+ roles: string[];
22
+ } | {
23
+ type: "entitlement";
24
+ value: string;
25
+ } | {
26
+ type: "where";
27
+ conditions: Record<string, unknown>;
28
+ } | {
29
+ type: "all";
30
+ rules: SerializedAccessRule[];
31
+ } | {
32
+ type: "any";
33
+ rules: SerializedAccessRule[];
34
+ } | {
35
+ type: "fva";
36
+ maxAge: number;
37
+ } | {
38
+ type: "deny";
39
+ };
40
+ /**
41
+ * Minimal session shape needed for prefetch access evaluation.
42
+ * Extracted from the JWT at SSR request time.
43
+ */
44
+ type PrefetchSession = {
45
+ status: "authenticated";
46
+ roles?: string[];
47
+ entitlements?: Record<string, boolean>;
48
+ tenantId?: string;
49
+ } | {
50
+ status: "unauthenticated";
51
+ };
2
52
  import { CompiledRoute, FontFallbackMetrics, Theme } from "@vertz/ui";
3
53
  import { SSRAuth as SSRAuth_jq1nwm } from "@vertz/ui/internals";
4
54
  interface SSRModule {
@@ -67,6 +117,60 @@ declare function ssrRenderToString(module: SSRModule, url: string, options?: {
67
117
  declare function ssrDiscoverQueries(module: SSRModule, url: string, options?: {
68
118
  ssrTimeout?: number;
69
119
  }): Promise<SSRDiscoverResult>;
120
+ import { ExtractedQuery } from "@vertz/ui-compiler";
121
+ /** Serialized entity access rules from the prefetch manifest. */
122
+ type EntityAccessMap = Record<string, Partial<Record<string, SerializedAccessRule>>>;
123
+ interface SSRPrefetchManifest {
124
+ /** Route patterns present in the manifest. */
125
+ routePatterns: string[];
126
+ /** Entity access rules keyed by entity name → operation → serialized rule. */
127
+ entityAccess?: EntityAccessMap;
128
+ /** Route entries with query binding metadata for zero-discovery prefetch. */
129
+ routeEntries?: Record<string, {
130
+ queries: ExtractedQuery[];
131
+ }>;
132
+ }
133
+ /** Context passed to AOT render functions for accessing data and runtime holes. */
134
+ interface SSRAotContext {
135
+ /** Pre-generated closures for runtime-rendered components. */
136
+ holes: Record<string, () => string>;
137
+ /** Access query data by cache key. */
138
+ getData(key: string): unknown;
139
+ /** Auth session for conditional rendering. */
140
+ session: PrefetchSession | undefined;
141
+ /** Route params for the current request. */
142
+ params: Record<string, string>;
143
+ }
144
+ /** An AOT render function: takes props/data and context, returns HTML string. */
145
+ type AotRenderFn = (data: Record<string, unknown>, ctx: SSRAotContext) => string;
146
+ /** Per-route AOT entry in the manifest. */
147
+ interface AotRouteEntry {
148
+ /** The pre-compiled render function. */
149
+ render: AotRenderFn;
150
+ /** Component names that need runtime fallback (holes). */
151
+ holes: string[];
152
+ /** Query cache keys this route reads via ctx.getData(). */
153
+ queryKeys?: string[];
154
+ }
155
+ /**
156
+ * AOT manifest — maps route patterns to pre-compiled render functions.
157
+ *
158
+ * Generated at build time by the AOT compiler pipeline.
159
+ */
160
+ interface AotManifest {
161
+ /** Route pattern → AOT entry. */
162
+ routes: Record<string, AotRouteEntry>;
163
+ }
164
+ /**
165
+ * Load AOT manifest and routes module from a server build directory.
166
+ *
167
+ * Returns `null` if either `aot-manifest.json` or `aot-routes.js` is missing,
168
+ * or if no routes can be wired to render functions.
169
+ *
170
+ * @param serverDir - Path to `dist/server/` directory
171
+ */
172
+ declare function loadAotManifest(serverDir: string): Promise<AotManifest | null>;
173
+ import { CompiledRoute as CompiledRoute2, FontFallbackMetrics as FontFallbackMetrics4 } from "@vertz/ui";
70
174
  interface PrerenderResult {
71
175
  /** The route path that was pre-rendered. */
72
176
  path: string;
@@ -79,7 +183,7 @@ interface PrerenderOptions {
79
183
  /** CSP nonce for inline scripts. */
80
184
  nonce?: string;
81
185
  /** Pre-computed font fallback metrics for zero-CLS font loading. */
82
- fallbackMetrics?: Record<string, FontFallbackMetrics2>;
186
+ fallbackMetrics?: Record<string, FontFallbackMetrics4>;
83
187
  }
84
188
  /**
85
189
  * Discover all route patterns from an SSR module.
@@ -128,59 +232,7 @@ declare function stripScriptsFromStaticHTML(html: string): string;
128
232
  * - Routes without `prerender` or `generateParams` are not collected
129
233
  */
130
234
  declare function collectPrerenderPaths(routes: CompiledRoute2[], prefix?: string): Promise<string[]>;
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
- }
235
+ import { FontFallbackMetrics as FontFallbackMetrics5 } from "@vertz/ui";
184
236
  import { AccessSet } from "@vertz/ui/auth";
185
237
  interface SessionData {
186
238
  user: {
@@ -234,7 +286,7 @@ interface SSRHandlerOptions {
234
286
  */
235
287
  nonce?: string;
236
288
  /** Pre-computed font fallback metrics (computed at server startup). */
237
- fallbackMetrics?: Record<string, FontFallbackMetrics4>;
289
+ fallbackMetrics?: Record<string, FontFallbackMetrics5>;
238
290
  /** Paths to inject as `<link rel="modulepreload">` in `<head>`. */
239
291
  modulepreload?: string[];
240
292
  /**
@@ -273,6 +325,16 @@ interface SSRHandlerOptions {
273
325
  * which always use buffered rendering.
274
326
  */
275
327
  progressiveHTML?: boolean;
328
+ /**
329
+ * AOT manifest with pre-compiled render functions.
330
+ *
331
+ * When provided, routes matching AOT entries are rendered via string-builder
332
+ * functions (no DOM shim), bypassing the reactive runtime for 4-6x speedup.
333
+ * Routes not in the manifest fall back to `ssrRenderSinglePass()`.
334
+ *
335
+ * Load via `loadAotManifest(serverDir)` at startup.
336
+ */
337
+ aotManifest?: AotManifest;
276
338
  }
277
339
  declare function createSSRHandler(options: SSRHandlerOptions): (request: Request) => Promise<Response>;
278
340
  interface InjectIntoTemplateOptions {
@@ -295,4 +357,4 @@ interface InjectIntoTemplateOptions {
295
357
  * injects CSS before </head>, and ssrData before </body>.
296
358
  */
297
359
  declare function injectIntoTemplate(options: InjectIntoTemplateOptions): string;
298
- export { stripScriptsFromStaticHTML, ssrRenderToString, ssrDiscoverQueries, prerenderRoutes, injectIntoTemplate, filterPrerenderableRoutes, discoverRoutes, createSSRHandler, collectPrerenderPaths, SSRRenderResult, SSRModule, SSRHandlerOptions, SSRDiscoverResult, PrerenderResult, PrerenderOptions };
360
+ export { stripScriptsFromStaticHTML, ssrRenderToString, ssrDiscoverQueries, prerenderRoutes, loadAotManifest, injectIntoTemplate, filterPrerenderableRoutes, discoverRoutes, createSSRHandler, collectPrerenderPaths, SSRRenderResult, SSRModule, SSRHandlerOptions, SSRDiscoverResult, PrerenderResult, PrerenderOptions, AotManifest };
package/dist/ssr/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import {
2
- createSSRHandler
3
- } from "../shared/chunk-wb5fv233.js";
2
+ createSSRHandler,
3
+ loadAotManifest
4
+ } from "../shared/chunk-2kx402c1.js";
4
5
  import {
5
6
  injectIntoTemplate,
6
7
  ssrDiscoverQueries,
7
8
  ssrRenderToString
8
- } from "../shared/chunk-34fexgex.js";
9
+ } from "../shared/chunk-hx7drzm3.js";
9
10
  import"../shared/chunk-ybftdw1r.js";
10
-
11
11
  // src/prerender.ts
12
12
  async function discoverRoutes(module) {
13
13
  const result = await ssrRenderToString(module, "/");
@@ -115,6 +115,7 @@ export {
115
115
  ssrRenderToString,
116
116
  ssrDiscoverQueries,
117
117
  prerenderRoutes,
118
+ loadAotManifest,
118
119
  injectIntoTemplate,
119
120
  filterPrerenderableRoutes,
120
121
  discoverRoutes,
package/package.json CHANGED
@@ -1,14 +1,17 @@
1
1
  {
2
2
  "name": "@vertz/ui-server",
3
- "version": "0.2.31",
4
- "type": "module",
5
- "license": "MIT",
3
+ "version": "0.2.33",
6
4
  "description": "Vertz UI server-side rendering runtime",
5
+ "license": "MIT",
7
6
  "repository": {
8
7
  "type": "git",
9
8
  "url": "https://github.com/vertz-dev/vertz.git",
10
9
  "directory": "packages/ui-server"
11
10
  },
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "type": "module",
12
15
  "main": "dist/index.js",
13
16
  "types": "dist/index.d.ts",
14
17
  "exports": {
@@ -49,40 +52,39 @@
49
52
  "types": "./dist/node-handler.d.ts"
50
53
  }
51
54
  },
52
- "files": [
53
- "dist"
54
- ],
55
+ "publishConfig": {
56
+ "access": "public",
57
+ "provenance": true
58
+ },
55
59
  "scripts": {
56
60
  "build": "bunup",
57
- "test": "bun test",
61
+ "test": "bun test src/",
58
62
  "test:integration": "bun test src/__tests__/bun-dev-server.integration.local.ts",
63
+ "test:e2e": "bunx playwright test",
59
64
  "typecheck": "tsc --noEmit"
60
65
  },
61
66
  "dependencies": {
62
67
  "@ampproject/remapping": "^2.3.0",
63
68
  "@capsizecss/unpack": "^4.0.0",
64
69
  "@jridgewell/trace-mapping": "^0.3.31",
65
- "@vertz/core": "^0.2.30",
66
- "@vertz/ui": "^0.2.30",
67
- "@vertz/ui-compiler": "^0.2.30",
70
+ "@vertz/core": "^0.2.31",
71
+ "@vertz/ui": "^0.2.31",
72
+ "@vertz/ui-compiler": "^0.2.31",
68
73
  "magic-string": "^0.30.0",
69
74
  "sharp": "^0.34.5",
70
75
  "ts-morph": "^27.0.2"
71
76
  },
72
77
  "devDependencies": {
73
- "@vertz/codegen": "^0.2.30",
78
+ "@happy-dom/global-registrator": "^20.8.3",
79
+ "@playwright/test": "^1.58.2",
80
+ "@vertz/codegen": "^0.2.31",
74
81
  "@vertz/ui-auth": "^0.2.19",
75
82
  "bun-types": "^1.3.10",
76
83
  "bunup": "^0.16.31",
77
- "@happy-dom/global-registrator": "^20.8.3",
78
84
  "happy-dom": "^20.8.3",
79
85
  "typescript": "^5.7.0"
80
86
  },
81
87
  "engines": {
82
88
  "node": ">=22"
83
- },
84
- "publishConfig": {
85
- "access": "public",
86
- "provenance": true
87
89
  }
88
90
  }