Migration Playbook
Guide to move code from apps/* to packages/* without breaking architecture.
Migration Checklist
- Identify “shared” code (reusable by api/discord/ws).
- Choose the target package:
- business logic ->
domain-* - cross-cutting application logic ->
core - technical integration ->
infra-* - contracts/validation ->
schema
- business logic ->
- Move files and fix imports to package paths (
@gmod/...). - Remove obsolete wrappers/re-exports from
apps/api/src/.... - Ensure no package imports files from
apps/*. - Check Turbo for dependency cycles.
- Run lint + typecheck + targeted dev run.
Example: Discord Action from API
Goal: do not call Discord directly.
- Add the job/reply schema in
packages/schema/src/bullmq.ts. - Add the adapter in
packages/infra-bullmq/src/discordQueueAdapters.ts. - Implement the worker in
apps/discord/src/discord/workers/discordQueueWorkers.ts. - Replace previous direct calls in
apps/api/packages/core.
Example: Add a field to req
- Declare the field in
packages/core/src/types/express.d.ts. - Ensure
tsconfigincludes this types directory. - Set the value in middleware.
- Consume it without unsafe casts in controllers/models.
Cycle Management
If Turbo reports a cycle between domain packages:
- Move shared types/functions to a neutral package (
coreor a new dedicated package). - Avoid reciprocal dependencies (domain A
<->domain B). - Replace direct calls with contracts (schema + event/job) when needed.
Definition of Done (DoD)
- Imports point to
@gmod/*, not app file paths. - Controllers are thin, with extracted logic.
- No package cycle remains.
lint,typecheck, and targeted dev startup pass.