# eQuantic.UI Build Flow This document describes the eQuantic.UI build flow, demonstrating how the framework maintains **zero external dependencies** for the consumer. ## Visual Flow ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ DEVELOPMENT (source tree) │ └─────────────────────────────────────────────────────────────────────────────┘ reconciler.ts, component.ts, etc. │ ▼ ┌──────────────────────────────────┐ │ npm run build │ (only during development) │ (eQuantic.UI.Runtime) │ └──────────────────────────────────┘ │ ▼ dist/index.js (compiled runtime) │ │ boot.ts ──────imports────────┘ │ ▼ ┌──────────────────────────────────┐ │ dotnet build │ │ (eQuantic.UI.Server) │ │ │ │ ResolveBunForServer target: │ │ ├─ Looks for Bun in: │ │ │ Runtime.Osx64/tools/bun/ │ │ │ Runtime.Win64/tools/bun/ │ │ │ Runtime.Linux64/tools/bun/ │ │ ├─ Extracts from .zip if needed │ │ └─ chmod +x (Unix) │ │ │ │ BundleRuntime target: │ │ └─ "$(_BunPath)" build boot.ts │ └──────────────────────────────────┘ │ ▼ wwwroot/runtime.js (embedded in Server.dll) │ ▼ ┌──────────────────────────────────┐ │ dotnet pack │ │ (eQuantic.UI.Server) │ └──────────────────────────────────┘ │ ▼ artifacts/packages/eQuantic.UI.Server.0.1.1.nupkg ┌─────────────────────────────────────────────────────────────────────────────┐ │ CONSUMER (client project) │ └─────────────────────────────────────────────────────────────────────────────┘ MyApp.csproj ├─ Sdk="eQuantic.UI.Sdk/0.1.1" └─ PackageReference: eQuantic.UI.Server, eQuantic.UI.Runtime │ ▼ ┌──────────────────────────────────┐ │ dotnet restore │ │ │ │ NuGet installs packages: │ │ ├─ eQuantic.UI.Sdk │ │ ├─ eQuantic.UI.Server │ │ ├─ eQuantic.UI.Runtime │ │ │ └─ (meta-package) │ │ └─ eQuantic.UI.Runtime.Osx64 │ ◄── Bun embedded here! │ └─ tools/bun/bun-darwin.zip │ └──────────────────────────────────┘ │ ▼ ┌──────────────────────────────────┐ │ dotnet build │ │ │ │ SDK.targets executes: │ │ │ │ 1. ResolveBunZipPath │ │ └─ $(PkgeQuantic_UI_Runtime_ │ │ Osx64)/tools/bun/*.zip │ │ │ │ 2. EnsureBunExtracted │ │ ├─ Unzip if needed │ │ └─ chmod +x (Unix) │ │ │ │ 3. ResolveBunPath │ │ └─ Defines $(BunPath) │ │ │ │ 4. InstallBunPackages │ │ ├─ → bun add │ │ └─ Symlink node_modules │ │ │ │ 5. CompileEQuanticUI │ │ └─ dotnet eqc.dll ... --bun │ │ "$(BunPath)" │ │ │ │ 6. CopyEQuanticRuntime │ ◄── Runtime.js deployment │ └─ Copy from Runtime package │ │ to wwwroot/_equantic/ │ │ │ │ └─ "$(BunPath)" x │ └──────────────────────────────────┘ │ ▼ wwwroot/_equantic/ ├─ runtime.js (from Runtime package) └─ *.js (compiled components) │ ▼ ┌──────────────────────────────────┐ │ dotnet run │ │ │ │ Server serves: │ │ ├─ runtime.js (from Server.dll) │ │ └─ *.js (from wwwroot/_equantic)│ └──────────────────────────────────┘ │ ▼ Browser loads application ``` ## Bun Source by Component | Component | Bun Source | | -------------------------- | --------------------------------------------------------- | | **Server** (package build) | `eQuantic.UI.Runtime.{OS}/tools/bun/` (source tree) | | **SDK** (consumer) | `$(PkgeQuantic_UI_Runtime_{OS})/tools/bun/` (NuGet cache) | ## Consumer Requirements The consumer only needs: - .NET SDK 10.0 - `dotnet restore` + `dotnet build` **No Node.js, npm, or global Bun installation required.** ## Key Files | File | Responsibility | | --------------------- | ---------------------------------------------------------------- | | `Sdk/Sdk.targets` | Resolves Bun, installs `` items, compiles components | | `Server.csproj` | Resolves Bun from source tree, bundles runtime.js | | `Runtime.{OS}.csproj` | Packages Bun executable for each platform | ## MSBuild Targets (Execution Order) ### In SDK (consumer) 1. **ResolveBunZipPath** - Finds the Bun .zip in NuGet cache 2. **EnsureBunExtracted** - Extracts the executable if needed 3. **ResolveBunPath** - Defines `$(BunPath)` for later use 4. **InstallBunPackages** - Installs `` items via `bun add` (see [BunPackage](BunPackage)) 5. **CompileEQuanticUI** - Transpiles C# → TypeScript → JavaScript 6. **CopyEQuanticRuntime** - Copies runtime.js from Runtime package to wwwroot/\_equantic/ ### In Server (development) 1. **ResolveBunForServer** - Finds Bun in source tree 2. **BundleRuntime** - Compiles boot.ts → runtime.js ## Package Architecture & Self-Containment eQuantic.UI follows a **self-contained package architecture** where each package manages its own artifacts. The SDK acts as an orchestrator, referencing other packages via NuGet's `$(Pkg*)` properties. ### Architecture Principles **Before (Problematic):** ``` SDK Package ❌ ├─ Embedded runtime.js (copied from Runtime) └─ Embedded *.cs files (copied from Components) ``` Problems: tight coupling, version conflicts, artifact duplication **After (Correct):** ``` Runtime Package ✅ └─ tools/runtime/runtime.js (self-contained) Components Package ✅ └─ tools/source/*.cs (self-contained) SDK Package ✅ └─ References other packages via $(PkgeQuantic_UI_*) ``` Benefits: decoupling, correct versioning, no duplication ### Runtime.js Deployment **1. Packaging (Development)** During `dotnet pack` of **eQuantic.UI.Runtime**: ```xml ``` The Runtime package embeds its own compiled JavaScript artifact. **2. Deployment (Consumer Build)** During `dotnet build`, the SDK's **CopyEQuanticRuntime** target executes: ```xml <_RuntimeSourcePath Condition="'$(PkgeQuantic_UI_Runtime)' != ''"> $(PkgeQuantic_UI_Runtime)/tools/runtime/runtime.js <_RuntimeSourcePath Condition="'$(_RuntimeSourcePath)' == ''"> $(MSBuildThisFileDirectory)../../eQuantic.UI.Runtime/dist/index.js <_RuntimeDestPath>$(MSBuildProjectDirectory)/$(EQuanticOutputPath)runtime.js ``` ### Components Source Deployment **1. Packaging (Development)** During `dotnet pack` of **eQuantic.UI.Components**: ```xml ``` The Components package embeds its own C# source files for compiler type resolution. **2. Compilation (Consumer Build)** During `dotnet build`, the SDK's **CompileEQuanticUI** target executes: ```xml <_StandardComponentsDir Condition="'$(PkgeQuantic_UI_Components)' != ''"> $(PkgeQuantic_UI_Components)/tools/source <_StandardComponentsDir Condition="'$(_StandardComponentsDir)' == ''"> $(MSBuildThisFileDirectory)../../eQuantic.UI.Components ``` ### Key Architectural Benefits - **Decoupling**: SDK doesn't embed artifacts from other packages - **Correct Versioning**: Consumer can use Runtime 0.1.3 + SDK 0.1.2 independently - **No Duplication**: Each artifact exists only in its source package - **Flexibility**: Packages evolve independently without tight coupling - **Clear Interface**: SDK references packages via well-defined NuGet properties (`$(Pkg*)`) - **Development Fallback**: Source tree paths work for framework development ### Runtime Single Bundle Strategy The Runtime uses **Vite's `inlineDynamicImports: true`** configuration to create a single bundle: ```typescript // eQuantic.UI.Runtime/vite.config.ts export default defineConfig({ build: { rollupOptions: { output: { inlineDynamicImports: true, // ← Creates single bundle }, }, }, }); ``` **Why Single Bundle?** - **Simplified Deployment**: Only one file to copy (runtime.js) - **No Chunk Management**: Avoids issues with separate logger-_.js, error-overlay-_.js chunks - **Reliable Distribution**: Guaranteed that all runtime features (logger, error overlay) are included - **Small Size**: ~49KB minified with all features included Without this, Vite would create separate chunks for dynamic imports, and the SDK would need to copy multiple files with hash-based names.