Dependency Management
Standards for managing npm dependencies across the Eko monorepo.
Core Rules
DEP-001: Package Location
Dependencies should be installed at the appropriate level in the monorepo.
// Root package.json - Shared across all packages
{
"dependencies": {
"zod": "^3.x", // Used everywhere
"typescript": "^5.x" // Shared tooling
},
"devDependencies": {
"vitest": "^2.x", // Shared test runner
"biome": "^1.x" // Shared linter
}
}
// packages/ai/package.json - Package-specific
{
"dependencies": {
"ai": "^6.x", // Vercel AI SDK, only used in this package
"@ai-sdk/google": "^3.x" // Provider-specific SDK
}
}
Guidelines:
| Dependency Type | Install Location |
|---|---|
| Used in 3+ packages | Root package.json |
| Used in 1-2 packages | Package package.json |
| Dev tooling (lint, test) | Root devDependencies |
| Build tooling | Root devDependencies |
| Runtime deps | Package dependencies |
Never:
- Duplicate the same version in multiple package.json files
- Install package-specific deps at root (bloats all packages)
- Use different versions of the same dep across packages
DEP-002: Version Pinning Strategy
Use appropriate version ranges based on dependency criticality.
{
"dependencies": {
// Caret (^) - Default for most deps
// Allows minor/patch updates: ^3.1.0 → 3.x.x
"zod": "^3.23.0",
// Caret-pinned - Critical framework deps
// Allow patch updates only within major
"next": "^16.1.1",
"@supabase/supabase-js": "^2.88.0",
// Tilde (~) - Patch updates only
// Use for deps with breaking minor releases
"some-unstable-lib": "~1.2.3"
}
}
Version strategy:
| Dependency Type | Strategy | Example |
|---|---|---|
| Framework (Next.js, Supabase) | Caret | "^16.1.1" |
| Type definitions | Caret | "^5.0.0" |
| Utilities (lodash, date-fns) | Caret | "^4.17.0" |
| Unstable/pre-1.0 | Tilde | "~0.9.0" |
| Security-critical | Exact | "1.2.3" |
Lock file: Always commit bun.lock for reproducible installs.
DEP-003: New Dependency Approval
New dependencies require review if they meet any of these criteria:
| Criterion | Threshold | Rationale |
|---|---|---|
| Bundle size | > 50KB | Impacts load time |
| Native bindings | Any | Deployment complexity |
| Weekly downloads | < 1,000 | Maintenance risk |
| Last update | > 1 year | Abandonment risk |
| TypeScript types | None | Type safety |
| License | Non-MIT/Apache | Legal review needed |
Before adding a dependency, check:
# Check bundle size
bunx bundlephobia-cli <package-name>
# Check package stats
bun pm info <package-name>
# Check for security issues
bun pm audit
Questions to ask:
- Can we use a smaller alternative?
- Is this functionality simple enough to implement ourselves?
- Is the package actively maintained?
- Does it have security vulnerabilities?
- What's the license?
DEP-004: Workspace Protocol
Internal package references must use the workspace protocol.
// packages/ai/package.json
{
"dependencies": {
"@eko/shared": "workspace:*", // Correct
"@eko/db": "workspace:*", // Correct
"@eko/observability": "workspace:*"
}
}
// Wrong: Referencing by version
{
"dependencies": {
"@eko/shared": "^1.0.0" // Wrong! Use workspace:*
}
}
Benefits:
- Always uses local version
- No version sync issues
- Proper monorepo linking
Dependency Update Process
Regular Updates (Monthly)
# Check for outdated packages
bun outdated
# Update patch versions
bun update
# Update specific package
bun update <package-name>
# Run full test suite after updates
bun run ci
Major Version Updates
- Read changelog for breaking changes
- Create branch for the update
- Update package and fix breaking changes
- Run full CI (
bun run ci) - Test locally (manual smoke tests)
- PR with migration notes
Forbidden Patterns
1. Floating Dependencies
// Bad: No version constraint
{
"dependencies": {
"lodash": "*" // Could get any version!
}
}
// Good: Constrained version
{
"dependencies": {
"lodash": "^4.17.21"
}
}
2. Git Dependencies (except temporary)
// Bad: Git dependency in production
{
"dependencies": {
"some-package": "github:user/repo"
}
}
// Acceptable: Temporary fix with tracking issue
{
"dependencies": {
// TODO(#123): Remove when upstream fix released
"some-package": "github:user/repo#fix-branch"
}
}
3. Duplicate Dependencies
# Check for duplicates
bun pm ls --all | grep <package-name>
# If duplicates found, dedupe
bun install
Security Updates
Automated Alerts
Dependabot is configured (.github/dependabot.yml) to:
- Check weekly for security updates
- Auto-create PRs for critical fixes
- Group minor updates
Manual Audit
# Run security audit
bun pm audit
# Review vulnerable packages
bun pm audit --json | jq '.vulnerabilities'
# Update vulnerable packages
bun update <package-name>
Response times:
- Critical: Fix within 24 hours
- High: Fix within 1 week
- Medium: Fix within 1 month
- Low: Fix in next scheduled update
Monorepo Structure
eko/
├── package.json # Root: shared deps, scripts
├── bun.lock # Lock file (always commit)
├── apps/
│ ├── web/
│ │ └── package.json # App-specific deps
│ └── worker-ingest/
│ └── package.json # Worker-specific deps
└── packages/
├── shared/
│ └── package.json # Zero external deps (pure TS)
├── db/
│ └── package.json # Supabase, Drizzle
└── ai/
└── package.json # AI SDKs
Related
- STACK.md — Technology stack decisions
- Product Bible — System overview
- Rules Index — All rules