Extract logic from apps into reusable bundles or libs
This skill guides the extraction of business logic from packages/apps/ (or misplaced locations) into reusable packages/bundles/ or packages/libs/, ensuring the code becomes multi-app ready with proper logging and analytics.
Invoke when:
packages/apps/ (flagged by /audit-health or post-edit-checks hook)Read the source file(s) and identify:
Analysis:
- Source: packages/apps/web-application/src/lib/projectService.ts
- Exports: createProject, updateProject, deleteProject, ProjectService class
- Consumers: 3 files in packages/apps/web-application/src/app/
- Dependencies: @contractspec/lib.contracts, prisma, zod
- Side effects: Database writes, external API calls
Use the package-architecture heuristics to decide where the code should live:
| Code type | Target | Example |
|---|---|---|
| Business logic (domain-specific) | packages/bundles/<bundle>/src/modules/<domain>/ | Project CRUD operations |
| Business UI components | packages/bundles/<bundle>/src/presentation/<domain>/ | ProjectCard, ProjectForm |
| Pure utilities (no business deps) | packages/libs/utils-typescript/src/ | formatCurrency, slugify |
| Shared types/schemas | packages/libs/contracts-*/src/ | ProjectSchema, UserType |
| Infrastructure adapters | packages/bundles/<bundle>/src/infrastructure/ | PrismaProjectRepo |
| Reusable hooks | packages/bundles/<bundle>/src/presentation/<domain>/ | useProjectData |
Ask the user to confirm the target location before proceeding.
index.ts barrel file exists in the target module<feature>.service.tstypes.tsuse<Feature>.ts<Feature>.tsx<name>.util.tsMove the code to the new location and enhance it:
logger.info at operation start/endlogger.error in catch blocksanalytics.track for significant operationsindex.tsFor each consumer of the original code:
// Before
import { createProject } from '@/lib/projectService';
// After
import { createProject } from '@contractspec/bundle.studio/modules/project';
// packages/apps/web-application/src/lib/projectService.ts
/**
* @deprecated Import from @contractspec/bundle.studio/modules/project instead.
* This re-export will be removed in the next major version.
*/
export {
createProject,
updateProject,
deleteProject,
} from '@contractspec/bundle.studio/modules/project';
<feature>.test.ts next to the service fileRun the following checks in order:
# 1. Type check
turbo build:types
# 2. Lint
turbo lint
# 3. Tests
turbo test
# 4. Build
turbo build
Also verify:
packages/apps/web-application/src/lib/
└── projectService.ts (180 lines, mixed concerns)
packages/bundles/contractspec-studio/src/modules/project/
├── index.ts # Barrel exports
├── types.ts # ProjectInput, ProjectOutput types
├── project.service.ts # Business logic with logging + analytics
└── project.test.ts # Tests with observability assertions
packages/apps/web-application/src/lib/
└── projectService.ts # Re-export with @deprecated JSDoc
any)After extraction, report: