@vertz/ui-server 0.2.25 → 0.2.26

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.
@@ -9,7 +9,7 @@ import {
9
9
 
10
10
  // src/bun-dev-server.ts
11
11
  import { execSync } from "child_process";
12
- import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, watch as watch2, writeFileSync as writeFileSync2 } from "fs";
12
+ import { existsSync as existsSync2, mkdirSync, readdirSync as readdirSync2, readFileSync as readFileSync2, watch as watch2, writeFileSync as writeFileSync2 } from "fs";
13
13
  import { dirname, normalize, resolve } from "path";
14
14
 
15
15
  // src/debug-logger.ts
@@ -644,6 +644,186 @@ function escapeAttr(s) {
644
644
  return s.replace(/[&"'<>]/g, (c) => `&#${c.charCodeAt(0)};`);
645
645
  }
646
646
 
647
+ // src/ssr-aot-manifest-dev.ts
648
+ import { compileForSSRAot } from "@vertz/ui-compiler";
649
+
650
+ // src/ssr-aot-diagnostics.ts
651
+ var MAX_DIVERGENCES = 20;
652
+
653
+ class AotDiagnostics {
654
+ _components = new Map;
655
+ _divergences = [];
656
+ recordCompilation(components) {
657
+ for (const comp of components) {
658
+ this._components.set(comp.name, {
659
+ tier: comp.tier,
660
+ holes: comp.holes
661
+ });
662
+ }
663
+ }
664
+ recordDivergence(component, aotHtml, domHtml) {
665
+ this._divergences.push({
666
+ component,
667
+ aotHtml,
668
+ domHtml,
669
+ timestamp: new Date().toISOString()
670
+ });
671
+ if (this._divergences.length > MAX_DIVERGENCES) {
672
+ this._divergences = this._divergences.slice(this._divergences.length - MAX_DIVERGENCES);
673
+ }
674
+ }
675
+ clear() {
676
+ this._components.clear();
677
+ this._divergences = [];
678
+ }
679
+ clearComponents() {
680
+ this._components.clear();
681
+ }
682
+ getClassificationLog() {
683
+ const lines = [];
684
+ for (const [name, comp] of this._components) {
685
+ let line = `${name}: ${comp.tier}`;
686
+ if (comp.holes.length > 0) {
687
+ line += `, ${comp.holes.length} hole${comp.holes.length > 1 ? "s" : ""} (${comp.holes.join(", ")})`;
688
+ }
689
+ lines.push(line);
690
+ }
691
+ const snapshot = this.getSnapshot();
692
+ const { total, aot, percentage } = snapshot.coverage;
693
+ if (total > 0) {
694
+ lines.push(`Coverage: ${aot}/${total} components (${percentage}%)`);
695
+ }
696
+ return lines;
697
+ }
698
+ getSnapshot() {
699
+ let aot = 0;
700
+ let runtime = 0;
701
+ for (const comp of this._components.values()) {
702
+ if (comp.tier === "runtime-fallback") {
703
+ runtime++;
704
+ } else {
705
+ aot++;
706
+ }
707
+ }
708
+ const total = aot + runtime;
709
+ return {
710
+ components: Object.fromEntries(this._components),
711
+ coverage: {
712
+ total,
713
+ aot,
714
+ runtime,
715
+ percentage: total === 0 ? 0 : Math.round(aot / total * 100)
716
+ },
717
+ divergences: [...this._divergences]
718
+ };
719
+ }
720
+ }
721
+
722
+ // src/ssr-aot-manifest-dev.ts
723
+ function createAotManifestManager(options) {
724
+ const { readFile: readFile2, listFiles } = options;
725
+ let currentManifest = null;
726
+ const diagnostics = new AotDiagnostics;
727
+ let rebuildCount = 0;
728
+ let lastRebuildMs = null;
729
+ let lastRebuildAt = null;
730
+ function compileFile(filePath, source) {
731
+ try {
732
+ const result = compileForSSRAot(source, { filename: filePath });
733
+ return result.components.map((comp) => ({
734
+ name: comp.name,
735
+ entry: {
736
+ tier: comp.tier,
737
+ holes: comp.holes,
738
+ file: filePath
739
+ }
740
+ }));
741
+ } catch {
742
+ return [];
743
+ }
744
+ }
745
+ function updateDiagnostics(manifest, isFullBuild) {
746
+ if (isFullBuild) {
747
+ diagnostics.clear();
748
+ } else {
749
+ diagnostics.clearComponents();
750
+ }
751
+ const entries = Object.entries(manifest.components).map(([name, entry]) => ({
752
+ name,
753
+ tier: entry.tier,
754
+ holes: entry.holes
755
+ }));
756
+ diagnostics.recordCompilation(entries);
757
+ }
758
+ function fullBuild() {
759
+ const start = performance.now();
760
+ const files = listFiles();
761
+ const components = {};
762
+ for (const filePath of files) {
763
+ if (!filePath.endsWith(".tsx"))
764
+ continue;
765
+ const source = readFile2(filePath);
766
+ if (!source)
767
+ continue;
768
+ const entries = compileFile(filePath, source);
769
+ for (const { name, entry } of entries) {
770
+ components[name] = entry;
771
+ }
772
+ }
773
+ currentManifest = { components };
774
+ updateDiagnostics(currentManifest, true);
775
+ rebuildCount++;
776
+ lastRebuildMs = Math.round(performance.now() - start);
777
+ lastRebuildAt = new Date().toISOString();
778
+ }
779
+ function incrementalUpdate(filePath, sourceText) {
780
+ if (!currentManifest)
781
+ return;
782
+ const start = performance.now();
783
+ const newComponents = { ...currentManifest.components };
784
+ for (const [name, entry] of Object.entries(newComponents)) {
785
+ if (entry.file === filePath) {
786
+ delete newComponents[name];
787
+ }
788
+ }
789
+ if (sourceText.trim()) {
790
+ const entries = compileFile(filePath, sourceText);
791
+ for (const { name, entry } of entries) {
792
+ newComponents[name] = entry;
793
+ }
794
+ }
795
+ currentManifest = { components: newComponents };
796
+ updateDiagnostics(currentManifest, false);
797
+ rebuildCount++;
798
+ lastRebuildMs = Math.round(performance.now() - start);
799
+ lastRebuildAt = new Date().toISOString();
800
+ }
801
+ return {
802
+ build() {
803
+ fullBuild();
804
+ },
805
+ onFileChange(filePath, sourceText) {
806
+ if (!filePath.endsWith(".tsx"))
807
+ return;
808
+ incrementalUpdate(filePath, sourceText);
809
+ },
810
+ getManifest() {
811
+ return currentManifest;
812
+ },
813
+ getSnapshot() {
814
+ return {
815
+ manifest: currentManifest,
816
+ rebuildCount,
817
+ lastRebuildMs,
818
+ lastRebuildAt
819
+ };
820
+ },
821
+ getDiagnostics() {
822
+ return diagnostics;
823
+ }
824
+ };
825
+ }
826
+
647
827
  // src/ssr-prefetch-dev.ts
648
828
  import {
649
829
  analyzeComponentQueries,
@@ -2726,6 +2906,18 @@ function clearSSRRequireCache() {
2726
2906
  }
2727
2907
  return keys.length;
2728
2908
  }
2909
+ function collectFiles(dir) {
2910
+ const files = [];
2911
+ for (const entry of readdirSync2(dir, { withFileTypes: true })) {
2912
+ const fullPath = resolve(dir, entry.name);
2913
+ if (entry.isDirectory()) {
2914
+ files.push(...collectFiles(fullPath));
2915
+ } else {
2916
+ files.push(fullPath);
2917
+ }
2918
+ }
2919
+ return files;
2920
+ }
2729
2921
  function createBunDevServer(options) {
2730
2922
  const {
2731
2923
  entry,
@@ -2756,6 +2948,7 @@ function createBunDevServer(options) {
2756
2948
  mkdirSync(devDir, { recursive: true });
2757
2949
  const logger = createDebugLogger(devDir);
2758
2950
  const diagnostics = new DiagnosticsCollector;
2951
+ let aotManifestManager = null;
2759
2952
  let server = null;
2760
2953
  let srcWatcherRef = null;
2761
2954
  let refreshTimeout = null;
@@ -3170,6 +3363,36 @@ function createBunDevServer(options) {
3170
3363
  prefetchManager = null;
3171
3364
  }
3172
3365
  }
3366
+ aotManifestManager = createAotManifestManager({
3367
+ readFile: (path) => {
3368
+ try {
3369
+ return readFileSync2(path, "utf-8");
3370
+ } catch {
3371
+ return;
3372
+ }
3373
+ },
3374
+ listFiles: () => {
3375
+ try {
3376
+ return collectFiles(srcDir);
3377
+ } catch {
3378
+ return [];
3379
+ }
3380
+ }
3381
+ });
3382
+ try {
3383
+ const aotStart = performance.now();
3384
+ aotManifestManager.build();
3385
+ const aotMs = Math.round(performance.now() - aotStart);
3386
+ logger.log("aot", "initial-build", { durationMs: aotMs });
3387
+ if (logRequests) {
3388
+ const manifest = aotManifestManager.getManifest();
3389
+ const count = manifest ? Object.keys(manifest.components).length : 0;
3390
+ console.log(`[Server] AOT manifest built (${count} components, ${aotMs}ms)`);
3391
+ }
3392
+ } catch (e) {
3393
+ console.warn("[Server] Failed to build AOT manifest:", e instanceof Error ? e.message : e);
3394
+ aotManifestManager = null;
3395
+ }
3173
3396
  mkdirSync(devDir, { recursive: true });
3174
3397
  const frInitPath = resolve(devDir, "fast-refresh-init.ts");
3175
3398
  writeFileSync2(frInitPath, `import '@vertz/ui-server/fast-refresh-runtime';
@@ -3260,6 +3483,12 @@ if (import.meta.hot) import.meta.hot.accept();
3260
3483
  if (pathname === "/__vertz_diagnostics") {
3261
3484
  return Response.json(diagnostics.getSnapshot());
3262
3485
  }
3486
+ if (pathname === "/__vertz_ssr_aot") {
3487
+ if (!aotManifestManager) {
3488
+ return Response.json({ error: "AOT manifest manager not available" }, { status: 404 });
3489
+ }
3490
+ return Response.json(aotManifestManager.getDiagnostics().getSnapshot());
3491
+ }
3263
3492
  if (pathname === "/__vertz_prefetch_manifest") {
3264
3493
  if (!prefetchManager) {
3265
3494
  return Response.json({ error: "No prefetch manifest available (router file not found)" }, { status: 404 });
@@ -3687,7 +3916,20 @@ data: {}
3687
3916
  isRouter: changedFilePath === routerPath
3688
3917
  });
3689
3918
  }
3690
- } catch {}
3919
+ if (aotManifestManager) {
3920
+ const aotStart = performance.now();
3921
+ aotManifestManager.onFileChange(changedFilePath, source);
3922
+ const aotMs = Math.round(performance.now() - aotStart);
3923
+ logger.log("aot", "rebuild", {
3924
+ file: lastChangedFile,
3925
+ durationMs: aotMs
3926
+ });
3927
+ }
3928
+ } catch {
3929
+ if (aotManifestManager) {
3930
+ aotManifestManager.onFileChange(changedFilePath, "");
3931
+ }
3932
+ }
3691
3933
  }
3692
3934
  if (stopped)
3693
3935
  return;
@@ -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" | "prefetch" | "ssr" | "watcher" | "ws";
3
+ type DebugCategory = "aot" | "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;