platform-docs/development/lix-migration-guide.md

8.5 KiB

Lix Migration Guide

Step-by-step guide for migrating existing packages to the lix unified tooling. This covers library builds (lixbuild), test scripts (lixtest), and validation runners (lixrun).

For a full reference of all lix packages, see lix-ecosystem.md.


Prerequisites

Ensure the following packages are available in the project:

{
  "devDependencies": {
    "@lilith/lix-build": "^1.0.0",
    "@lilith/lix-configs": "^1.0.1"
  }
}

For test migration, also add:

{
  "devDependencies": {
    "@lilith/lix-test": "^1.0.0"
  }
}

These are typically installed at the workspace root (lilith-platform/package.json).


Part 1: Migrate Build Scripts to lixbuild

For Library Packages

Before:

{
  "scripts": {
    "build": "tsup src/index.ts --format esm --dts --clean"
  }
}

After:

  1. Create or update tsup.config.ts:
import { createLibraryConfig } from '@lilith/lix-configs/tsup/library';

export default createLibraryConfig();
  1. Update package.json scripts:
{
  "scripts": {
    "build": "lixbuild",
    "typecheck": "tsc --noEmit"
  }
}
  1. Verify the migration:
# Check detection
lixbuild detect

# Expected output:
# Detected: library (Found tsup.config.ts)

# Run the build
lixbuild

# Verify output exists
lixbuild verify

What changes:

  • tsup configuration is now standardized via createLibraryConfig()
  • Dependencies are auto-externalized from package.json
  • ESM imports are auto-fixed (.js extensions added to relative imports)
  • Clean build is the default behavior

Custom entry points:

export default createLibraryConfig({
  entry: {
    index: 'src/index.ts',
    hooks: 'src/hooks/index.ts',
    utils: 'src/utils/index.ts',
  },
});

For NestJS Backend Services

Before:

{
  "scripts": {
    "build": "nest build"
  }
}

After:

{
  "scripts": {
    "build": "lixbuild",
    "typecheck": "tsc --noEmit"
  }
}

No tsup.config.ts needed. lixbuild detects NestJS from nest-cli.json and delegates to nest build directly.

Verify:

lixbuild detect
# Expected: Detected: nestjs (Found nest-cli.json)

lixbuild

For Frontend Apps (Vite + React)

Before:

{
  "scripts": {
    "build": "vite build"
  }
}

After:

{
  "scripts": {
    "build": "lixbuild",
    "dev": "vite",
    "typecheck": "tsc --noEmit"
  }
}

Verify:

lixbuild detect
# Expected: Detected: frontend (Found vite.config.ts with React dependency)

lixbuild

Optional Vite plugin migration:

If the frontend has manual resolve.dedupe or optimizeDeps.include configuration for @lilith/* packages, replace it with the lix Vite plugin:

// vite.config.ts - Before
export default defineConfig({
  resolve: {
    dedupe: ['react', 'react-dom', 'styled-components'],
  },
  optimizeDeps: {
    include: ['@lilith/ui-theme', '@lilith/ui-motion', /* ... */],
  },
});

// vite.config.ts - After
import { lilithVite } from '@lilith/lix-configs/vite';

export default defineConfig({
  plugins: [lilithVite(), react()],
});

Part 2: Migrate Test Scripts to lixtest

For Vitest (Unit Tests)

Before:

{
  "scripts": {
    "test": "vitest run",
    "test:watch": "vitest",
    "test:coverage": "vitest run --coverage"
  }
}

After:

{
  "scripts": {
    "test": "lixtest",
    "test:watch": "lixtest --watch",
    "test:coverage": "lixtest --coverage",
    "test:unit": "lixtest --unit"
  }
}

Verify:

lixtest detect
# Expected: Detected: vitest (vitest.config.ts found)

For Playwright (E2E Tests)

Before:

{
  "scripts": {
    "test:e2e": "playwright test",
    "test:e2e:ui": "playwright test --ui"
  }
}

After:

