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 TypeInstall Location
Used in 3+ packagesRoot package.json
Used in 1-2 packagesPackage package.json
Dev tooling (lint, test)Root devDependencies
Build toolingRoot devDependencies
Runtime depsPackage 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 TypeStrategyExample
Framework (Next.js, Supabase)Caret"^16.1.1"
Type definitionsCaret"^5.0.0"
Utilities (lodash, date-fns)Caret"^4.17.0"
Unstable/pre-1.0Tilde"~0.9.0"
Security-criticalExact"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:

CriterionThresholdRationale
Bundle size> 50KBImpacts load time
Native bindingsAnyDeployment complexity
Weekly downloads< 1,000Maintenance risk
Last update> 1 yearAbandonment risk
TypeScript typesNoneType safety
LicenseNon-MIT/ApacheLegal 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:

  1. Can we use a smaller alternative?
  2. Is this functionality simple enough to implement ourselves?
  3. Is the package actively maintained?
  4. Does it have security vulnerabilities?
  5. 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

  1. Read changelog for breaking changes
  2. Create branch for the update
  3. Update package and fix breaking changes
  4. Run full CI (bun run ci)
  5. Test locally (manual smoke tests)
  6. 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