create-tigra 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +87 -0
  3. package/bin/create-tigra.js +292 -0
  4. package/package.json +41 -0
  5. package/template/.agent/rules/client/01-project-structure.md +326 -0
  6. package/template/.agent/rules/client/02-component-patterns.md +249 -0
  7. package/template/.agent/rules/client/03-typescript-rules.md +226 -0
  8. package/template/.agent/rules/client/04-state-management.md +474 -0
  9. package/template/.agent/rules/client/05-api-integration.md +129 -0
  10. package/template/.agent/rules/client/06-forms-validation.md +129 -0
  11. package/template/.agent/rules/client/07-common-patterns.md +150 -0
  12. package/template/.agent/rules/client/08-color-system.md +93 -0
  13. package/template/.agent/rules/client/09-security-rules.md +97 -0
  14. package/template/.agent/rules/client/10-testing-strategy.md +370 -0
  15. package/template/.agent/rules/global/ai-edit-safety.md +38 -0
  16. package/template/.agent/rules/server/01-db-and-migrations.md +242 -0
  17. package/template/.agent/rules/server/02-general-rules.md +111 -0
  18. package/template/.agent/rules/server/03-migrations.md +20 -0
  19. package/template/.agent/rules/server/04-pagination.md +130 -0
  20. package/template/.agent/rules/server/05-project-conventions.md +71 -0
  21. package/template/.agent/rules/server/06-response-handling.md +173 -0
  22. package/template/.agent/rules/server/07-testing-strategy.md +506 -0
  23. package/template/.agent/rules/server/08-observability.md +180 -0
  24. package/template/.agent/rules/server/09-api-documentation-v2.md +168 -0
  25. package/template/.agent/rules/server/10-background-jobs-v2.md +185 -0
  26. package/template/.agent/rules/server/11-rate-limiting-v2.md +210 -0
  27. package/template/.agent/rules/server/12-performance-optimization.md +567 -0
  28. package/template/.claude/rules/client-01-project-structure.md +327 -0
  29. package/template/.claude/rules/client-02-component-patterns.md +250 -0
  30. package/template/.claude/rules/client-03-typescript-rules.md +227 -0
  31. package/template/.claude/rules/client-04-state-management.md +475 -0
  32. package/template/.claude/rules/client-05-api-integration.md +130 -0
  33. package/template/.claude/rules/client-06-forms-validation.md +130 -0
  34. package/template/.claude/rules/client-07-common-patterns.md +151 -0
  35. package/template/.claude/rules/client-08-color-system.md +94 -0
  36. package/template/.claude/rules/client-09-security-rules.md +98 -0
  37. package/template/.claude/rules/client-10-testing-strategy.md +371 -0
  38. package/template/.claude/rules/global-ai-edit-safety.md +39 -0
  39. package/template/.claude/rules/server-01-db-and-migrations.md +243 -0
  40. package/template/.claude/rules/server-02-general-rules.md +112 -0
  41. package/template/.claude/rules/server-03-migrations.md +21 -0
  42. package/template/.claude/rules/server-04-pagination.md +131 -0
  43. package/template/.claude/rules/server-05-project-conventions.md +72 -0
  44. package/template/.claude/rules/server-06-response-handling.md +174 -0
  45. package/template/.claude/rules/server-07-testing-strategy.md +507 -0
  46. package/template/.claude/rules/server-08-observability.md +181 -0
  47. package/template/.claude/rules/server-09-api-documentation-v2.md +169 -0
  48. package/template/.claude/rules/server-10-background-jobs-v2.md +186 -0
  49. package/template/.claude/rules/server-11-rate-limiting-v2.md +211 -0
  50. package/template/.claude/rules/server-12-performance-optimization.md +568 -0
  51. package/template/.cursor/rules/client-01-project-structure.mdc +327 -0
  52. package/template/.cursor/rules/client-02-component-patterns.mdc +250 -0
  53. package/template/.cursor/rules/client-03-typescript-rules.mdc +227 -0
  54. package/template/.cursor/rules/client-04-state-management.mdc +475 -0
  55. package/template/.cursor/rules/client-05-api-integration.mdc +130 -0
  56. package/template/.cursor/rules/client-06-forms-validation.mdc +130 -0
  57. package/template/.cursor/rules/client-07-common-patterns.mdc +151 -0
  58. package/template/.cursor/rules/client-08-color-system.mdc +94 -0
  59. package/template/.cursor/rules/client-09-security-rules.mdc +98 -0
  60. package/template/.cursor/rules/client-10-testing-strategy.mdc +371 -0
  61. package/template/.cursor/rules/global-ai-edit-safety.mdc +39 -0
  62. package/template/.cursor/rules/server-01-db-and-migrations.mdc +243 -0
  63. package/template/.cursor/rules/server-02-general-rules.mdc +112 -0
  64. package/template/.cursor/rules/server-03-migrations.mdc +21 -0
  65. package/template/.cursor/rules/server-04-pagination.mdc +131 -0
  66. package/template/.cursor/rules/server-05-project-conventions.mdc +72 -0
  67. package/template/.cursor/rules/server-06-response-handling.mdc +174 -0
  68. package/template/.cursor/rules/server-07-testing-strategy.mdc +507 -0
  69. package/template/.cursor/rules/server-08-observability.mdc +181 -0
  70. package/template/.cursor/rules/server-09-api-documentation-v2.mdc +169 -0
  71. package/template/.cursor/rules/server-10-background-jobs-v2.mdc +186 -0
  72. package/template/.cursor/rules/server-11-rate-limiting-v2.mdc +211 -0
  73. package/template/.cursor/rules/server-12-performance-optimization.mdc +568 -0
  74. package/template/CLAUDE.md +207 -0
  75. package/template/server/.env.example +148 -0
  76. package/template/server/.tsc-aliasrc.json +12 -0
  77. package/template/server/README.md +175 -0
  78. package/template/server/SECURITY.md +190 -0
  79. package/template/server/biome.json +42 -0
  80. package/template/server/docker-compose.yml +111 -0
  81. package/template/server/package.json +83 -0
  82. package/template/server/postman_collection.json +733 -0
  83. package/template/server/prisma/schema.prisma +92 -0
  84. package/template/server/prisma/seed.ts +142 -0
  85. package/template/server/scripts/wait-for-db.js +60 -0
  86. package/template/server/src/app.ts +74 -0
  87. package/template/server/src/config/env.ts +101 -0
  88. package/template/server/src/hooks/request-timing.hook.ts +26 -0
  89. package/template/server/src/libs/auth/authenticate.middleware.ts +22 -0
  90. package/template/server/src/libs/auth/rbac.middleware.test.ts +134 -0
  91. package/template/server/src/libs/auth/rbac.middleware.ts +147 -0
  92. package/template/server/src/libs/db.ts +76 -0
  93. package/template/server/src/libs/error-handler.ts +89 -0
  94. package/template/server/src/libs/logger.ts +60 -0
  95. package/template/server/src/libs/queue.ts +79 -0
  96. package/template/server/src/libs/redis.ts +79 -0
  97. package/template/server/src/libs/swagger-schemas.ts +16 -0
  98. package/template/server/src/modules/admin/admin.controller.ts +122 -0
  99. package/template/server/src/modules/admin/admin.routes.ts +100 -0
  100. package/template/server/src/modules/admin/admin.schemas.ts +35 -0
  101. package/template/server/src/modules/admin/admin.service.ts +167 -0
  102. package/template/server/src/modules/auth/auth.controller.ts +141 -0
  103. package/template/server/src/modules/auth/auth.integration.test.ts +150 -0
  104. package/template/server/src/modules/auth/auth.repo.ts +218 -0
  105. package/template/server/src/modules/auth/auth.routes.ts +204 -0
  106. package/template/server/src/modules/auth/auth.schemas.ts +137 -0
  107. package/template/server/src/modules/auth/auth.service.test.ts +119 -0
  108. package/template/server/src/modules/auth/auth.service.ts +329 -0
  109. package/template/server/src/modules/auth/auth.types.ts +97 -0
  110. package/template/server/src/modules/resources/resources.controller.ts +218 -0
  111. package/template/server/src/modules/resources/resources.repo.ts +253 -0
  112. package/template/server/src/modules/resources/resources.routes.ts +355 -0
  113. package/template/server/src/modules/resources/resources.schemas.ts +146 -0
  114. package/template/server/src/modules/resources/resources.service.ts +218 -0
  115. package/template/server/src/modules/resources/resources.types.ts +73 -0
  116. package/template/server/src/plugins/rate-limit.plugin.ts +21 -0
  117. package/template/server/src/plugins/security.plugin.ts +21 -0
  118. package/template/server/src/plugins/swagger.plugin.ts +41 -0
  119. package/template/server/src/routes/health.routes.ts +31 -0
  120. package/template/server/src/server.ts +142 -0
  121. package/template/server/src/test/setup.ts +38 -0
  122. package/template/server/src/types/fastify.d.ts +36 -0
  123. package/template/server/src/utils/errors.ts +108 -0
  124. package/template/server/src/utils/pagination.ts +120 -0
  125. package/template/server/src/utils/response.ts +110 -0
  126. package/template/server/src/workers/file.worker.ts +106 -0
  127. package/template/server/tsconfig.build.json +30 -0
  128. package/template/server/tsconfig.build.tsbuildinfo +1 -0
  129. package/template/server/tsconfig.json +89 -0
  130. package/template/server/tsconfig.test.json +22 -0
  131. package/template/server/vitest.config.ts +98 -0
