-
Notifications
You must be signed in to change notification settings - Fork 1
BunPackage
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.
<!-- MyApp.csproj -->
<ItemGroup>
<BunPackage Include="tailwindcss-animate" Version="1.0.7" />
</ItemGroup>That's it. On dotnet build, the SDK automatically:
- Generates a temporary
package.jsoninobj/eQuantic/npm/ - Installs packages using the embedded Bun runtime
- Creates a
node_modulessymlink for tool resolution - Skips installation on incremental builds
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
│
└── 5. BuildCSS (Tailwind) ← Generates CSS (can resolve installed packages)
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/
└── styles.css ← @plugin "tailwindcss-animate" works!
The developer never sees or touches package.json. The node_modules symlink is gitignored and auto-created.
The most common use case — installing Tailwind plugins referenced via @plugin in your CSS:
<ItemGroup>
<BunPackage Include="tailwindcss-animate" Version="1.0.7" />
</ItemGroup>/* src/styles.css */
@import "tailwindcss";
@plugin "tailwindcss-animate";Multiple BunPackage items are supported. Each runs as a separate bun add:
<ItemGroup>
<BunPackage Include="tailwindcss-animate" Version="1.0.7" />
<BunPackage Include="@tailwindcss/typography" Version="0.5.10" />
</ItemGroup>Works equally well with CSS-only packages imported via @import:
<ItemGroup>
<BunPackage Include="tw-animate-css" Version="1.2.5" />
</ItemGroup>/* src/styles.css */
@import "tailwindcss";
@import "tw-animate-css";The InstallBunPackages target lives in Sdk.targets:
<Target Name="InstallBunPackages"
AfterTargets="ResolveBunPath"
BeforeTargets="CompileEQuanticUI"
Condition="'@(BunPackage)' != '' And '$(BunPath)' != ''">| 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 |
To force a fresh install (e.g., after changing versions):
# Option 1: Delete the npm cache
rm -rf obj/eQuantic/npm
# Option 2: Full clean
dotnet clean
dotnet build- 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
- Symlinks are universally supported by all tools (Tailwind CLI, PostCSS, etc.)
-
NODE_PATHhas inconsistent behavior across tools - The symlink is transparent — if a tool looks for
node_modules/, it finds them
-
bun addworks with a minimal{"private": true}package.json - MSBuild item batching (
%(BunPackage.Identity)) naturally maps to individualbun addcalls - Each package is installed with its exact version
-
bun xis for running CLI tools, not for installing libraries - Packages referenced in CSS (
@plugin,@import) need to exist innode_modules/ -
bun addis the correct semantic for "install this library"
| 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 |
Symptom: Tailwind CLI can't find a plugin referenced in CSS
Cause: node_modules symlink missing or broken
Fix:
rm -rf obj/eQuantic/npm node_modules
dotnet buildCause: node_modules already exists, so InstallBunPackages skips
Fix:
rm -rf obj/eQuantic/npm
dotnet buildCause: Creating symlinks on Windows requires elevated permissions or Developer Mode
Fix: Enable Developer Mode in Windows Settings, or run terminal as Administrator
- Build Flow — Complete MSBuild target execution order
- Package Architecture — Self-contained package design
- Asset Management — Component asset dependencies