eQuantic.UIeQuantic.UI
Docs
Playground
GitHub
DocsServer
BunPackage: npm Packages via .csproj
Edit this page
2 min read
🌐 This page in: English · Português
eQuantic.UI allows declaring npm package dependencies directly in .csproj files, keeping the developer experience 100% .NET with zero package.json, zero npm, and zero Node.js.
Quick Start
1
2
3
4
<!-- MyApp.csproj -->
<ItemGroup>
<BunPackage Include="dayjs" Version="1.11.13" />
</ItemGroup>
That's it. On dotnet build, the SDK automatically:
1.
Generates a temporary package.json in obj/eQuantic/npm/
2.
Installs packages using the embedded Bun runtime
3.
Creates a node_modules symlink for tool resolution
4.
Skips installation on incremental builds
How It Works
Build Pipeline
1
2
3
4
5
6
7
8
9
10
11
12
13
dotnet build
├── 1. ResolveBunPath ← Extracts embedded Bun from NuGet package
├── 2. InstallBunPackages ← NEW: Installs <BunPackage> items
│ ├── Creates obj/eQuantic/npm/package.json
│ ├── Runs: bun add <package>@<version>
│ └── Symlinks: node_modules → obj/eQuantic/npm/node_modules/
├── 3. CompileEQuanticUI ← C# → TypeScript → JavaScript
├── 4. CopyEQuanticRuntime ← Copies runtime.js
File Layout
1
2
3
4
5
6
7
8
9
10
11
MyApp/
├── MyApp.csproj ← BunPackage declared here
├── node_modules/ ← Symlink (gitignored)
│ └── → obj/eQuantic/npm/node_modules/
├── obj/
│ └── eQuantic/
│ └── npm/ ← Hidden from developer
│ ├── package.json ← Auto-generated
│ ├── bun.lock ← Auto-generated
│ └── node_modules/ ← Real packages
└── src/
The developer never sees or touches package.json. The node_modules symlink is gitignored and auto-created.
Usage Examples
Multiple Packages
Multiple BunPackage items are supported. Each runs as a separate bun add:
1
2
3
4
<ItemGroup>
<BunPackage Include="dayjs" Version="1.11.13" />
<BunPackage Include="marked" Version="15.0.6" />
</ItemGroup>
CSS-Only Packages
Works equally well with CSS-only packages imported via @import:
1
2
3
<ItemGroup>
<BunPackage Include="tw-animate-css" Version="1.2.5" />
</ItemGroup>
1
2
/* src/styles.css */
@import "tw-animate-css";
MSBuild Target Details
The InstallBunPackages target lives in Sdk.targets:
1
2
3
4
<Target Name="InstallBunPackages"
AfterTargets="ResolveBunPath"
BeforeTargets="CompileEQuanticUI"
Condition="'@(BunPackage)' != '' And '$(BunPath)' != ''">
Key Behaviors
Behavior
Details
Incremental
Skips if obj/eQuantic/npm/node_modules/ already exists
Clean build
Runs bun add for each package on first build or after dotnet clean
Cross-platform
Symlink on macOS/Linux, mklink /D on Windows
Isolation
Packages live in obj/, not project root
No pollution
No package.json, bun.lockb, or node_modules committed to git
Forcing Reinstall
To force a fresh install (e.g., after changing versions):
1
2
3
4
5
6
# Option 1: Delete the npm cache
rm -rf obj/eQuantic/npm
# Option 2: Full clean
dotnet clean
dotnet build
Design Decisions
Why not generate package.json at project root?
Pollutes the .NET project with npm artifacts
Developers might accidentally commit it
Confuses IDEs into treating it as a Node.js project
Violates the "100% .NET" principle
Why symlink instead of NODE_PATH?
Symlinks are universally supported by the tools that resolve node_modules
NODE_PATH has inconsistent behavior across tools
The symlink is transparent: if a tool looks for node_modules/, it finds them
Why bun add instead of bun install?
bun add works with a minimal {"private": true} package.json
MSBuild item batching (%(BunPackage.Identity)) naturally maps to individual bun add calls
Each package is installed with its exact version
Why not use bun x --install?
bun x is for running CLI tools, not for installing libraries
Packages referenced in CSS (@plugin, @import) need to exist in node_modules/
bun add is the correct semantic for "install this library"
Comparison
Approach
package.json needed
npm/Node.js needed
Developer experience
Traditional npm
Yes
Yes
Must manage two ecosystems
BunPackage
No
No
Pure .NET, zero friction
Troubleshooting
Packages not updating after version change
Cause: node_modules already exists, so InstallBunPackages skips
Fix:
1
2
rm -rf obj/eQuantic/npm
dotnet build
Symlink permission error on Windows
Cause: Creating symlinks on Windows requires elevated permissions or Developer Mode
Fix: Enable Developer Mode in Windows Settings, or run terminal as Administrator
Related Documentation
Build Flow: Complete MSBuild target execution order
Package Architecture: Self-contained package design
Asset Management: Component asset dependencies