From 3ab443790c664a4be04de7ac64eba361be15dec8 Mon Sep 17 00:00:00 2001 From: Jackson Roberts Date: Sat, 14 Feb 2026 12:08:23 -0600 Subject: [PATCH] Lots of updates and cleaning up. --- .github/copilot-instructions.md | 73 ++++++++ src/api/auth/redirect.ts | 2 - src/api/auth/refresh.ts | 2 - src/api/companies/[id]/configurations.ts | 26 +++ src/api/companies/{ => [id]}/fetch.ts | 13 +- src/api/companies/fetchAll.ts | 10 +- src/api/companies/index.ts | 5 +- src/api/server.ts | 2 +- src/controllers/CompanyController.ts | 29 +++ src/controllers/RoleController.ts | 17 +- src/controllers/UserController.ts | 2 - src/managers/companies.ts | 31 ++++ .../cw-utils/fetchCompanyConfigurations.ts | 30 ++++ .../cw-utils/processConfigurationResponse.ts | 22 +++ src/modules/cw-utils/refreshCompanies.ts | 47 ++--- src/modules/globalEvents.ts | 59 ++++++- src/types/ConnectWiseTypes.ts | 166 ++++++++++++++++++ 17 files changed, 484 insertions(+), 52 deletions(-) create mode 100644 .github/copilot-instructions.md create mode 100644 src/api/companies/[id]/configurations.ts rename src/api/companies/{ => [id]}/fetch.ts (58%) create mode 100644 src/modules/cw-utils/fetchCompanyConfigurations.ts create mode 100644 src/modules/cw-utils/processConfigurationResponse.ts diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..451e0d3 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,73 @@ +# 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/Router.ts` exporting a Hono router and mount it in `src/api/server.ts` under the `v1` router. +- **Add controller**: create `src/controllers/Controller.ts` exporting functions for each action. Controllers should validate input with Zod, call managers, and return `apiResponse.*` results. +- **Add manager**: create `src/managers/.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. + +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. diff --git a/src/api/auth/redirect.ts b/src/api/auth/redirect.ts index 0906382..6bb9cb3 100644 --- a/src/api/auth/redirect.ts +++ b/src/api/auth/redirect.ts @@ -23,8 +23,6 @@ export default createRoute("get", ["/redirect"], async (c) => { refreshToken: tokens.refreshToken, }); - console.log("Emitted auth callback for key:", callbackKey); - // Close the window because duh return c.html( `