create-tigra 1.1.0 → 2.0.1

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 (243) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +80 -87
  3. package/bin/create-tigra.js +259 -308
  4. package/package.json +49 -41
  5. package/template/_claude/QUICK_REFERENCE.md +193 -0
  6. package/template/_claude/README.md +53 -0
  7. package/template/_claude/commands/create-client.md +881 -0
  8. package/template/_claude/commands/create-server.md +383 -0
  9. package/template/_claude/rules/client/01-project-structure.md +133 -0
  10. package/template/_claude/rules/client/02-components-and-types.md +146 -0
  11. package/template/_claude/rules/client/03-data-and-state.md +156 -0
  12. package/template/_claude/rules/client/04-design-system.md +185 -0
  13. package/template/_claude/rules/client/05-security.md +55 -0
  14. package/template/_claude/rules/client/06-ux-checklist.md +81 -0
  15. package/template/_claude/rules/client/core.md +42 -0
  16. package/template/_claude/rules/global/core.md +77 -0
  17. package/template/_claude/rules/server/core.md +50 -0
  18. package/template/_claude/rules/server/database.md +124 -0
  19. package/template/_claude/rules/server/project-conventions.md +150 -0
  20. package/template/_claude/rules/server/response-handling.md +144 -0
  21. package/template/client/.env.example +5 -0
  22. package/template/client/README.md +36 -0
  23. package/template/client/components.json +23 -0
  24. package/template/client/eslint.config.mjs +18 -0
  25. package/template/client/next.config.ts +34 -0
  26. package/template/client/package.json +44 -0
  27. package/template/client/postcss.config.mjs +7 -0
  28. package/template/client/src/app/(auth)/layout.tsx +18 -0
  29. package/template/client/src/app/(auth)/login/page.tsx +13 -0
  30. package/template/client/src/app/(auth)/register/page.tsx +13 -0
  31. package/template/client/src/app/(main)/dashboard/page.tsx +22 -0
  32. package/template/client/src/app/(main)/layout.tsx +11 -0
  33. package/template/client/src/app/error.tsx +27 -0
  34. package/template/client/src/app/favicon.ico +0 -0
  35. package/template/client/src/app/globals.css +145 -0
  36. package/template/client/src/app/layout.tsx +36 -0
  37. package/template/client/src/app/loading.tsx +11 -0
  38. package/template/client/src/app/not-found.tsx +23 -0
  39. package/template/client/src/app/page.tsx +45 -0
  40. package/template/client/src/app/providers.tsx +43 -0
  41. package/template/client/src/components/common/ConfirmDialog.tsx +56 -0
  42. package/template/client/src/components/common/EmptyState.tsx +31 -0
  43. package/template/client/src/components/common/LoadingSpinner.tsx +30 -0
  44. package/template/client/src/components/common/Pagination.tsx +55 -0
  45. package/template/client/src/components/layout/Footer.tsx +17 -0
  46. package/template/client/src/components/layout/Header.tsx +173 -0
  47. package/template/client/src/components/layout/MainLayout.tsx +18 -0
  48. package/template/client/src/components/ui/alert-dialog.tsx +196 -0
  49. package/template/client/src/components/ui/badge.tsx +48 -0
  50. package/template/client/src/components/ui/button.tsx +64 -0
  51. package/template/client/src/components/ui/card.tsx +92 -0
  52. package/template/client/src/components/ui/input.tsx +21 -0
  53. package/template/client/src/components/ui/label.tsx +24 -0
  54. package/template/client/src/components/ui/select.tsx +190 -0
  55. package/template/client/src/components/ui/skeleton.tsx +13 -0
  56. package/template/client/src/components/ui/table.tsx +116 -0
  57. package/template/client/src/features/auth/components/AuthInitializer.tsx +55 -0
  58. package/template/client/src/features/auth/components/LoginForm.tsx +107 -0
  59. package/template/client/src/features/auth/components/RegisterForm.tsx +178 -0
  60. package/template/client/src/features/auth/hooks/useAuth.ts +84 -0
  61. package/template/client/src/features/auth/services/auth.service.ts +52 -0
  62. package/template/client/src/features/auth/store/authSlice.ts +38 -0
  63. package/template/client/src/features/auth/types/auth.types.ts +32 -0
  64. package/template/client/src/hooks/useDebounce.ts +14 -0
  65. package/template/client/src/hooks/useLocalStorage.ts +55 -0
  66. package/template/client/src/hooks/useMediaQuery.ts +27 -0
  67. package/template/client/src/lib/api/api.types.ts +34 -0
  68. package/template/client/src/lib/api/axios.config.ts +98 -0
  69. package/template/client/src/lib/constants/api-endpoints.ts +18 -0
  70. package/template/client/src/lib/constants/app.constants.ts +12 -0
  71. package/template/client/src/lib/constants/routes.ts +9 -0
  72. package/template/client/src/lib/utils/error.ts +32 -0
  73. package/template/client/src/lib/utils/format.ts +37 -0
  74. package/template/client/src/lib/utils/security.ts +34 -0
  75. package/template/client/src/lib/utils.ts +6 -0
  76. package/template/client/src/middleware.ts +57 -0
  77. package/template/client/src/store/hooks.ts +7 -0
  78. package/template/client/src/store/index.ts +12 -0
  79. package/template/client/src/types/index.ts +3 -0
  80. package/template/client/tsconfig.json +34 -0
  81. package/template/gitignore +34 -0
  82. package/template/server/.dockerignore +66 -0
  83. package/template/server/.env.example +96 -69
  84. package/template/server/.env.production.example +90 -0
  85. package/template/server/Dockerfile +94 -0
  86. package/template/server/docker-compose.yml +82 -111
  87. package/template/server/docs/logging.md +62 -0
  88. package/template/server/eslint.config.mjs +17 -0
  89. package/template/server/package.json +68 -81
  90. package/template/server/phpmyadmin-config.php +26 -0
  91. package/template/server/postman_collection.json +666 -0
  92. package/template/server/prisma/schema.prisma +77 -93
  93. package/template/server/prisma/seed.ts +46 -142
  94. package/template/server/scripts/flush-redis.ts +41 -0
  95. package/template/server/src/app.ts +243 -71
  96. package/template/server/src/config/env.ts +67 -94
  97. package/template/server/src/libs/auth.ts +88 -0
  98. package/template/server/src/libs/cleanup.ts +35 -0
  99. package/template/server/src/libs/cookies.ts +46 -0
  100. package/template/server/src/libs/logger.ts +33 -60
  101. package/template/server/src/libs/monitoring.ts +205 -0
  102. package/template/server/src/libs/password.ts +38 -0
  103. package/template/server/src/libs/prisma.ts +68 -0
  104. package/template/server/src/libs/redis.ts +60 -79
  105. package/template/server/src/libs/requestLogger.ts +66 -0
  106. package/template/server/src/libs/storage/file-storage.service.ts +211 -0
  107. package/template/server/src/libs/storage/file-validator.ts +97 -0
  108. package/template/server/src/libs/storage/filename-sanitizer.ts +71 -0
  109. package/template/server/src/libs/storage/image-optimizer.service.ts +144 -0
  110. package/template/server/src/modules/auth/__tests__/auth.service.test.ts +365 -0
  111. package/template/server/src/modules/auth/auth.controller.ts +90 -141
  112. package/template/server/src/modules/auth/auth.repo.ts +120 -218
  113. package/template/server/src/modules/auth/auth.routes.ts +96 -83
  114. package/template/server/src/modules/auth/auth.schemas.ts +35 -137
  115. package/template/server/src/modules/auth/auth.service.ts +286 -329
  116. package/template/server/src/modules/auth/session.repo.ts +110 -0
  117. package/template/server/src/modules/users/users.controller.ts +120 -0
  118. package/template/server/src/modules/users/users.repo.ts +77 -0
  119. package/template/server/src/modules/users/users.routes.ts +89 -0
  120. package/template/server/src/modules/users/users.schemas.ts +21 -0
  121. package/template/server/src/modules/users/users.service.ts +169 -0
  122. package/template/server/src/server.ts +58 -139
  123. package/template/server/src/shared/errors/AppError.ts +21 -0
  124. package/template/server/src/shared/errors/errors.ts +43 -0
  125. package/template/server/src/shared/responses/paginatedResponse.ts +38 -0
  126. package/template/server/src/shared/responses/successResponse.ts +17 -0
  127. package/template/server/src/shared/schemas/pagination.schema.ts +12 -0
  128. package/template/server/src/shared/types/index.ts +26 -0
  129. package/template/server/src/test/setup.ts +74 -38
  130. package/template/server/tsconfig.json +27 -89
  131. package/template/server/uploads/avatars/.gitkeep +1 -0
  132. package/template/server/vitest.config.ts +43 -98
  133. package/template/.agent/rules/client/01-project-structure.md +0 -326
  134. package/template/.agent/rules/client/02-component-patterns.md +0 -249
  135. package/template/.agent/rules/client/03-typescript-rules.md +0 -226
  136. package/template/.agent/rules/client/04-state-management.md +0 -474
  137. package/template/.agent/rules/client/05-api-integration.md +0 -129
  138. package/template/.agent/rules/client/06-forms-validation.md +0 -129
  139. package/template/.agent/rules/client/07-common-patterns.md +0 -150
  140. package/template/.agent/rules/client/08-color-system.md +0 -93
  141. package/template/.agent/rules/client/09-security-rules.md +0 -97
  142. package/template/.agent/rules/client/10-testing-strategy.md +0 -370
  143. package/template/.agent/rules/global/ai-edit-safety.md +0 -38
  144. package/template/.agent/rules/server/01-db-and-migrations.md +0 -242
  145. package/template/.agent/rules/server/02-general-rules.md +0 -111
  146. package/template/.agent/rules/server/03-migrations.md +0 -20
  147. package/template/.agent/rules/server/04-pagination.md +0 -130
  148. package/template/.agent/rules/server/05-project-conventions.md +0 -71
  149. package/template/.agent/rules/server/06-response-handling.md +0 -173
  150. package/template/.agent/rules/server/07-testing-strategy.md +0 -506
  151. package/template/.agent/rules/server/08-observability.md +0 -180
  152. package/template/.agent/rules/server/10-background-jobs-v2.md +0 -185
  153. package/template/.agent/rules/server/11-rate-limiting-v2.md +0 -210
  154. package/template/.agent/rules/server/12-performance-optimization.md +0 -567
  155. package/template/.claude/rules/client-01-project-structure.md +0 -327
  156. package/template/.claude/rules/client-02-component-patterns.md +0 -250
  157. package/template/.claude/rules/client-03-typescript-rules.md +0 -227
  158. package/template/.claude/rules/client-04-state-management.md +0 -475
  159. package/template/.claude/rules/client-05-api-integration.md +0 -130
  160. package/template/.claude/rules/client-06-forms-validation.md +0 -130
  161. package/template/.claude/rules/client-07-common-patterns.md +0 -151
  162. package/template/.claude/rules/client-08-color-system.md +0 -94
  163. package/template/.claude/rules/client-09-security-rules.md +0 -98
  164. package/template/.claude/rules/client-10-testing-strategy.md +0 -371
  165. package/template/.claude/rules/global-ai-edit-safety.md +0 -39
  166. package/template/.claude/rules/server-01-db-and-migrations.md +0 -243
  167. package/template/.claude/rules/server-02-general-rules.md +0 -112
  168. package/template/.claude/rules/server-03-migrations.md +0 -21
  169. package/template/.claude/rules/server-04-pagination.md +0 -131
  170. package/template/.claude/rules/server-05-project-conventions.md +0 -72
  171. package/template/.claude/rules/server-06-response-handling.md +0 -174
  172. package/template/.claude/rules/server-07-testing-strategy.md +0 -507
  173. package/template/.claude/rules/server-08-observability.md +0 -181
  174. package/template/.claude/rules/server-10-background-jobs-v2.md +0 -186
  175. package/template/.claude/rules/server-11-rate-limiting-v2.md +0 -211
  176. package/template/.claude/rules/server-12-performance-optimization.md +0 -568
  177. package/template/.cursor/rules/client-01-project-structure.mdc +0 -327
  178. package/template/.cursor/rules/client-02-component-patterns.mdc +0 -250
  179. package/template/.cursor/rules/client-03-typescript-rules.mdc +0 -227
  180. package/template/.cursor/rules/client-04-state-management.mdc +0 -475
  181. package/template/.cursor/rules/client-05-api-integration.mdc +0 -130
  182. package/template/.cursor/rules/client-06-forms-validation.mdc +0 -130
  183. package/template/.cursor/rules/client-07-common-patterns.mdc +0 -151
  184. package/template/.cursor/rules/client-08-color-system.mdc +0 -94
  185. package/template/.cursor/rules/client-09-security-rules.mdc +0 -98
  186. package/template/.cursor/rules/client-10-testing-strategy.mdc +0 -371
  187. package/template/.cursor/rules/global-ai-edit-safety.mdc +0 -39
  188. package/template/.cursor/rules/server-01-db-and-migrations.mdc +0 -243
  189. package/template/.cursor/rules/server-02-general-rules.mdc +0 -112
  190. package/template/.cursor/rules/server-03-migrations.mdc +0 -21
  191. package/template/.cursor/rules/server-04-pagination.mdc +0 -131
  192. package/template/.cursor/rules/server-05-project-conventions.mdc +0 -72
  193. package/template/.cursor/rules/server-06-response-handling.mdc +0 -174
  194. package/template/.cursor/rules/server-07-testing-strategy.mdc +0 -507
  195. package/template/.cursor/rules/server-08-observability.mdc +0 -181
  196. package/template/.cursor/rules/server-09-api-documentation-v2.mdc +0 -169
  197. package/template/.cursor/rules/server-10-background-jobs-v2.mdc +0 -186
  198. package/template/.cursor/rules/server-11-rate-limiting-v2.mdc +0 -211
  199. package/template/.cursor/rules/server-12-performance-optimization.mdc +0 -568
  200. package/template/CLAUDE.md +0 -207
  201. package/template/server/.tsc-aliasrc.json +0 -13
  202. package/template/server/IMPORT_FIX_CHECKLIST.md +0 -98
  203. package/template/server/IMPORT_FIX_COMPLETE.md +0 -89
  204. package/template/server/README.md +0 -183
  205. package/template/server/REMAINING_IMPORT_FIXES.md +0 -150
  206. package/template/server/SECURITY.md +0 -190
  207. package/template/server/Tigra-API.postman_collection.json +0 -733
  208. package/template/server/biome.json +0 -42
  209. package/template/server/scripts/fix-all-imports.ps1 +0 -52
  210. package/template/server/scripts/fix-imports-reference.ps1 +0 -16
  211. package/template/server/scripts/fix-imports.mjs +0 -55
  212. package/template/server/scripts/setup-env.js +0 -50
  213. package/template/server/scripts/wait-for-db.js +0 -60
  214. package/template/server/src/hooks/request-timing.hook.ts +0 -26
  215. package/template/server/src/libs/auth/authenticate.middleware.ts +0 -22
  216. package/template/server/src/libs/auth/rbac.middleware.test.ts +0 -134
  217. package/template/server/src/libs/auth/rbac.middleware.ts +0 -147
  218. package/template/server/src/libs/db.ts +0 -76
  219. package/template/server/src/libs/error-handler.ts +0 -89
  220. package/template/server/src/libs/queue.ts +0 -79
  221. package/template/server/src/modules/admin/admin.controller.ts +0 -122
  222. package/template/server/src/modules/admin/admin.routes.ts +0 -62
  223. package/template/server/src/modules/admin/admin.schemas.ts +0 -35
  224. package/template/server/src/modules/admin/admin.service.ts +0 -167
  225. package/template/server/src/modules/auth/auth.integration.test.ts +0 -150
  226. package/template/server/src/modules/auth/auth.service.test.ts +0 -119
  227. package/template/server/src/modules/auth/auth.types.ts +0 -97
  228. package/template/server/src/modules/resources/resources.controller.ts +0 -218
  229. package/template/server/src/modules/resources/resources.repo.ts +0 -253
  230. package/template/server/src/modules/resources/resources.routes.ts +0 -116
  231. package/template/server/src/modules/resources/resources.schemas.ts +0 -146
  232. package/template/server/src/modules/resources/resources.service.ts +0 -218
  233. package/template/server/src/modules/resources/resources.types.ts +0 -73
  234. package/template/server/src/plugins/rate-limit.plugin.ts +0 -21
  235. package/template/server/src/plugins/security.plugin.ts +0 -21
  236. package/template/server/src/routes/health.routes.ts +0 -31
  237. package/template/server/src/types/fastify.d.ts +0 -36
  238. package/template/server/src/utils/errors.ts +0 -108
  239. package/template/server/src/utils/pagination.ts +0 -120
  240. package/template/server/src/utils/response.ts +0 -110
  241. package/template/server/src/workers/file.worker.ts +0 -106
  242. package/template/server/tsconfig.build.json +0 -30
  243. package/template/server/tsconfig.test.json +0 -22
