Tooling
ESLint configurations, domain invariant rules, and the scaffold CLI for generating CRUD domain slices.
Tooling (packages/tooling)
The tooling package contains shared ESLint configurations and the scaffold CLI. It provides the mechanical enforcement layer that keeps the codebase consistent.
ESLint Configs
The package exports several ESLint configurations under packages/tooling/eslint-config/:
Base Config (base.js)
strictTypeChecked preset from typescript-eslint with project-wide overrides.
Domain Invariants (domain-invariants.js)
Architecture and DDD layer boundary rules:
| Rule | Rationale |
|---|---|
No console.* | Use @tx-agent-kit/logging instead |
No drizzle-orm outside packages/infra/db | Database access is isolated to one package |
No effect in apps/web | The web app stays a thin client |
| No default exports in domain layers | Named exports keep imports explicit |
No as any assertions | Model unknowns explicitly and decode at boundaries |
No chained assertions (as unknown as ...) | Decode at boundaries instead of double-casting |
| No suppression directives | Fix root types rather than suppressing errors |
Code Quality (code-quality.js)
General code quality and modern JS style:
| Rule | Rationale |
|---|---|
unused-imports/no-unused-imports | Auto-remove dead imports |
curly | Braces required on all blocks |
object-shorthand | { foo } over { foo: foo } |
prefer-arrow-callback | Arrow callbacks (named functions allowed) |
prefer-rest-params | ...args over arguments |
prefer-spread | Spread over .apply() |
no-nested-ternary | Readable conditionals |
no-void | No floating void expressions |
Effect Consistency (effect-consistency.js)
Effect-specific patterns. Bans new Promise() in core/API source in favor of Effect.promise/Effect.tryPromise.
Type Safety (type-safety.js)
Exhaustive switch checks, nullish coalescing (?? over ||), optional chain, and consistent type exports.
Testing (testing.js)
Test-specific rules: vitest globals, no-only-tests/no-only-tests to prevent committed .only() calls.
Unicorn (unicorn.js)
Modern JS best practices from eslint-plugin-unicorn:
| Rule | Enforces |
|---|---|
unicorn/prefer-node-protocol | node:fs over fs |
unicorn/prefer-string-replace-all | .replaceAll() over .replace(/…/g) |
unicorn/prefer-string-slice | .slice() over .substring()/.substr() |
unicorn/prefer-array-flat-map | .flatMap() over .map().flat() |
unicorn/prefer-array-some | .some() over .filter().length |
unicorn/prefer-structured-clone | structuredClone over JSON round-trip |
unicorn/prefer-number-properties | Number.isNaN over global isNaN |
unicorn/catch-error-name | Consistent error naming in catch blocks |
unicorn/numeric-separators-style | 1_000_000 over 1000000 |
unicorn/no-useless-spread | No redundant spreads |
unicorn/no-useless-promise-resolve-reject | No return Promise.resolve(x) in async functions |
unicorn/no-abusive-eslint-disable | No blanket /* eslint-disable */ |
unicorn/prefer-optional-catch-binding | Drop unused catch (error) bindings |
Boundaries Config
Package boundary enforcement via eslint-plugin-boundaries. Prevents unauthorized cross-package imports.
Scaffold CLI
The scaffold CLI generates CRUD domain slices following the golden path:
# Preview what will be created
pnpm scaffold:crud --domain billing --entity invoice --dry-run
# Generate the domain slice
pnpm scaffold:crud --domain billing --entity invoice
# Generate with database schema additions
pnpm scaffold:crud --domain billing --entity invoice --with-dbWhat It Generates
For a domain billing with entity invoice:
packages/core/src/domains/billing/
domain/billing-domain.ts # Entity types and pure rules
ports/billing-ports.ts # Repository port contracts
application/billing-service.ts # Use-case orchestration
adapters/billing-adapters.ts # Adapter implementationsWith --with-db:
packages/infra/db/src/effect-schemas/invoices.ts
packages/infra/db/src/factories/invoices.factory.tsCLI Options
| Flag | Description |
|---|---|
--domain <name> | Domain name (e.g., billing) |
--entity <name> | Entity name (e.g., invoice) |
--plural <name> | Plural form (auto-inferred if omitted) |
--dry-run | Preview changes without writing files |
--force | Overwrite existing files |
--with-db | Also generate DB schema/factory stubs |
The CLI locates the repository root by walking up from cwd and finding the root package.json with name tx-agent-kit.