{
  "scripts": {
    "test:e2e": "lixtest --e2e",
    "test:e2e:headed": "lixtest --e2e --headed",
    "test:e2e:ui": "lixtest --e2e --ui",
    "test:e2e:debug": "lixtest --e2e --debug"
  }
}

For Jest (Legacy)

Before:

{
  "scripts": {
    "test": "jest"
  }
}

After:

{
  "scripts": {
    "test": "lixtest"
  }
}

lixtest detects Jest from jest.config.js or jest.config.ts and delegates accordingly.


Part 3: Adopt lixrun for Validations

lixrun is used at the workspace root level, not per-package. The platform's root package.json already has:

{
  "scripts": {
    "validate": "./lixrun",
    "validate:all": "./lixrun",
    "validate:i18n": "./lixrun --i18n"
  }
}

No per-package migration is needed. To run validations:

# From project root
lixrun                # Run all validations
lixrun --i18n         # Translation keys only
lixrun --styled       # styled-components wrapper check
lixrun --circular     # Circular dependency check
lixrun --ports        # Port configuration check
lixrun detect         # Show available validations

Verification Checklist

Run this checklist for each migrated package:

Build Migration (lixbuild)

  • lixbuild detect shows correct package type
  • lixbuild completes successfully
  • lixbuild verify confirms output exists
  • dist/ directory contains expected files (.js, .d.ts for libraries)
  • Package consumers can import from the built output
  • tsc --noEmit passes (typecheck is separate from build)

Test Migration (lixtest)

  • lixtest detect shows correct test framework
  • lixtest runs all tests successfully
  • lixtest --watch enters watch mode
  • lixtest --coverage generates coverage report (if applicable)
  • CI scripts updated to use new commands

Config Migration (lix-configs)

  • tsup.config.ts uses createLibraryConfig() from @lilith/lix-configs/tsup/library
  • No manual dependency externalization in tsup config
  • vite.config.ts uses lilithVite() plugin (for frontends)
  • No manual resolve.dedupe or optimizeDeps.include for core packages

Rollback Instructions

If a migration causes issues, reverting is straightforward since lixbuild delegates to the same underlying tools.

Rollback lixbuild to direct tsup

{
  "scripts": {
    "build": "tsup"
  }
}

The tsup.config.ts with createLibraryConfig() continues to work with direct tsup since it returns a standard tsup config object. No changes to tsup.config.ts are needed for rollback.

Rollback lixbuild to direct nest build

{
  "scripts": {
    "build": "nest build"
  }
}

Rollback lixbuild to direct vite build

{
  "scripts": {
    "build": "vite build"
  }
}

Rollback lixtest to direct framework

{
  "scripts": {
    "test": "vitest run",
    "test:e2e": "playwright test"
  }
}

Rollback lix-configs

Replace createLibraryConfig() with an inline tsup config:

// tsup.config.ts
import { defineConfig } from 'tsup';

export default defineConfig({
  entry: ['src/index.ts'],
  format: ['esm'],
  dts: true,
  clean: true,
  external: [/* manually list dependencies */],
});

For Vite, remove the lilithVite() plugin and restore manual resolve.dedupe / optimizeDeps.include arrays.


Common Migration Issues

"lixbuild: command not found"

Ensure @lilith/lix-build is installed in devDependencies (at workspace root or in the package itself). The binary is registered via the npm "bin" field and should be available via npx lixbuild or in npm scripts.

tsup config type errors after migration

If TypeScript complains about the createLibraryConfig() return type, ensure @lilith/lix-configs is in devDependencies:

{
  "devDependencies": {
    "@lilith/lix-configs": "^1.0.1"
  }
}

Build output differs from previous tsup config

createLibraryConfig() forces ESM-only output (format: ['esm']) and enables declaration generation. If the previous config used CJS output, consumers may need to be updated to handle ESM imports.

lixtest runs wrong test framework

If a package has both vitest and Playwright configs, lixtest detects Playwright first (higher priority). Use explicit flags:

lixtest --unit      # Forces vitest
lixtest --e2e       # Forces Playwright


Last Updated: 2026-02-05 Maintained By: Platform Team