@@ -1,185 +0,0 @@
1
- ---
2
- trigger: always_on
3
- ---
4
-
5
- > **SCOPE**: These rules apply specifically to the **server** directory.
6
-
7
- # Background Jobs & Queue Processing
8
-
9
- ## Stack
10
-
11
- ```json
12
- {
13
- "dependencies": {
14
- "bullmq": "^5.0.0",
15
- "ioredis": "^5.3.0"
16
- }
17
- }
18
- ```
19
-
20
- ## Redis Setup
21
-
22
- ```typescript
23
- // libs/redis.ts
24
- import Redis from 'ioredis';
25
-
26
- export const redis = new Redis({
27
- host: process.env.REDIS_HOST || 'localhost',
28
- port: parseInt(process.env.REDIS_PORT || '6379'),
29
- maxRetriesPerRequest: null, // Required for BullMQ
30
- });
31
- ```
32
-
33
- ## Queue Setup
34
-
35
- ```typescript
36
- // libs/queue.ts
37
- import { Queue, Worker, QueueEvents } from 'bullmq';
38
- import { redis } from './redis';
39
-
40
- export const emailQueue = new Queue('emails', {
41
- connection: redis,
42
- defaultJobOptions: {
43
- attempts: 3,
44
- backoff: { type: 'exponential', delay: 2000 },
45
- removeOnComplete: { age: 3600, count: 100 },
46
- removeOnFail: { age: 86400 },
47
- },
48
- });
49
- ```
50
-
51
- ## Worker Pattern
52
-
53
- ```typescript
54
- // workers/email.worker.ts
55
- import { Worker, Job } from 'bullmq';
56
-
57
- interface EmailJobData {
58
- to: string;
59
- subject: string;
60
- body: string;
61
- }
62
-
63
- export const emailWorker = new Worker<EmailJobData>(
64
- 'emails',
65
- async (job: Job<EmailJobData>) => {
66
- const { to, subject, body } = job.data;
67
-
68
- logger.info({ jobId: job.id, to }, 'Processing email');
69
-
70
- await sendEmail({ to, subject, body });
71
-
72
- return { success: true, sentAt: new Date().toISOString() };
73
- },
74
- {
75
- connection: redis,
76
- concurrency: 5,
77
- limiter: { max: 100, duration: 60000 }, // 100 jobs/minute
78
- }
79
- );
80
- ```
81
-
82
- ## Job Patterns
83
-
84
- ### 1. Immediate Background Job
85
- ```typescript
86
- // Add to queue (non-blocking)
87
- await emailQueue.add('welcome-email', {
88
- to: user.email,
89
- subject: 'Welcome!',
90
- body: 'Thanks for signing up',
91
- });
92
- ```
93
-
94
- ### 2. Delayed Job
95
- ```typescript
96
- // Send after 24 hours
97
- await emailQueue.add(
98
- 'reminder-email',
99
- { to: user.email, subject: 'Reminder', body: 'Complete your profile' },
100
- { delay: 24 * 60 * 60 * 1000 }
101
- );
102
- ```
103
-
104
- ### 3. Scheduled Job (Cron)
105
- ```typescript
106
- // Daily at 2 AM
107
- await cleanupQueue.add(
108
- 'daily-cleanup',
109
- {},
110
- { repeat: { pattern: '0 2 * * *' } }
111
- );
112
- ```
113
-
114
- ### 4. Priority Job
115
- ```typescript
116
- await paymentQueue.add(
117
- 'process-payment',
118
- { orderId, amount },
119
- { priority: 1 } // Lower = higher priority
120
- );
121
- ```
122
-
123
- ## Error Handling
124
-
125
- ```typescript
126
- emailWorker.on('failed', (job, error) => {
127
- logger.error({ jobId: job?.id, error }, 'Job failed');
128
-
129
- // Move to dead letter queue after all retries
130
- if (job && job.attemptsMade >= job.opts.attempts!) {
131
- deadLetterQueue.add('failed-email', {
132
- originalJob: job.data,
133
- failedReason: error.message,
134
- });
135
- }
136
- });
137
- ```
138
-
139
- ## Graceful Shutdown
140
-
141
- ```typescript
142
- // server.ts
143
- const workers = [emailWorker, fileWorker];
144
-
145
- async function gracefulShutdown() {
146
- logger.info('Shutting down workers...');
147
- await Promise.all(workers.map((w) => w.close()));
148
- process.exit(0);
149
- }
150
-
151
- process.on('SIGTERM', gracefulShutdown);
152
- process.on('SIGINT', gracefulShutdown);
153
- ```
154
-
155
- ## Use Cases
156
-
157
- - **Email sending** (welcome, verification, notifications)
158
- - **File processing** (image thumbnails, video encoding)
159
- - **Report generation** (PDFs, exports)
160
- - **Data cleanup** (expired records, temp files)
161
- - **External API calls** (webhooks, third-party sync)
162
-
163
- ## Best Practices
164
-
165
- ### ✅ DO:
166
- - Use background jobs for slow operations (>1s)
167
- - Set appropriate retry strategies
168
- - Implement rate limiting for external APIs
169
- - Monitor job failures
170
- - Clean up old jobs
171
-
172
- ### ❌ DON'T:
173
- - Block HTTP responses with heavy processing
174
- - Forget error handling
175
- - Skip monitoring
176
- - Use queues for everything (simple tasks can run inline)
177
-
178
- ## Checklist
179
-
180
- - [ ] BullMQ and Redis installed
181
- - [ ] Queues created with retry config
182
- - [ ] Workers implemented with error handling
183
- - [ ] Graceful shutdown configured
184
- - [ ] Job monitoring in place
185
- - [ ] Dead letter queue for failures
@@ -1,210 +0,0 @@
1
- ---
2
- trigger: always_on
3
- ---
4
-
5
- > **SCOPE**: These rules apply specifically to the **server** directory.
6
-
7
- # Rate Limiting & Throttling
8
-
9
- ## Stack
10
-
11
- ```json
12
- {
13
- "dependencies": {
14
- "@fastify/rate-limit": "^9.0.0",
15
- "ioredis": "^5.3.0"
16
- }
17
- }
18
- ```
19
-
20
- ## Basic Setup
21
-
22
- ```typescript
23
- // app.ts
24
- import rateLimit from '@fastify/rate-limit';
25
- import { redis } from './libs/redis';
26
-
27
- await app.register(rateLimit, {
28
- global: true,
29
- max: 100,
30
- timeWindow: '15 minutes',
31
- redis,
32
- nameSpace: 'rate-limit:',
33
- addHeaders: {
34
- 'x-ratelimit-limit': true,
35
- 'x-ratelimit-remaining': true,
36
- 'x-ratelimit-reset': true,
37
- 'retry-after': true,
38
- },
39
- errorResponseBuilder: (request, context) => ({
40
- success: false,
41
- error: {
42
- code: 'RATE_LIMIT_EXCEEDED',
43
- message: `Rate limit exceeded. Retry in ${Math.ceil(context.ttl / 1000)}s.`,
44
- },
45
- }),
46
- });
47
- ```
48
-
49
- ## Per-Route Limits
50
-
51
- ```typescript
52
- // Disable global, configure per route
53
- await app.register(rateLimit, { global: false, redis });
54
-
55
- // Strict limit for login
56
- app.post('/auth/login', {
57
- config: {
58
- rateLimit: {
59
- max: 5,
60
- timeWindow: '15 minutes',
61
- },
62
- },
63
- handler: authController.login,
64
- });
65
-
66
- // Generous limit for authenticated routes
67
- app.get('/resources', {
68
- preHandler: [app.authenticate],
69
- config: {
70
- rateLimit: {
71
- max: 1000,
72
- timeWindow: '15 minutes',
73
- },
74
- },
75
- handler: resourceController.listResources,
76
- });
77
- ```
78
-
79
- ## Custom Rate Limit Keys
80
-
81
- ```typescript
82
- await app.register(rateLimit, {
83
- redis,
84
- keyGenerator: (request) => {
85
- // Authenticated: rate limit by user ID
86
- if (request.user) {
87
- return `user:${request.user.id}`;
88
- }
89
- // Anonymous: rate limit by IP
90
- return `ip:${request.ip}`;
91
- },
92
- });
93
- ```
94
-
95
- ## User-Based Tiered Limits
96
-
97
- ```typescript
98
- await app.register(rateLimit, {
99
- redis,
100
- max: async (request) => {
101
- if (!request.user) return 100; // Anonymous
102
- if (request.user.role === 'ADMIN') return 10000;
103
- if (request.user.tier === 'PREMIUM') return 5000;
104
- return 1000; // Standard
105
- },
106
- });
107
- ```
108
-
109
- ## Rate Limit Tiers
110
-
111
- ```typescript
112
- // lib/constants/rate-limits.ts
113
- export const RATE_LIMITS = {
114
- LOGIN: { max: 5, timeWindow: '15 minutes' },
115
- REGISTER: { max: 3, timeWindow: '1 hour' },
116
- PASSWORD_RESET: { max: 3, timeWindow: '1 hour' },
117
- PUBLIC: { max: 100, timeWindow: '15 minutes' },
118
- AUTHENTICATED: { max: 1000, timeWindow: '15 minutes' },
119
- PREMIUM: { max: 5000, timeWindow: '15 minutes' },
120
- ADMIN: { max: 10000, timeWindow: '15 minutes' },
121
- FILE_UPLOAD: { max: 10, timeWindow: '1 hour' },
122
- } as const;
123
- ```
124
-
125
- ## Monitoring
126
-
127
- ```typescript
128
- await app.register(rateLimit, {
129
- redis,
130
- onExceeding: (request, key) => {
131
- logger.warn({ key, ip: request.ip, url: request.url }, 'Approaching limit');
132
- },
133
- onExceeded: (request, key) => {
134
- logger.error({ key, ip: request.ip, url: request.url }, 'Limit exceeded');
135
- },
136
- });
137
- ```
138
-
139
- ## Whitelist IPs
140
-
141
- ```typescript
142
- app.addHook('preHandler', async (request, reply) => {
143
- const whitelistedIPs = ['127.0.0.1', '::1'];
144
- if (whitelistedIPs.includes(request.ip)) {
145
- // @ts-ignore
146
- request.bypassRateLimit = true;
147
- }
148
- });
149
-
150
- await app.register(rateLimit, {
151
- redis,
152
- skip: (request) => request.bypassRateLimit === true,
153
- });
154
- ```
155
-
156
- ## Check Rate Limit Status
157
-
158
- ```typescript
159
- app.get('/me/rate-limit', {
160
- preHandler: [app.authenticate],
161
- handler: async (request, reply) => {
162
- const key = `user:${request.user.id}`;
163
- const current = await redis.get(`rate-limit:${key}`);
164
- const ttl = await redis.ttl(`rate-limit:${key}`);
165
-
166
- return {
167
- limit: 1000,
168
- used: parseInt(current || '0'),
169
- remaining: 1000 - parseInt(current || '0'),
170
- resetIn: ttl,
171
- };
172
- },
173
- });
174
- ```
175
-
176
- ## Strategy Summary
177
-
178
- | Endpoint | Max | Window | Key |
179
- |----------|-----|--------|-----|
180
- | Login | 5 | 15 min | IP |
181
- | Register | 3 | 1 hour | IP + email |
182
- | Public API | 100 | 15 min | IP |
183
- | Authenticated | 1000 | 15 min | User ID |
184
- | Premium | 5000 | 15 min | User ID |
185
- | Admin | 10000 | 15 min | User ID |
186
-
187
- ## Best Practices
188
-
189
- ### ✅ DO:
190
- - Use Redis for distributed rate limiting
191
- - Set stricter limits for auth endpoints
192
- - Return helpful error messages with retry time
193
- - Log rate limit violations
194
- - Add rate limit headers to responses
195
- - Whitelist localhost for testing
196
-
197
- ### ❌ DON'T:
198
- - Use in-memory rate limiting in production
199
- - Apply same limits to all endpoints
200
- - Block users permanently without investigation
201
- - Forget to test rate limits
202
-
203
- ## Checklist
204
-
205
- - [ ] Rate limiting configured with Redis
206
- - [ ] Per-route limits set appropriately
207
- - [ ] Custom error responses implemented
208
- - [ ] Rate limit headers enabled
209
- - [ ] Monitoring and logging in place
210
- - [ ] Whitelist configured for testing