Files
optima/.github/copilot-instructions.md
T
2026-02-17 21:53:14 -06:00

80 lines
8.1 KiB
Markdown

# Copilot / AI Agent Instructions for ttscm-api
Purpose: make AI coding agents immediately productive in this repository by describing architecture, conventions, workflows, and helpful code pointers.
-- **Big picture**: This is a TypeScript API service (runs on Bun) using the Hono framework. The HTTP surface is implemented in `src/api` where small router files are mounted on a versioned router in `src/api/server.ts` (see the `/v1` mount). Typical request flow is:
- `router` (in `src/api/routers/*`) → `controller` (in `src/controllers/*`) → `manager` (in `src/managers/*`) → `module` / `generated/prisma` for persistence and external integrations.
- Keep each layer focused: routers handle routing & middleware, controllers handle request validation and high-level orchestration, managers encapsulate domain/persistence logic, modules provide shared utilities (external API clients, helpers).
- **Runtime / tooling**: The project runs on Bun. Dev command: `npm run dev` (runs `bun --watch src/index.ts`). DB tooling uses Prisma; generated client lives under `generated/prisma` (do NOT edit generated files). Key scripts in `package.json`:
- `dev` — start the server with Bun in watch mode
- `db:gen``prisma generate`
- `db:push``prisma migrate dev --skip-generate`
- **Data layer**: Prisma schema is at `prisma/schema.prisma`. The app imports the generated Prisma client from `generated/prisma/client.ts` (or `generated/prisma/browser.ts` in browser contexts). Always run the `db:gen` script after updating `schema.prisma`.
- **Routing & controllers**: Example flow: a request hits a `router` in `src/api/routers/*` → router delegates to a `controller` in `src/controllers/*` → controller calls a `manager` in `src/managers/*` for domain/persistence logic. Important concrete patterns:
- `src/api/server.ts` mounts `v1` and uses `v1.route("/auth", require("./routers/authRouter").default)` style requires; preserve this shape when adding routes.
- Router files export a default Hono router object (CommonJS `module.exports`/`export default` mixture is used across the codebase).
- Controllers are single-export modules named like `CompanyController.ts` with named methods per action (e.g., `fetch`, `update`). Prefer small methods that call into `managers/*`.
- Managers are thin domain layers (e.g., `managers/companies.ts`) that wrap `generated/prisma` calls and other I/O. Keep side effects here, keep controllers pure orchestration.
- Use `src/modules/api-utils/apiResponse.ts` for every HTTP response shape (successful/created/error/internalError/zodError).
- Use Zod schemas in controllers for request validation; server-level `app.onError` maps `ZodError` to `apiResponse.zodError`.
**API layout & conventions (how to add a new endpoint)**
- **Add router**: create `src/api/routers/<thing>Router.ts` exporting a Hono router and mount it in `src/api/server.ts` under the `v1` router.
- **Add controller**: create `src/controllers/<Thing>Controller.ts` exporting functions for each action. Controllers should validate input with Zod, call managers, and return `apiResponse.*` results.
- **Add manager**: create `src/managers/<things>.ts` for persistence/domain logic. Use the generated Prisma client (`generated/prisma/client.ts`) here; do not import Prisma directly in controllers.
- **Add modules/types**: if needed, add helpers to `src/modules/*` and runtime types to `src/types/*`.
- **Middleware & auth**: use `src/api/middleware/authorization.ts` for protecting routes; follow existing token/session patterns from `src/controllers/SessionController.ts` and `src/Errors/*`.
- **Error handling**: throw repository-specific errors from `src/Errors/*` (include `status`, `name`, `message`, optional `cause`) and let `src/api/server.ts` map them via `apiResponse.error`.
- **Naming**: prefer plural manager filenames (`companies.ts`) and singular controller names (`CompanyController.ts`) — follow existing files.
**Examples & notable files**
- `src/api/server.ts` — mounts `v1`, registers `cors`, central `onError` handler and `notFound` response.
- `src/api/routers/companyRouter.ts` and `src/controllers/CompanyController.ts` — canonical example for adding company endpoints.
- `src/api/user/@me/*` — nested route example (use Hono sub-routers for subpaths).
- `src/modules/cw-utils/*` — external API integrations; keep interfaces stable and return domain objects consumed by managers.
- **Validation & errors**: Zod is used for input validation; Zod errors are handled centrally in `src/api/server.ts` via `apiResponse.zodError`. Application errors use custom error classes in `src/Errors/*` (e.g., `AuthenticationError.ts`, `GenericError.ts`). When creating errors, follow the shape used in existing errors (include `status`, `name`, `message`, and optional `cause`).
- **Response pattern**: Use the `apiResponse` helpers in `src/modules/api-utils/apiResponse.ts` for formatting responses and status codes (successful, created, error, internalError, zodError).
- **Auth & external integrations**: Microsoft OAuth flow is under `src/api/auth/*` and `src/modules/fetchMicrosoftUser.ts`. If touching authentication, follow existing redirect/refresh patterns in `src/api/auth` and preserve token-refresh semantics.
- **ConnectWise integration**: Utilities for ConnectWise interactions live in `src/modules/cw-utils/*` (e.g., `fetchCompanyConfigurations.ts`). These modules often call external APIs and return domain data; preserve the module contracts (input types and returned shapes) when refactoring.
- **Generated files and CI**: `generated/` is a build artifact. Do not modify. When updating Prisma models, run `npm run db:gen` and commit changes to `generated/prisma` only if that's the established workflow.
- **Files to inspect for context / examples**:
- `src/api/server.ts` — central error handling, router mounting, CORS and not-found handling.
- `src/modules/api-utils/apiResponse.ts` — response shaping used across controllers.
- `src/controllers/CompanyController.ts` — example controller calling managers.
- `src/modules/cw-utils/fetchCompanyConfigurations.ts` — example external integration utility.
- `generated/prisma/client.ts` — generated Prisma client imports; avoid editing.
- **Coding conventions & patterns specific to this repo**:
- Prefer the existing layered architecture: routers → controllers → managers → modules.
- Use the `apiResponse` helpers for all HTTP responses.
- Throw or propagate repository-specific custom errors (from `src/Errors/*`) rather than returning bare objects.
- Keep TypeScript types in `src/types/*` and use Zod for runtime checks.
- **Avoid `else` statements** — prefer ternary operators, early returns, or other control flow patterns. Only use `else` if there is absolutely no other way.
- **Local dev / quick checks**:
- Start dev server: `npm run dev`
- Regenerate Prisma client: `npm run db:gen`
- Apply DB migrations locally: `npm run db:push`
- **When editing generated or infra files**: if you need to change `generated/prisma/*` (rare), explain why in the PR and show commands used to regenerate.
- **Documentation sync (IMPORTANT)**: Whenever you add, remove, or modify API routes or permission nodes, you **must** update all three of the following files to keep them in sync:
1. `src/types/PermissionNodes.ts` — the single source of truth for all permission node definitions, categories, descriptions, and `usedIn` references.
2. `PERMISSIONS.md` — human-readable documentation of all permission nodes; must strictly reflect the data in `PermissionNodes.ts`.
3. `API_ROUTES.md` — comprehensive documentation of all API routes, including method, path, auth requirements, permissions, request/response examples.
Always verify that new routes have their required permissions listed in `PermissionNodes.ts`, that `PERMISSIONS.md` tables match the TS file exactly, and that `API_ROUTES.md` includes full documentation for every mounted route. Run through all three files at the end of any route or permission change to catch discrepancies.
If anything here is unclear or you'd like more examples (e.g., a walk-through editing a controller + manager + test run), tell me which area to expand and I'll iterate.