@@ -0,0 +1,112 @@
1
+ ---
2
+ trigger: always_on
3
+ globs: "server/**/*"
4
+ ---
5
+
6
+ > **SCOPE**: These rules apply specifically to the **server** directory.
7
+
8
+ You are a senior backend engineer helping build a high-traffic API server.
9
+
10
+ ### PROJECT CONTEXT
11
+
12
+ - Stack:
13
+
14
+ - Node.js (LTS, 20+)
15
+ - Fastify as HTTP framework
16
+ - TypeScript
17
+ - MySQL as the primary relational database
18
+ - Redis for caching, sessions, and rate limiting
19
+ - Zod for runtime validation and type inference
20
+ - Drizzle ORM (or Prisma) for DB access and migrations
21
+ - Jest/Vitest for tests
22
+
23
+ - Domain:
24
+
25
+ - Users & Roles
26
+ - Core Business Entities
27
+ - Locations & Mapping
28
+ - Media (images, galleries)
29
+ - Resources Availability & Pricing
30
+ - Transactions & Bookings
31
+ - Payments (integration with external providers)
32
+ - Messaging & Communications
33
+
34
+ - Goals:
35
+ - Clean, layered architecture: Routes → Controllers → Services → Repositories → DB
36
+ - High performance (Fastify, Redis, proper indexes)
37
+ - Easy to maintain and scale
38
+ - Secure (auth, input validation, rate limiting)
39
+ - Clear separation of concerns
40
+
41
+ ### ARCHITECTURE & CODE STYLE
42
+
43
+ 1. Use TypeScript everywhere. Always type function parameters and return types.
44
+ 2. Organize by domain/module:
45
+
46
+ src/modules/<domain>/
47
+
48
+ - <domain>.routes.ts (Fastify route definitions)
49
+ - <domain>.controller.ts (HTTP handlers only; no business logic)
50
+ - <domain>.service.ts (business logic)
51
+ - <domain>.repo.ts (DB queries)
52
+ - <domain>.schemas.ts (Zod schemas for input/output)
53
+
54
+ 3. Fastify:
55
+
56
+ - Use plugins and route registration with prefixes (e.g., /api/v1/<resource>).
57
+ - Use schemas for validation & serialization.
58
+ - Implement centralized error handling.
59
+
60
+ 4. Database:
61
+
62
+ - Use migrations (via Drizzle/Prisma) for schema changes.
63
+ - Add proper indexes for search-heavy fields (identifiers, price, date, type).
64
+ - Avoid N+1 queries; prefer joins or batched queries.
65
+
66
+ 5. Redis:
67
+
68
+ - Use for caching frequently accessed data.
69
+ - Use for rate limiting and potentially for background task signaling.
70
+
71
+ 6. Auth:
72
+
73
+ - Use JWT with HS256 or RS256.
74
+ - Store only minimal user info in the token (id, role).
75
+ - Implement role-based access control.
76
+
77
+ 7. Security:
78
+
79
+ - Validate all inputs with Zod and Fastify schemas.
80
+ - Never interpolate raw values into SQL; always use the ORM query builder.
81
+ - Implement sane rate limiting for public endpoints.
82
+ - Sanitize outputs where necessary.
83
+
84
+ 8. Coding constraints:
85
+
86
+ - Do NOT break existing exports or types unless explicitly asked.
87
+ - When modifying existing files, keep changes focused and minimal.
88
+ - Reuse existing helpers (db, logger, env) instead of re-creating them.
89
+ - Add TODO comments for non-trivial follow-up tasks.
90
+
91
+ 9. When asked to implement a feature:
92
+
93
+ - First, summarize what needs to be done.
94
+ - Then list files to be created/modified.
95
+ - Then provide code for each file in separate code blocks.
96
+ - Ensure imports between files are correct and consistent with the project structure.
97
+
98
+ 10. Testing:
99
+
100
+ - For core logic (calculations, transactions, payment callbacks), provide Jest/Vitest tests.
101
+ - Tests should be deterministic and not hit external APIs directly (use mocks).
102
+
103
+ ### RESPONSE FORMAT
104
+
105
+ Whenever you make changes:
106
+
107
+ 1. Briefly explain the approach (1–2 paragraphs).
108
+ 2. Show updated/created files with full content in code blocks.
109
+ 3. Mention any migrations or environment variables that must be added.
110
+ 4. If you are unsure, state your assumptions clearly.
111
+
112
+ If instructions from earlier parts of the prompt conflict with the user’s new message, follow the user’s latest explicit instructions.
@@ -0,0 +1,21 @@
1
+ ---
2
+ trigger: always_on
3
+ globs: "server/**/*"
4
+ ---
5
+
6
+ > **SCOPE**: These rules apply specifically to the **server** directory.
7
+
8
+ # Migration Rules for AI Agent
9
+
10
+ CRITICAL: When user asks for schema changes:
11
+
12
+ 1. ALWAYS edit `prisma/schema.prisma` first
13
+ 2. THEN run: `npm run prisma:migrate dev --name descriptive_name`
14
+ 3. IF migration fails with conflicts:
15
+ - DON'T try to fix manually
16
+ - DO run: `npm run prisma:reset`
17
+ - Then: `npm run prisma:seed`
18
+ 4. NEVER use `prisma db push` unless explicitly asked
19
+
20
+ Development = use prisma:reset freely
21
+ Production = ONLY use prisma:migrate deploy
@@ -0,0 +1,131 @@
1
+ ---
2
+ trigger: always_on
3
+ globs: "server/**/*"
4
+ ---
5
+
6
+ > **SCOPE**: These rules apply specifically to the **server** directory.
7
+
8
+ ## Pagination Contract (MANDATORY)
9
+
10
+ All paginated API responses MUST follow a unified structure. No exceptions are allowed.
11
+
12
+ ### Paginated Response Format
13
+
14
+ Every paginated response MUST follow this exact structure:
15
+ ```json
16
+ {
17
+ "success": true,
18
+ "message": "string",
19
+ "data": {
20
+ "items": [],
21
+ "pagination": {
22
+ "page": 1,
23
+ "limit": 10,
24
+ "totalItems": 237,
25
+ "totalPages": 24,
26
+ "hasNextPage": true,
27
+ "hasPreviousPage": false
28
+ }
29
+ }
30
+ }
31
+ ```
32
+
33
+ ### Response Rules
34
+
35
+ - `success` is always `true`
36
+ - `message` is REQUIRED and must be human-readable
37
+ - `data.items` contains the array of results (can be empty array)
38
+ - `data.pagination` is REQUIRED and contains:
39
+ - `page` – current page number (starts at 1)
40
+ - `limit` – items per page
41
+ - `totalItems` – total count of items across all pages
42
+ - `totalPages` – calculated as `Math.ceil(totalItems / limit)`
43
+ - `hasNextPage` – boolean, `true` if `page < totalPages`
44
+ - `hasPreviousPage` – boolean, `true` if `page > 1`
45
+
46
+ ### Shared Pagination Helper (REQUIRED)
47
+
48
+ Controllers MUST use a shared `paginatedResponse` helper:
49
+ ```typescript
50
+ function paginatedResponse<T>(
51
+ message: string,
52
+ items: T[],
53
+ page: number,
54
+ limit: number,
55
+ totalItems: number
56
+ )
57
+ ```
58
+
59
+ **Allowed example:**
60
+ ```typescript
61
+ return reply.send(paginatedResponse("Resources retrieved successfully", items, page, limit, totalCount));
62
+ ```
63
+
64
+ **Forbidden examples:**
65
+ ```typescript
66
+ reply.send({ items, page, total });
67
+ reply.send({ success: true, data: items, pagination: {...} });
68
+ reply.send({ items: items, meta: {...} });
69
+ ```
70
+
71
+ ### Pagination Input Validation (REQUIRED)
72
+
73
+ All endpoints accepting pagination MUST validate using a shared Zod schema:
74
+ ```typescript
75
+ const PaginationSchema = z.object({
76
+ page: z.coerce.number().int().min(1).default(1),
77
+ limit: z.coerce.number().int().min(1).max(100).default(10)
78
+ });
79
+ ```
80
+
81
+ **Rules:**
82
+ - `page` defaults to `1`, must be positive integer
83
+ - `limit` defaults to `10`, must be between 1 and 100
84
+ - Use `z.coerce.number()` to handle query string conversion
85
+ - Controllers MUST validate pagination inputs before calling services
86
+
87
+ ### Service Layer Requirements
88
+
89
+ Services handling pagination MUST:
90
+ - Accept `page` and `limit` as parameters
91
+ - Return both the `items` array AND `totalItems` count
92
+ - NOT construct pagination metadata (controller responsibility)
93
+ - Calculate offset as: `(page - 1) * limit`
94
+
95
+ **Service return pattern:**
96
+ ```typescript
97
+ return {
98
+ items: results,
99
+ totalItems: count
100
+ };
101
+ ```
102
+
103
+ ### Filter & Sort with Pagination
104
+
105
+ When combining filters/sorting with pagination:
106
+ - Filters come BEFORE pagination in query parameters
107
+ - Pagination params (`page`, `limit`) are separate from filters
108
+ - Apply filters/sorting to query BEFORE applying `limit` and `offset`
109
+ - Count total items AFTER filters but BEFORE pagination
110
+
111
+ **Example query string:**
112
+ ```
113
+ ?category=active&minPrice=100&sortBy=price&order=asc&page=2&limit=20
114
+ ```
115
+
116
+ ### Strict Prohibitions
117
+
118
+ These patterns are NOT allowed:
119
+ - Multiple pagination formats across endpoints
120
+ - Returning raw arrays without pagination wrapper
121
+ - Custom pagination field names (e.g., `pageNumber`, `perPage`, `count`)
122
+ - Including pagination in query results instead of metadata
123
+ - Zero-indexed pages (always start at 1)
124
+ - Omitting `totalItems` or `totalPages`
125
+
126
+ ### Enforcement Rule
127
+
128
+ If a user instruction conflicts with this pagination contract:
129
+ - Follow the user instruction ONLY if explicitly stated
130
+ - Otherwise, this pagination contract is non-negotiable
131
+ - Pagination structure MUST be consistent across ALL endpoints
@@ -0,0 +1,72 @@
1
+ ---
2
+ trigger: always_on
3
+ globs: "server/**/*"
4
+ ---
5
+
6
+ > **SCOPE**: These rules apply specifically to the **server** directory.
7
+
8
+ # API Server – Project Conventions
9
+
10
+ ## Package manager
11
+
12
+ - Detect the package manager from the lockfile:
13
+ - If `pnpm-lock.yaml` exists → use `pnpm`
14
+ - If `yarn.lock` exists → use `yarn`
15
+ - Else → use `npm`
16
+
17
+ ## File & folder structure
18
+
19
+ - Keep everything under `src/`.
20
+ - Prefer this layout:
21
+
22
+ - `src/app.ts` → Fastify instance and plugin registration
23
+ - `src/server.ts` → actual `listen()` call, no app logic
24
+ - `src/config/` → env, config, constants
25
+ - `src/libs/` → shared libraries (db, redis, logger, auth)
26
+ - `src/modules/<domain>/` → domain modules:
27
+ - `<domain>.routes.ts`
28
+ - `<domain>.controller.ts`
29
+ - `<domain>.service.ts`
30
+ - `<domain>.repo.ts`
31
+ - `<domain>.schemas.ts`
32
+ - `<domain>.types.ts` (if needed)
33
+
34
+ - When adding new modules, stick to `src/modules/<name>/` and keep the exact naming pattern.
35
+
36
+ ## Coding style
37
+
38
+ - Use TypeScript with `strict` mode ON.
39
+ - Prefer `async/await` over `.then()`.
40
+ - Prefer named exports over default exports, except for:
41
+ - `src/app.ts` → default export is the Fastify instance
42
+ - Frontend components (if any).
43
+ - Use consistent import paths:
44
+ - Use relative imports inside a module: `./user.service`
45
+ - Use aliased imports for cross-module paths if configured (e.g. `@modules/users/...`).
46
+
47
+ ## Error handling
48
+
49
+ - Controllers must never throw raw errors; they should:
50
+ - Either use a shared error helper, or
51
+ - Let Fastify’s error handler handle typed errors.
52
+ - Never `console.log` for production logic:
53
+ - Use the shared `logger` from `src/libs/logger`.
54
+
55
+ ## API versioning & routes
56
+
57
+ - All API routes must be prefixed with `/api/v1`.
58
+ - Group routes by domain:
59
+ - `/api/v1/auth/...`
60
+ - `/api/v1/users/...`
61
+ - `/api/v1/<domain_resource>/...`
62
+ - When adding new routes, register them in a Fastify plugin under `src/modules/<domain>/<domain>.routes.ts`.
63
+
64
+ ## Service Layer Rules
65
+
66
+ - Every domain module must include a `<domain>.service.ts` file.
67
+ - Services contain all business logic and must NOT depend on Fastify, reply, request, or HTTP-specific concepts.
68
+ - Controllers must call services instead of performing logic directly.
69
+ - Services may call repositories for DB operations.
70
+ - Services must throw typed AppError instances for failures.
71
+ - Services must not return success or error responses; they only return data or throw errors.
72
+ - Services must be stateless and reusable.
@@ -0,0 +1,174 @@
1
+ ---
2
+ trigger: always_on
3
+ globs: "server/**/*"
4
+ ---
5
+
6
+ > **SCOPE**: These rules apply specifically to the **server** directory.
7
+
8
+ API Server – Error & Success Response Rules
9
+
10
+ These rules define the ONLY allowed way to return success and error responses from the API. All AI assistants MUST follow this contract strictly.
11
+
12
+ Unified Response Contract (MANDATORY)
13
+ The API uses a single, stable response structure for all endpoints. No exceptions are allowed.
14
+
15
+ Success Response Format
16
+ Every successful response MUST follow this exact structure:
17
+
18
+ {
19
+ "success": true,
20
+ "message": "string",
21
+ "data": {}
22
+ }
23
+
24
+ Rules:
25
+
26
+ success is always true
27
+
28
+ message is REQUIRED and must be human-readable
29
+
30
+ data can be an object, array, or null
31
+
32
+ Controllers MUST use a shared success helper (for example successResponse)
33
+
34
+ Controllers MUST NOT return raw values or custom-shaped JSON
35
+
36
+ Allowed example:
37
+ return reply.send(successResponse("Resource created successfully", data));
38
+
39
+ Forbidden examples:
40
+ reply.send(data);
41
+ reply.send({ data: data });
42
+ reply.send({ success: true, data });
43
+
44
+ Error Response Format
45
+ Every error response MUST follow this exact structure:
46
+
47
+ {
48
+ "success": false,
49
+ "error": {
50
+ "code": "ERROR_CODE",
51
+ "message": "Human readable message"
52
+ }
53
+ }
54
+
55
+ Rules:
56
+
57
+ success is always false
58
+
59
+ code must be a stable machine-readable string (for example RESOURCE_NOT_FOUND)
60
+
61
+ message must be safe for end users
62
+
63
+ Internal details, stack traces, or SQL errors MUST NOT be exposed
64
+
65
+ Controllers MUST NOT manually send error responses
66
+
67
+ Global Error Handling Architecture
68
+ The server MUST define ONE global Fastify error handler using fastify.setErrorHandler(...).
69
+ This global handler is responsible for:
70
+
71
+ Mapping errors to HTTP status codes
72
+
73
+ Formatting the unified error response
74
+
75
+ Logging internal error details on server side only
76
+
77
+ Error Throwing Rules (CRITICAL)
78
+ Controllers and services MUST throw typed errors ONLY.
79
+ They MUST NOT throw:
80
+
81
+ raw Error
82
+
83
+ strings
84
+
85
+ unstructured objects
86
+
87
+ Required Error Base Class
88
+ All custom errors MUST extend a shared AppError class which defines:
89
+
90
+ code
91
+
92
+ message
93
+
94
+ statusCode
95
+
96
+ Allowed Error Types
97
+ Allowed subclasses:
98
+
99
+ BadRequestError
100
+
101
+ ValidationError
102
+
103
+ UnauthorizedError
104
+
105
+ ForbiddenError
106
+
107
+ NotFoundError
108
+
109
+ ConflictError
110
+
111
+ InternalError
112
+
113
+ Each subclass MUST:
114
+
115
+ extend AppError
116
+
117
+ set a meaningful code
118
+
119
+ set an appropriate statusCode
120
+
121
+ Controller Responsibilities
122
+ Controllers MUST:
123
+
124
+ Validate input using Zod schemas
125
+
126
+ Call service-layer logic only
127
+
128
+ Return success responses using the shared success helper
129
+
130
+ Throw typed errors when something fails
131
+
132
+ Controllers MUST NOT:
133
+
134
+ Set HTTP status codes for errors
135
+
136
+ Build custom error JSON structures
137
+
138
+ Catch errors unless rethrowing typed errors
139
+
140
+ Service Layer Responsibilities
141
+ Services MUST:
142
+
143
+ Contain business logic
144
+
145
+ Throw typed AppError errors when needed
146
+
147
+ NEVER depend on Fastify reply or HTTP objects
148
+
149
+ Logging Rules
150
+ Logging MUST occur only inside:
151
+
152
+ The global error handler
153
+
154
+ Shared logging utilities
155
+
156
+ Controllers MUST NOT log unless explicitly instructed. Internal logs MUST NOT be sent to the client.
157
+
158
+ Strict Prohibitions
159
+ These patterns are NOT allowed anywhere:
160
+
161
+ Multiple response formats
162
+
163
+ reply.send({ error: "text" })
164
+
165
+ throw new Error("message")
166
+
167
+ Returning raw errors from services
168
+
169
+ Leaking stack traces or database internals to users
170
+
171
+ Final Enforcement Rule
172
+ If a user instruction conflicts with this document:
173
+ Follow the user instruction ONLY if explicitly stated.
174
+ Otherwise, this response contract is non-negotiable.