ali-ahnaf / ali-ahnaf/pocket_pixel
Introduce NanoDI dependency injection container in the API workspace
- 主要语言
- TypeScript
- 星标
- 14
- 派生
- 91
- PR 合并指标
- 30 天内没有已合并 PR
描述
### 📌 Context / background
Right now the API in `packages/api` wires its dependencies by hand. Every service and repository is created once with `new` and exported as a shared singleton from two files:
- `packages/api/src/services/index.ts` — ~18 `new SomeService()` lines
- `packages/api/src/repositories/index.ts` — ~11 `new SomeRepository()` lines
Each service then pulls its dependencies through constructor parameters that **default to those singletons**, e.g. in `packages/api/src/services/transactions.service.ts`:
```ts
constructor(
private readonly transactions: TransactionsRepository = transactionsRepository,
private readonly vaults = vaultsRepository,
) {}
```
This works, but wiring order is manual and fragile: a new dependency means editing the index file, and the default-parameter pattern couples every service file to the singleton graph. [NanoDI](https://github.com/andersnm/nanodi) is a tiny, decorator-free DI container for TypeScript/Node that can register these classes and resolve the graph for us — a natural fit for the existing `route → service → repository → entity` layering described in `CLAUDE.md`.
> 🧩 **Dependency injection (DI)** = instead of a class building its own dependencies, a central "container" creates them and hands them in. Makes wiring explicit and swapping in test mocks trivial.
### 🎯 Problem / goal
Replace the manual singleton wiring with a NanoDI container so that:
- Services and repositories are **registered once** with the container.
- Consumers (routes, scheduler, tests) resolve instances from the container instead of importing hand-built singletons.
- Unit tests can register mock repositories without relying on default constructor parameters.
### 🛠️ Suggested approach
Start small — do **not** convert every service in one PR. Pick 1–2 services (e.g. `TransactionsService` + `TransactionsRepository`) as a pilot, prove the pattern, then follow up.
1. **Add the dependency** to the API workspace: `npm install nanodi -w packages/api`. Confirm it ships types and works with this repo's CommonJS/ts-node setup.
2. **Create a container module**, e.g. `packages/api/src/container.ts`, that registers repositories and services with NanoDI. Look at how `packages/api/src/services/index.ts` and `packages/api/src/repositories/index.ts` build the graph today and reproduce it as container registrations.
3. **Resolve from the container** at the composition root. Check where the current singletons are imported (routes under `packages/api/src/routes`, the scheduler in `packages/api/src/scheduler/recurring-scheduler.ts`, and `packages/api/src/index.ts`) and switch the pilot service's consumers to resolve it from the container.
4. **Keep the constructor-injection shape.** NanoDI should supply the dependencies the constructor currently defaults to; the default-parameter fallbacks can stay for now so existing tests keep passing during migration.
5. **Update the pilot service's unit test** (`packages/api/src/tests`) to register mocks via the container instead of passing them positionally.
6. **Document the pattern** — add a short note to `CLAUDE.md` under the "API request flow" section describing how to register a new service/repository with the container, so the next contributor follows the DI path, not the old singleton path.
⚠️ Follow the repo rule: no `try/catch` in routes, no business logic moved into wiring, and run `npm run test:api` after the change.
### ✅ Acceptance criteria
- [ ] `nanodi` added as a dependency of `packages/api`.
- [ ] A container module registers the pilot service(s) and their repositories.
- [ ] The pilot service is resolved from the container at its consumers (route/scheduler), not from the hand-built singleton.
- [ ] The pilot service's unit test uses the container to inject mocks and still passes.
- [ ] `npm run test:api` is green.
- [ ] `CLAUDE.md` documents how to register a new service/repository with NanoDI.
- [ ] PR describes what changed and notes this is a pilot, with follow-up issues for migrating the remaining services.
贡献指南
这个仓库没有索引到贡献指南
评估
这个 Issue 还没有评估数据。