create-tigra 2.1.5 → 2.3.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 (39) hide show
  1. package/bin/create-tigra.js +2 -0
  2. package/package.json +4 -1
  3. package/template/_claude/commands/create-client.md +1 -4
  4. package/template/_claude/commands/create-server.md +0 -1
  5. package/template/_claude/rules/client/01-project-structure.md +0 -3
  6. package/template/_claude/rules/client/03-data-and-state.md +1 -1
  7. package/template/_claude/rules/server/project-conventions.md +13 -0
  8. package/template/client/package.json +2 -1
  9. package/template/server/.env.example +23 -0
  10. package/template/server/.env.example.production +21 -0
  11. package/template/server/package.json +2 -1
  12. package/template/server/postman/collection.json +524 -0
  13. package/template/server/postman/environment.json +31 -0
  14. package/template/server/prisma/schema.prisma +17 -1
  15. package/template/server/src/app.ts +43 -10
  16. package/template/server/src/config/env.ts +9 -0
  17. package/template/server/src/config/rate-limit.config.ts +114 -0
  18. package/template/server/src/jobs/cleanup-deleted-accounts.job.ts +80 -0
  19. package/template/server/src/{libs/cleanup.ts → jobs/cleanup-expired-auth.job.ts} +10 -4
  20. package/template/server/src/jobs/index.ts +20 -0
  21. package/template/server/src/libs/auth.ts +45 -1
  22. package/template/server/src/libs/ip-block.ts +206 -0
  23. package/template/server/src/libs/requestLogger.ts +1 -1
  24. package/template/server/src/libs/storage/file-storage.service.ts +65 -18
  25. package/template/server/src/libs/storage/file-validator.ts +4 -11
  26. package/template/server/src/libs/storage/image-optimizer.service.ts +1 -1
  27. package/template/server/src/modules/admin/admin.controller.ts +42 -0
  28. package/template/server/src/modules/admin/admin.routes.ts +45 -0
  29. package/template/server/src/modules/auth/auth.repo.ts +18 -0
  30. package/template/server/src/modules/auth/auth.routes.ts +10 -30
  31. package/template/server/src/modules/auth/auth.service.ts +52 -26
  32. package/template/server/src/modules/users/users.controller.ts +92 -5
  33. package/template/server/src/modules/users/users.repo.ts +27 -0
  34. package/template/server/src/modules/users/users.routes.ts +210 -19
  35. package/template/server/src/modules/users/users.schemas.ts +62 -4
  36. package/template/server/src/modules/users/users.service.ts +124 -3
  37. package/template/server/src/shared/types/index.ts +2 -0
  38. package/template/server/tsconfig.json +2 -1
  39. package/template/server/uploads/avatars/.gitkeep +0 -1
@@ -21,6 +21,8 @@ const FILES_TO_REPLACE = [
21
21
  'server/docker-compose.yml',
22
22
  'client/package.json',
23
23
  'client/.env.example',
24
+ 'server/postman/collection.json',
25
+ 'server/postman/environment.json',
24
26
  ];
25
27
 
26
28
  // Directories/files to skip when copying
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-tigra",
3
- "version": "2.1.5",
3
+ "version": "2.3.0",
4
4
  "type": "module",
5
5
  "description": "Create a production-ready full-stack app with Next.js 16 + Fastify 5 + Prisma + Redis",
6
6
  "bin": {
@@ -39,6 +39,9 @@
39
39
  "url": "https://github.com/blessandsoul/create-tigra/issues"
40
40
  },
41
41
  "homepage": "https://github.com/blessandsoul/create-tigra#readme",
