@vertz/ui-server 0.2.24 → 0.2.25

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.
@@ -1,6 +1,6 @@
1
1
  type ErrorCategory = "build" | "resolve" | "runtime" | "ssr";
2
2
  import { CSSExtractionResult } from "@vertz/ui-compiler";
3
- type DebugCategory = "fields" | "manifest" | "plugin" | "ssr" | "watcher" | "ws";
3
+ type DebugCategory = "fields" | "manifest" | "plugin" | "prefetch" | "ssr" | "watcher" | "ws";
4
4
  interface DebugLogger {
5
5
  log(category: DebugCategory, message: string, data?: Record<string, unknown>): void;
6
6
  isEnabled(category: DebugCategory): boolean;
@@ -13,6 +13,7 @@ interface VNode {
13
13
  * Base Node class for SSR — matches the browser's Node interface minimally
14
14
  */
15
15
  declare class SSRNode {
16
+ nodeType: number;
16
17
  childNodes: SSRNode[];
17
18
  parentNode: SSRNode | null;
18
19
  get firstChild(): SSRNode | null;
@@ -28,6 +29,7 @@ declare class SSRNode {
28
29
  * hydration cursor can claim during mount.
29
30
  */
30
31
  declare class SSRComment extends SSRNode {
32
+ nodeType: number;
31
33
  text: string;
32
34
  constructor(text: string);
33
35
  get data(): string;
@@ -37,6 +39,7 @@ declare class SSRComment extends SSRNode {
37
39
  * SSR text node
38
40
  */
39
41
  declare class SSRTextNode extends SSRNode {
42
+ nodeType: number;
40
43
  text: string;
41
44
  constructor(text: string);
42
45
  get data(): string;
@@ -46,6 +49,7 @@ declare class SSRTextNode extends SSRNode {
46
49
  * SSR document fragment
47
50
  */
48
51
  declare class SSRDocumentFragment extends SSRNode {
52
+ nodeType: number;
49
53
  children: (SSRElement | string)[];
50
54
  appendChild(child: SSRElement | SSRTextNode | SSRDocumentFragment): void;
51
55
  }
@@ -7,7 +7,7 @@ import {
7
7
  installDomShim,
8
8
  removeDomShim,
9
9
  toVNode
10
- } from "../shared/chunk-zs75v8qj.js";
10
+ } from "../shared/chunk-gcwqkynf.js";
11
11
  export {
12
12
  toVNode,
13
13
  removeDomShim,
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { FallbackFontName as FallbackFontName2, FontFallbackMetrics as FontFallbackMetrics6 } from "@vertz/ui";
1
2
  /** A raw HTML string that bypasses escaping during serialization. */
2
3
  interface RawHtml {
3
4
  __raw: true;
@@ -80,7 +81,6 @@ declare function renderAssetTags(assets: AssetDescriptor[]): string;
80
81
  * Returns an empty string if the CSS is empty.
81
82
  */
82
83
  declare function inlineCriticalCss(css: string): string;
83
- import { FallbackFontName as FallbackFontName2, FontFallbackMetrics as FontFallbackMetrics5 } from "@vertz/ui";
84
84
  import { FallbackFontName, FontDescriptor, FontFallbackMetrics } from "@vertz/ui";
85
85
  /**
86
86
  * Auto-detect which system font to use as fallback base.
@@ -317,6 +317,85 @@ declare function resetSlotCounter(): void;
317
317
  declare function createSlotPlaceholder(fallback: VNode | string): VNode & {
318
318
  _slotId: number;
319
319
  };
320
+ /**
321
+ * SSR prefetch access rule evaluator.
322
+ *
323
+ * Evaluates serialized entity access rules against the current session
324
+ * to determine whether a query should be prefetched during SSR.
325
+ *
326
+ * The serialized rules come from the prefetch manifest (generated at build time).
327
+ * The session comes from the JWT decoded at request time.
328
+ */
329
+ /**
330
+ * Serialized access rule — the JSON-friendly format stored in the manifest.
331
+ * Mirrors SerializedRule from @vertz/server/auth/rules but defined here
332
+ * to avoid importing the server package into the SSR pipeline.
333
+ */
334
+ type SerializedAccessRule = {
335
+ type: "public";
336
+ } | {
337
+ type: "authenticated";
338
+ } | {
339
+ type: "role";
340
+ roles: string[];
341
+ } | {
342
+ type: "entitlement";
343
+ value: string;
344
+ } | {
345
+ type: "where";
346
+ conditions: Record<string, unknown>;
347
+ } | {
348
+ type: "all";
349
+ rules: SerializedAccessRule[];
350
+ } | {
351
+ type: "any";
352
+ rules: SerializedAccessRule[];
353
+ } | {
354
+ type: "fva";
355
+ maxAge: number;
356
+ } | {
357
+ type: "deny";
358
+ };
359
+ /**
360
+ * Minimal session shape needed for prefetch access evaluation.
361
+ * Extracted from the JWT at SSR request time.
362
+ */
363
+ type PrefetchSession = {
364
+ status: "authenticated";
365
+ roles?: string[];
366
+ entitlements?: Record<string, boolean>;
367
+ tenantId?: string;
368
+ } | {
369
+ status: "unauthenticated";
370
+ };
371
+ /**
372
+ * Convert SSRAuth (from the JWT/session resolver) to PrefetchSession
373
+ * for entity access evaluation during SSR prefetching.
374
+ */
375
+ declare function toPrefetchSession(ssrAuth: {
376
+ status: string;
377
+ user?: {
378
+ role?: string;
379
+ [key: string]: unknown;
380
+ };
381
+ } | undefined): PrefetchSession;
382
+ /**
383
+ * Evaluate a serialized access rule against the current session.
384
+ *
385
+ * Returns true if the query is eligible for prefetch (the user
386
+ * likely has access), false if it should be skipped.
387
+ *
388
+ * Design rationale for specific rule types:
389
+ * - `where` → true: row-level filter, not an access gate. The query
390
+ * always executes; it just returns fewer rows for non-owners.
391
+ * - `fva` → optimistic for authenticated users: MFA freshness is
392
+ * enforced on the actual API call. If the check fails server-side,
393
+ * the query returns an error result.
394
+ * - `deny` → false: explicitly denied operations are never prefetched.
395
+ * - Unknown types → false: fail-secure. Don't prefetch if we can't
396
+ * evaluate the rule.
397
+ */
398
+ declare function evaluateAccessRule(rule: SerializedAccessRule, session: PrefetchSession): boolean;
320
399
  import { AccessSet } from "@vertz/ui/auth";
321
400
  /**
322
401
  * Extract an AccessSet from a decoded JWT payload for SSR injection.
@@ -393,6 +472,8 @@ interface SSRModule {
393
472
  getInjectedCSS?: () => string[];
394
473
  /** Compiled routes exported from the app for build-time SSG with generateParams. */
395
474
  routes?: CompiledRoute[];
475
+ /** Code-generated API client for manifest-driven zero-discovery prefetching. */
476
+ api?: Record<string, Record<string, (...args: unknown[]) => unknown>>;
396
477
  }
397
478
  interface SSRRenderResult {
398
479
  html: string;
@@ -540,6 +621,109 @@ interface GenerateSSRHtmlOptions {
540
621
  * Generate a complete HTML document from SSR render results.
541
622
  */
542
623
  declare function generateSSRHtml(options: GenerateSSRHtmlOptions): string;
624
+ import { PrefetchManifest } from "@vertz/ui-compiler";
625
+ import { FontFallbackMetrics as FontFallbackMetrics5 } from "@vertz/ui";
626
+ import { SSRAuth } from "@vertz/ui/internals";
627
+ import { ExtractedQuery } from "@vertz/ui-compiler";
628
+ /** Serialized entity access rules from the prefetch manifest. */
629
+ type EntityAccessMap = Record<string, Partial<Record<string, SerializedAccessRule>>>;
630
+ interface SSRPrefetchManifest {
631
+ /** Route patterns present in the manifest. */
632
+ routePatterns: string[];
633
+ /** Entity access rules keyed by entity name → operation → serialized rule. */
634
+ entityAccess?: EntityAccessMap;
635
+ /** Route entries with query binding metadata for zero-discovery prefetch. */
636
+ routeEntries?: Record<string, {
637
+ queries: ExtractedQuery[];
638
+ }>;
639
+ }
640
+ interface SSRSinglePassOptions {
641
+ ssrTimeout?: number;
642
+ /** Pre-computed font fallback metrics (computed at server startup). */
643
+ fallbackMetrics?: Record<string, FontFallbackMetrics5>;
644
+ /** Auth state resolved from session cookie. */
645
+ ssrAuth?: SSRAuth;
646
+ /** Set to false to fall back to two-pass rendering. Default: true. */
647
+ prefetch?: boolean;
648
+ /** Prefetch manifest for entity access filtering. */
649
+ manifest?: SSRPrefetchManifest;
650
+ /** Session data for access rule evaluation. */
651
+ prefetchSession?: PrefetchSession;
652
+ }
653
+ /**
654
+ * Render an SSR module in a single pass via discovery-only execution.
655
+ *
656
+ * 1. Discovery: Run the app factory to capture query registrations (no stream render)
657
+ * 2. Prefetch: Await all discovered queries with timeout
658
+ * 3. Render: Create a fresh context with pre-populated cache, render once
659
+ *
660
+ * Falls back to two-pass (`ssrRenderToString`) when:
661
+ * - `prefetch: false` is set
662
+ * - A redirect is detected during discovery
663
+ */
664
+ declare function ssrRenderSinglePass(module: SSRModule, url: string, options?: SSRSinglePassOptions): Promise<SSRRenderResult>;
665
+ interface PrefetchManifestManagerOptions {
666
+ /** Absolute path to the router file. */
667
+ routerPath: string;
668
+ /** Read a file's contents. Returns undefined if file doesn't exist. */
669
+ readFile: (path: string) => string | undefined;
670
+ /** Resolve an import specifier from a given file to an absolute path. */
671
+ resolveImport: (specifier: string, fromFile: string) => string | undefined;
672
+ }
673
+ interface PrefetchManifestSnapshot {
674
+ manifest: PrefetchManifest | null;
675
+ rebuildCount: number;
676
+ lastRebuildMs: number | null;
677
+ lastRebuildAt: string | null;
678
+ }
679
+ interface PrefetchManifestManager {
680
+ /** Initial full manifest build. */
681
+ build(): void;
682
+ /** Handle a file change — incremental for components, full for router. */
683
+ onFileChange(filePath: string, sourceText: string): void;
684
+ /** Get the SSR manifest for rendering (atomic read). */
685
+ getSSRManifest(): SSRPrefetchManifest | undefined;
686
+ /** Get diagnostic snapshot for the `/__vertz_prefetch_manifest` endpoint. */
687
+ getSnapshot(): PrefetchManifestSnapshot;
688
+ }
689
+ declare function createPrefetchManifestManager(options: PrefetchManifestManagerOptions): PrefetchManifestManager;
690
+ import { ExtractedQuery as ExtractedQuery2 } from "@vertz/ui-compiler";
691
+ interface ReconstructedDescriptor {
692
+ key: string;
693
+ fetch: () => Promise<unknown>;
694
+ }
695
+ /**
696
+ * Reconstruct QueryDescriptors from manifest metadata by calling the
697
+ * real API client factories. Returns descriptors with correct `_key`
698
+ * and `_fetch` for pre-populating the SSR query cache.
699
+ *
700
+ * Skips queries that:
701
+ * - Have no entity/operation (variable references)
702
+ * - Reference entities or operations not in the API client
703
+ * - Have unresolvable where bindings (null = dynamic value)
704
+ * - Reference route params not present in the URL
705
+ */
706
+ declare function reconstructDescriptors(queries: ExtractedQuery2[], routeParams: Record<string, string>, apiClient: Record<string, Record<string, (...args: unknown[]) => unknown>> | undefined): ReconstructedDescriptor[];
707
+ /**
708
+ * SSR route matcher — matches URLs to manifest route patterns.
709
+ *
710
+ * Used by the single-pass SSR pipeline to look up which components
711
+ * and queries are expected for a given URL, enabling entity access
712
+ * filtering before discovery-only execution.
713
+ */
714
+ interface MatchedRoute {
715
+ /** The matched route pattern (e.g., '/projects/:projectId/board') */
716
+ pattern: string;
717
+ /** Extracted route parameter values (e.g., { projectId: 'abc123' }) */
718
+ params: Record<string, string>;
719
+ }
720
+ /**
721
+ * Match a URL path against a list of route patterns.
722
+ * Returns all matching patterns (layouts + page) ordered from most general to most specific.
723
+ *
724
+ * Patterns use Express-style `:param` syntax.
725
+ */
726
+ declare function matchUrlToPatterns(url: string, patterns: string[]): MatchedRoute[];
543
727
  /**
544
728
  * Serialize data to JSON with `<` escaped as `\u003c`.
545
729
  * Prevents `<\/script>` breakout and `<!--` injection in inline scripts.
@@ -590,4 +774,4 @@ declare function collectStreamChunks(stream: ReadableStream<Uint8Array>): Promis
590
774
  * @param nonce - Optional CSP nonce to add to the inline script tag.
591
775
  */
592
776
  declare function createTemplateChunk(slotId: number, resolvedHtml: string, nonce?: string): string;
593
- export { wrapWithHydrationMarkers, streamToString, ssrStorage, ssrRenderToString, ssrDiscoverQueries, setGlobalSSRTimeout, serializeToHtml, safeSerialize, resetSlotCounter, renderToStream, renderToHTMLStream, renderToHTML, renderPage, renderHeadToHtml, renderAssetTags, registerSSRQuery, rawHtml, isInSSR, inlineCriticalCss, getStreamingRuntimeScript, getSSRUrl, getSSRQueries, getGlobalSSRTimeout, getAccessSetForSSR, generateSSRHtml, extractFontMetrics, encodeChunk, detectFallbackFont, createTemplateChunk, createSlotPlaceholder, createSessionScript, createSSRHandler, createSSRDataChunk, createSSRAdapter, createAccessSetScript, collectStreamChunks, clearGlobalSSRTimeout, VNode, SessionResolver, SessionData, SSRSessionInfo, SSRRenderResult, SSRQueryEntry2 as SSRQueryEntry, SSRModule, SSRHandlerOptions, SSRDiscoverResult, RenderToStreamOptions, RenderToHTMLStreamOptions, RenderToHTMLOptions, RawHtml, PageOptions, HydrationOptions, HeadEntry, HeadCollector, GenerateSSRHtmlOptions, FontFallbackMetrics5 as FontFallbackMetrics, FallbackFontName2 as FallbackFontName, AssetDescriptor };
777
+ export { wrapWithHydrationMarkers, toPrefetchSession, streamToString, ssrStorage, ssrRenderToString, ssrRenderSinglePass, ssrDiscoverQueries, setGlobalSSRTimeout, serializeToHtml, safeSerialize, resetSlotCounter, renderToStream, renderToHTMLStream, renderToHTML, renderPage, renderHeadToHtml, renderAssetTags, registerSSRQuery, reconstructDescriptors, rawHtml, matchUrlToPatterns, isInSSR, inlineCriticalCss, getStreamingRuntimeScript, getSSRUrl, getSSRQueries, getGlobalSSRTimeout, getAccessSetForSSR, generateSSRHtml, extractFontMetrics, evaluateAccessRule, encodeChunk, detectFallbackFont, createTemplateChunk, createSlotPlaceholder, createSessionScript, createSSRHandler, createSSRDataChunk, createSSRAdapter, createPrefetchManifestManager, createAccessSetScript, collectStreamChunks, clearGlobalSSRTimeout, VNode, SessionResolver, SessionData, SerializedAccessRule, SSRSinglePassOptions, SSRSessionInfo, SSRRenderResult, SSRQueryEntry2 as SSRQueryEntry, SSRPrefetchManifest, SSRModule, SSRHandlerOptions, SSRDiscoverResult, RenderToStreamOptions, RenderToHTMLStreamOptions, RenderToHTMLOptions, ReconstructedDescriptor, RawHtml, PrefetchSession, PrefetchManifestSnapshot, PrefetchManifestManagerOptions, PrefetchManifestManager, PageOptions, MatchedRoute, HydrationOptions, HeadEntry, HeadCollector, GenerateSSRHtmlOptions, FontFallbackMetrics6 as FontFallbackMetrics, FallbackFontName2 as FallbackFontName, EntityAccessMap, AssetDescriptor };