42
+ "scripts": {
43
+ "create:test": "node -e \"import('fs').then(f=>f.rmSync('testapp',{recursive:true,force:true}))\" && node bin/create-tigra.js testapp"
44
+ },
42
45
  "dependencies": {
43
46
  "chalk": "^5.4.1",
44
47
  "commander": "^13.1.0",
@@ -180,8 +180,6 @@ export const API_ENDPOINTS = {
180
180
  LOGOUT: '/auth/logout',
181
181
  REFRESH: '/auth/refresh',
182
182
  ME: '/auth/me',
183
- VERIFY_EMAIL: '/auth/verify-email',
184
- RESEND_VERIFICATION: '/auth/resend-verification',
185
183
  REQUEST_PASSWORD_RESET: '/auth/request-password-reset',
186
184
  RESET_PASSWORD: '/auth/reset-password',
187
185
  },
@@ -199,7 +197,6 @@ export const ROUTES = {
199
197
  HOME: '/',
200
198
  LOGIN: '/login',
201
199
  REGISTER: '/register',
202
- VERIFY_EMAIL: '/verify-email',
203
200
  RESET_PASSWORD: '/reset-password',
204
201
  DASHBOARD: '/dashboard',
205
202
  PROFILE: '/profile',
@@ -369,7 +366,7 @@ Auth types from `02-components-and-types.md`:
369
366
 
370
367
  #### `src/features/auth/services/auth.service.ts`
371
368
  Auth service class from `03-data-and-state.md`:
372
- - `register`, `login`, `logout`, `refreshToken`, `getMe`, `verifyEmail`, `requestPasswordReset`, `resetPassword`
369
+ - `register`, `login`, `logout`, `refreshToken`, `getMe`, `requestPasswordReset`, `resetPassword`
373
370
  - Uses `apiClient` and `API_ENDPOINTS`
374
371
  - Singleton export: `export const authService = new AuthService();`
375
372
 
@@ -325,7 +325,6 @@ model User {
325
325
  lastName String
326
326
  role String @default("USER")
327
327
  isActive Boolean @default(true)
328
- emailVerified Boolean @default(false)
329
328
  deletedAt DateTime?
330
329
  createdAt DateTime @default(now())
331
330
  updatedAt DateTime @updatedAt
@@ -78,8 +78,6 @@ export const API_ENDPOINTS = {
78
78
  LOGOUT: '/auth/logout',
79
79
  REFRESH: '/auth/refresh',
80
80
  ME: '/auth/me',
81
- VERIFY_EMAIL: '/auth/verify-email',
82
- RESEND_VERIFICATION: '/auth/resend-verification',
83
81
  REQUEST_PASSWORD_RESET: '/auth/request-password-reset',
84
82
  RESET_PASSWORD: '/auth/reset-password',
85
83
  },
@@ -103,7 +101,6 @@ export const ROUTES = {
103
101
  HOME: '/',
104
102
  LOGIN: '/login',
105
103
  REGISTER: '/register',
106
- VERIFY_EMAIL: '/verify-email',
107
104
  RESET_PASSWORD: '/reset-password',
108
105
  DASHBOARD: '/dashboard',
109
106
  PROFILE: '/profile',
@@ -92,7 +92,7 @@ class ItemService {
92
92
  export const itemService = new ItemService();
93
93
  ```
94
94
 
95
- Auth service methods: `register`, `login`, `logout`, `refreshToken`, `getMe`, `verifyEmail`, `requestPasswordReset`, `resetPassword`.
95
+ Auth service methods: `register`, `login`, `logout`, `refreshToken`, `getMe`, `requestPasswordReset`, `resetPassword`.
96
96
 
97
97
  ---
98
98
 
@@ -212,3 +212,16 @@ const apiClient = axios.create({ ...httpClient.defaults, baseURL: 'https://api.e
212
212
  - Always use `httpClient` — never `fetch`, `node:http`, or inline `axios.create()`.
213
213
  - Never add auth headers, cookies, or credentials to the singleton itself.
214
214
  - Never log response bodies (may contain PII or secrets).
215
+
216
+ ## File Storage
217
+
218
+ Upload directory structure: `uploads/users/{userId}/<media-type>/`
219
+
220
+ | Media type | Path | Example |
221
+ |---|---|---|
222
+ | Avatar | `uploads/users/{userId}/avatar/` | `uploads/users/abc123/avatar/john-doe-avatar.webp` |
223
+
224
+ - All user media lives under `uploads/users/{userId}/` for easy per-user cleanup.
225
+ - On account purge, delete the entire `uploads/users/{userId}/` directory via `deleteUserMedia()`.
226
+ - Public URL pattern: `/uploads/users/{userId}/<media-type>/{filename}`
227
+ - New media types follow the same pattern: add a subfolder under the user directory.
@@ -6,7 +6,8 @@
6
6
  "dev": "next dev",
7
7
  "build": "next build",
8
8
  "start": "next start",
9
- "lint": "eslint src/"
9
+ "lint": "eslint src/",
10
+ "generate:env": "node -e \"import('fs').then(f=>{if(f.existsSync('.env'))console.log('.env already exists, skipping');else{f.copyFileSync('.env.example','.env');console.log('.env created from .env.example')}})\""
10
11
  },
11
12
  "dependencies": {
12
13
  "@hookform/resolvers": "^5.2.2",
@@ -39,6 +39,29 @@ REDIS_MAX_RETRIES=3
39
39
  # Connection timeout in milliseconds
40
40
  REDIS_CONNECT_TIMEOUT=10000
41
41
 
42
+ # ===================================================================
43
+ # RATE LIMITING
44
+ # ===================================================================
45
+
46
+ # Master switch to enable/disable rate limiting (default: true)
47
+ # Set to false in development to disable all rate limits
48
+ RATE_LIMIT_ENABLED=true
49
+
50
+ # Multiply all rate limit max values by this factor (default: 1)
51
+ # Set to 10 in development for 10x headroom, or 0.5 for tighter limits
52
+ RATE_LIMIT_MULTIPLIER=1
53
+
54
+ # Optional: Override specific critical route limits (uses defaults if not set)
55
+ # RATE_LIMIT_AUTH_LOGIN_MAX=10
56
+ # RATE_LIMIT_AUTH_REGISTER_MAX=5
57
+
58
+ # ===================================================================
59
+ # FILE UPLOAD
60
+ # ===================================================================
61
+
62
+ # Maximum file upload size in MB (default: 10)
63
+ MAX_FILE_SIZE_MB=10
64
+
42
65
  # ===================================================================
43
66
  # DOCKER PORTS (auto-generated, unique per project)
44
67
  # ===================================================================
@@ -39,6 +39,27 @@ REDIS_URL="redis://:REDIS_PASSWORD@redis.internal:6379"
39
39
  REDIS_MAX_RETRIES=5
40
40
  REDIS_CONNECT_TIMEOUT=5000
41
41
 
42
+ # ===================================================================
43
+ # RATE LIMITING
44
+ # ===================================================================
45
+
46
+ # Always enabled in production
47
+ RATE_LIMIT_ENABLED=true
48
+
49
+ # Production: keep at 1 (default limits are tuned for production)
50
+ RATE_LIMIT_MULTIPLIER=1
51
+
52
+ # Tight limits for sensitive auth routes in production
53
+ RATE_LIMIT_AUTH_LOGIN_MAX=10
54
+ RATE_LIMIT_AUTH_REGISTER_MAX=5
55
+
56
+ # ===================================================================
57
+ # FILE UPLOAD
58
+ # ===================================================================
59
+
60
+ # Maximum file upload size in MB
61
+ MAX_FILE_SIZE_MB=10
62
+
42
63
  # ===================================================================
43
64
  # JWT AUTHENTICATION
44
65
  # ===================================================================
@@ -22,7 +22,8 @@
22
22
  "redis:flush": "tsx scripts/flush-redis.ts",
23
23
  "docker:up": "docker compose up -d",
24
24
  "docker:down": "docker compose down",
25
- "docker:logs": "docker compose logs -f"
25
+ "docker:logs": "docker compose logs -f",
26
+ "generate:env": "node -e \"import('fs').then(f=>{if(f.existsSync('.env'))console.log('.env already exists, skipping');else{f.copyFileSync('.env.example','.env');console.log('.env created from .env.example')}})\""
26
27
  },
27
28
  "prisma": {
28
29
  "seed": "tsx prisma/seed.ts"