create-tigra 1.0.0 → 1.0.2
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.
- package/bin/create-tigra.js +7 -3
- package/package.json +1 -1
- package/template/server/.env.example +69 -148
- package/template/server/README.md +25 -17
- package/template/server/package.json +5 -7
- package/template/server/prisma/schema.prisma +2 -1
- package/template/server/scripts/setup-env.js +50 -0
- package/template/server/scripts/wait-for-db.js +3 -3
- package/template/server/src/app.ts +0 -3
- package/template/server/src/config/env.ts +0 -7
- package/template/server/src/modules/admin/admin.routes.ts +0 -38
- package/template/server/src/modules/auth/auth.routes.ts +8 -129
- package/template/server/src/modules/resources/resources.routes.ts +10 -249
- package/template/.agent/rules/server/09-api-documentation-v2.md +0 -168
- package/template/.claude/rules/server-09-api-documentation-v2.md +0 -169
- package/template/server/src/libs/swagger-schemas.ts +0 -16
- package/template/server/src/plugins/swagger.plugin.ts +0 -41
- package/template/server/tsconfig.build.tsbuildinfo +0 -1
- /package/template/server/{postman_collection.json → Tigra-API.postman_collection.json} +0 -0
package/bin/create-tigra.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import prompts from 'prompts';
|
|
@@ -80,7 +80,6 @@ const filesToProcess = [
|
|
|
80
80
|
'CLAUDE.md',
|
|
81
81
|
// Server files
|
|
82
82
|
'server/package.json',
|
|
83
|
-
'server/.env',
|
|
84
83
|
'server/.env.example',
|
|
85
84
|
'server/docker-compose.yml',
|
|
86
85
|
'server/README.md',
|
|
@@ -100,6 +99,11 @@ const excludePatterns = [
|
|
|
100
99
|
'coverage',
|
|
101
100
|
'build-errors.txt',
|
|
102
101
|
'.env.local',
|
|
102
|
+
'.env',
|
|
103
|
+
'*.tsbuildinfo',
|
|
104
|
+
'tsconfig.build.tsbuildinfo',
|
|
105
|
+
'.DS_Store',
|
|
106
|
+
'Thumbs.db',
|
|
103
107
|
];
|
|
104
108
|
|
|
105
109
|
// ==============================================
|
|
@@ -278,7 +282,7 @@ program
|
|
|
278
282
|
console.log();
|
|
279
283
|
console.log(chalk.gray(' URLs after starting:'));
|
|
280
284
|
console.log(chalk.gray(' API Server: http://localhost:3000'));
|
|
281
|
-
console.log(chalk.gray('
|
|
285
|
+
console.log(chalk.gray(' Health Check: http://localhost:3000/health'));
|
|
282
286
|
console.log(chalk.gray(' phpMyAdmin: http://localhost:8080 (root / password)'));
|
|
283
287
|
console.log(chalk.gray(' Redis UI: http://localhost:8081'));
|
|
284
288
|
console.log();
|
package/package.json
CHANGED
|
@@ -1,148 +1,69 @@
|
|
|
1
|
-
# ==============================================
|
|
2
|
-
# SERVER CONFIGURATION
|
|
3
|
-
# ==============================================
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
#
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
# ==============================================
|
|
18
|
-
#
|
|
19
|
-
# ==============================================
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
#
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
#
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
#
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
#
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
#
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
# ==============================================
|
|
65
|
-
|
|
66
|
-
#
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
# For production:
|
|
71
|
-
# CORS_ALLOWED_ORIGINS=https://yourdomain.com,https://www.yourdomain.com
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
# ==============================================
|
|
75
|
-
# FILE UPLOAD CONFIGURATION
|
|
76
|
-
# ==============================================
|
|
77
|
-
|
|
78
|
-
# Maximum file size in bytes (10MB default)
|
|
79
|
-
MAX_FILE_SIZE=10485760
|
|
80
|
-
|
|
81
|
-
# Allowed file types (comma-separated)
|
|
82
|
-
ALLOWED_FILE_TYPES=image/jpeg,image/png,image/webp,application/pdf
|
|
83
|
-
|
|
84
|
-
# Upload directory
|
|
85
|
-
UPLOAD_DIR=./uploads
|
|
86
|
-
|
|
87
|
-
# ==============================================
|
|
88
|
-
# RATE LIMITING
|
|
89
|
-
# ==============================================
|
|
90
|
-
|
|
91
|
-
# Global rate limit (requests per time window)
|
|
92
|
-
RATE_LIMIT_MAX=100
|
|
93
|
-
|
|
94
|
-
# Time window in milliseconds (15 minutes = 900000)
|
|
95
|
-
RATE_LIMIT_WINDOW=900000
|
|
96
|
-
|
|
97
|
-
# ==============================================
|
|
98
|
-
# MONITORING & ERROR TRACKING
|
|
99
|
-
# ==============================================
|
|
100
|
-
|
|
101
|
-
# ==============================================
|
|
102
|
-
# API DOCUMENTATION (Swagger)
|
|
103
|
-
# ==============================================
|
|
104
|
-
|
|
105
|
-
# Enable Swagger UI (true/false)
|
|
106
|
-
# Set to false in production for security
|
|
107
|
-
SWAGGER_ENABLED=true
|
|
108
|
-
|
|
109
|
-
# Swagger route prefix
|
|
110
|
-
SWAGGER_ROUTE=/docs
|
|
111
|
-
|
|
112
|
-
# ==============================================
|
|
113
|
-
# EXTERNAL SERVICES (Optional)
|
|
114
|
-
# ==============================================
|
|
115
|
-
|
|
116
|
-
# AWS S3 (for file storage)
|
|
117
|
-
# AWS_ACCESS_KEY_ID=
|
|
118
|
-
# AWS_SECRET_ACCESS_KEY=
|
|
119
|
-
# AWS_REGION=us-east-1
|
|
120
|
-
# AWS_S3_BUCKET=
|
|
121
|
-
|
|
122
|
-
# Stripe (for payments)
|
|
123
|
-
# STRIPE_SECRET_KEY=
|
|
124
|
-
# STRIPE_WEBHOOK_SECRET=
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
# ==============================================
|
|
129
|
-
# DEVELOPMENT TOOLS
|
|
130
|
-
# ==============================================
|
|
131
|
-
|
|
132
|
-
# Enable query logging in development
|
|
133
|
-
PRISMA_QUERY_LOG=false
|
|
134
|
-
|
|
135
|
-
# Enable slow query warnings (milliseconds)
|
|
136
|
-
SLOW_QUERY_THRESHOLD=1000
|
|
137
|
-
|
|
138
|
-
# ==============================================
|
|
139
|
-
# ADMIN SEED (Initial Setup)
|
|
140
|
-
# ==============================================
|
|
141
|
-
|
|
142
|
-
# Admin user email for database seeding
|
|
143
|
-
# Change this before running npm run prisma:seed
|
|
144
|
-
ADMIN_EMAIL=admin@{{PROJECT_NAME}}.dev
|
|
145
|
-
|
|
146
|
-
# Admin user password for database seeding
|
|
147
|
-
# CHANGE THIS IMMEDIATELY AFTER FIRST LOGIN!
|
|
148
|
-
ADMIN_PASSWORD=ChangeThisPassword123!
|
|
1
|
+
# ==============================================
|
|
2
|
+
# SERVER CONFIGURATION
|
|
3
|
+
# ==============================================
|
|
4
|
+
|
|
5
|
+
NODE_ENV=development
|
|
6
|
+
PORT=3000
|
|
7
|
+
API_PREFIX=/api/v1
|
|
8
|
+
LOG_LEVEL=info
|
|
9
|
+
|
|
10
|
+
# ==============================================
|
|
11
|
+
# DATABASE CONFIGURATION (MySQL)
|
|
12
|
+
# ==============================================
|
|
13
|
+
|
|
14
|
+
DATABASE_URL="mysql://root:{{DATABASE_PASSWORD}}@localhost:3306/{{DATABASE_NAME}}"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# ==============================================
|
|
18
|
+
# REDIS CONFIGURATION
|
|
19
|
+
# ==============================================
|
|
20
|
+
|
|
21
|
+
REDIS_HOST=localhost
|
|
22
|
+
REDIS_PORT=6379
|
|
23
|
+
REDIS_PASSWORD=
|
|
24
|
+
REDIS_DB=0
|
|
25
|
+
|
|
26
|
+
# ==============================================
|
|
27
|
+
# JWT AUTHENTICATION
|
|
28
|
+
# =============================================='
|
|
29
|
+
|
|
30
|
+
# enter strong jwt secret in production !
|
|
31
|
+
JWT_SECRET=123412341234123412341234123412341234123412341234123412341234
|
|
32
|
+
JWT_ACCESS_EXPIRATION=15m
|
|
33
|
+
JWT_REFRESH_EXPIRATION=7d
|
|
34
|
+
JWT_ISSUER={{PROJECT_NAME}}
|
|
35
|
+
|
|
36
|
+
# ==============================================
|
|
37
|
+
# CORS CONFIGURATION
|
|
38
|
+
# ==============================================
|
|
39
|
+
|
|
40
|
+
CORS_ALLOWED_ORIGINS=http://localhost:5173,http://localhost:3000
|
|
41
|
+
|
|
42
|
+
# ==============================================
|
|
43
|
+
# FILE UPLOAD CONFIGURATION
|
|
44
|
+
# ==============================================
|
|
45
|
+
|
|
46
|
+
MAX_FILE_SIZE=10485760
|
|
47
|
+
ALLOWED_FILE_TYPES=image/jpeg,image/png,image/webp,application/pdf
|
|
48
|
+
UPLOAD_DIR=./uploads
|
|
49
|
+
|
|
50
|
+
# ==============================================
|
|
51
|
+
# RATE LIMITING
|
|
52
|
+
# ==============================================
|
|
53
|
+
|
|
54
|
+
RATE_LIMIT_MAX=100
|
|
55
|
+
RATE_LIMIT_WINDOW=900000
|
|
56
|
+
|
|
57
|
+
# ==============================================
|
|
58
|
+
# DEVELOPMENT TOOLS
|
|
59
|
+
# ==============================================
|
|
60
|
+
|
|
61
|
+
PRISMA_QUERY_LOG=false
|
|
62
|
+
SLOW_QUERY_THRESHOLD=1000
|
|
63
|
+
|
|
64
|
+
# ==============================================
|
|
65
|
+
# ADMIN SEED (Initial Setup)
|
|
66
|
+
# ==============================================
|
|
67
|
+
|
|
68
|
+
ADMIN_EMAIL=admin@{{PROJECT_NAME}}.dev
|
|
69
|
+
ADMIN_PASSWORD=Admin123!
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
- Pagination with filters
|
|
10
10
|
- Rate limiting with Redis
|
|
11
11
|
- Background job processing (BullMQ)
|
|
12
|
-
- API documentation (Swagger/OpenAPI)
|
|
13
12
|
- Comprehensive error handling
|
|
14
13
|
- Request logging and monitoring
|
|
15
14
|
- Health checks
|
|
@@ -22,7 +21,6 @@
|
|
|
22
21
|
- **Validation**: Zod
|
|
23
22
|
- **Authentication**: JWT (jsonwebtoken)
|
|
24
23
|
- **Testing**: Vitest + Supertest
|
|
25
|
-
- **Documentation**: Swagger/OpenAPI 3.0
|
|
26
24
|
|
|
27
25
|
## Prerequisites
|
|
28
26
|
- Node.js 20 or higher
|
|
@@ -35,33 +33,43 @@
|
|
|
35
33
|
# 1. Install dependencies
|
|
36
34
|
npm install
|
|
37
35
|
|
|
38
|
-
# 2.
|
|
39
|
-
cp .env.example .env
|
|
40
|
-
# Edit .env and set required variables (DATABASE_URL, JWT_SECRET, etc.)
|
|
41
|
-
|
|
42
|
-
# 3. Start Docker services (MySQL + Redis)
|
|
36
|
+
# 2. Start Docker services (MySQL + Redis)
|
|
43
37
|
docker-compose up -d
|
|
44
38
|
|
|
45
|
-
#
|
|
46
|
-
npm run
|
|
47
|
-
|
|
48
|
-
# 5. Run database migrations
|
|
49
|
-
npx prisma migrate dev --name init
|
|
39
|
+
# 3. Initialize database (creates .env, waits for DB, runs migrations)
|
|
40
|
+
npm run db:init
|
|
50
41
|
|
|
51
|
-
#
|
|
42
|
+
# 4. Seed the database
|
|
52
43
|
npm run prisma:seed
|
|
53
44
|
|
|
54
|
-
#
|
|
45
|
+
# 5. Start development server
|
|
55
46
|
npm run dev
|
|
56
47
|
```
|
|
57
48
|
|
|
58
49
|
Server will start at http://localhost:3000
|
|
59
50
|
|
|
60
|
-
|
|
51
|
+
### Production Installation
|
|
52
|
+
|
|
53
|
+
For production deployments, install only production dependencies:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Install production dependencies only (faster, smaller)
|
|
57
|
+
npm install --omit=dev
|
|
58
|
+
|
|
59
|
+
# Generate Prisma Client
|
|
60
|
+
npx prisma generate
|
|
61
|
+
|
|
62
|
+
# Run migrations
|
|
63
|
+
npx prisma migrate deploy
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## API Endpoints
|
|
61
67
|
|
|
62
|
-
Once running,
|
|
63
|
-
- Swagger UI: http://localhost:3000/docs
|
|
68
|
+
Once running, you can access:
|
|
64
69
|
- Health Check: http://localhost:3000/health
|
|
70
|
+
- Auth endpoints: http://localhost:3000/api/v1/auth/*
|
|
71
|
+
- Resources endpoints: http://localhost:3000/api/v1/resources/*
|
|
72
|
+
- Admin endpoints: http://localhost:3000/api/v1/admin/*
|
|
65
73
|
|
|
66
74
|
## Available Scripts
|
|
67
75
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"version": "1.0.0",
|
|
4
4
|
"description": "{{PROJECT_DESCRIPTION}}",
|
|
5
5
|
"main": "dist/server.js",
|
|
6
|
-
"type": "
|
|
6
|
+
"type": "module",
|
|
7
7
|
"engines": {
|
|
8
8
|
"node": ">=20.0.0"
|
|
9
9
|
},
|
|
@@ -19,8 +19,9 @@
|
|
|
19
19
|
"test:watch": "vitest",
|
|
20
20
|
"test:coverage": "vitest run --coverage",
|
|
21
21
|
"test:e2e": "vitest run --config vitest.e2e.config.ts",
|
|
22
|
+
"env:setup": "node scripts/setup-env.js",
|
|
22
23
|
"db:wait": "node scripts/wait-for-db.js",
|
|
23
|
-
"db:init": "npm run db:wait && npx prisma migrate dev --name init",
|
|
24
|
+
"db:init": "npm run env:setup && npm run db:wait && npx prisma migrate dev --name init",
|
|
24
25
|
"prisma:generate": "prisma generate",
|
|
25
26
|
"prisma:migrate": "prisma migrate dev",
|
|
26
27
|
"prisma:migrate:deploy": "prisma migrate deploy",
|
|
@@ -48,8 +49,6 @@
|
|
|
48
49
|
"@fastify/helmet": "^13.0.0",
|
|
49
50
|
"@fastify/multipart": "^9.0.0",
|
|
50
51
|
"@fastify/rate-limit": "^10.2.0",
|
|
51
|
-
"@fastify/swagger": "^9.4.0",
|
|
52
|
-
"@fastify/swagger-ui": "^5.2.0",
|
|
53
52
|
"@prisma/client": "^6.2.0",
|
|
54
53
|
"bcryptjs": "^2.4.3",
|
|
55
54
|
"bullmq": "^5.34.0",
|
|
@@ -59,8 +58,7 @@
|
|
|
59
58
|
"jsonwebtoken": "^9.0.2",
|
|
60
59
|
"mysql2": "^3.11.5",
|
|
61
60
|
"pino": "^9.6.0",
|
|
62
|
-
"zod": "^3.24.0"
|
|
63
|
-
"zod-to-json-schema": "^3.24.0"
|
|
61
|
+
"zod": "^3.24.0"
|
|
64
62
|
},
|
|
65
63
|
"devDependencies": {
|
|
66
64
|
"@biomejs/biome": "^1.9.0",
|
|
@@ -68,9 +66,9 @@
|
|
|
68
66
|
"@types/jsonwebtoken": "^9.0.5",
|
|
69
67
|
"@types/node": "^22.10.0",
|
|
70
68
|
"@types/supertest": "^6.0.2",
|
|
69
|
+
"@vitest/coverage-v8": "^3.0.0",
|
|
71
70
|
"pino-pretty": "^13.0.0",
|
|
72
71
|
"prisma": "^6.2.0",
|
|
73
|
-
"@vitest/coverage-v8": "^3.0.0",
|
|
74
72
|
"supertest": "^7.1.0",
|
|
75
73
|
"tsc-alias": "^1.8.16",
|
|
76
74
|
"tsx": "^4.19.0",
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Setup environment file
|
|
5
|
+
* Copies .env.example to .env if .env doesn't exist
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
import { dirname } from 'path';
|
|
12
|
+
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = dirname(__filename);
|
|
15
|
+
|
|
16
|
+
const ROOT_DIR = path.resolve(__dirname, '..');
|
|
17
|
+
const ENV_FILE = path.join(ROOT_DIR, '.env');
|
|
18
|
+
const EXAMPLE_ENV_FILE = path.join(ROOT_DIR, '.env.example');
|
|
19
|
+
|
|
20
|
+
function setupEnv() {
|
|
21
|
+
// Check if .env already exists
|
|
22
|
+
if (fs.existsSync(ENV_FILE)) {
|
|
23
|
+
console.log('✓ .env file already exists');
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Check if .env.example exists
|
|
28
|
+
if (!fs.existsSync(EXAMPLE_ENV_FILE)) {
|
|
29
|
+
console.error('✗ .env.example file not found!');
|
|
30
|
+
console.error(' Please create a .env.example file first');
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Copy .env.example to .env
|
|
35
|
+
try {
|
|
36
|
+
fs.copyFileSync(EXAMPLE_ENV_FILE, ENV_FILE);
|
|
37
|
+
console.log('✓ Created .env file from .env.example');
|
|
38
|
+
console.log('');
|
|
39
|
+
console.log('⚠ IMPORTANT: Please update the following values in .env:');
|
|
40
|
+
console.log(' - DATABASE_URL (replace {{DATABASE_PASSWORD}} and {{DATABASE_NAME}})');
|
|
41
|
+
console.log(' - JWT_SECRET (use a strong secret in production)');
|
|
42
|
+
console.log(' - ADMIN_EMAIL and ADMIN_PASSWORD');
|
|
43
|
+
console.log('');
|
|
44
|
+
} catch (error) {
|
|
45
|
+
console.error('✗ Failed to create .env file:', error.message);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
setupEnv();
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* This script polls the database connection until it's available
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
import { createConnection } from 'mysql2/promise';
|
|
9
|
+
import { config } from 'dotenv';
|
|
10
|
+
import { resolve } from 'path';
|
|
11
11
|
|
|
12
12
|
// Load environment variables
|
|
13
13
|
config({ path: resolve(process.cwd(), '.env') });
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
* @see /mnt/project/02-general-rules.md
|
|
8
8
|
* @see /mnt/project/06-response-handling.md
|
|
9
9
|
* @see /mnt/project/08-observability.md
|
|
10
|
-
* @see /mnt/project/09-api-documentation-v2.md
|
|
11
10
|
* @see /mnt/project/11-rate-limiting-v2.md
|
|
12
11
|
*/
|
|
13
12
|
|
|
@@ -19,7 +18,6 @@ import logger from '@/libs/logger';
|
|
|
19
18
|
import { setupErrorHandler } from '@/libs/error-handler';
|
|
20
19
|
import { registerSecurityPlugins } from '@/plugins/security.plugin';
|
|
21
20
|
import { registerRateLimit } from '@/plugins/rate-limit.plugin';
|
|
22
|
-
import { registerSwagger } from '@/plugins/swagger.plugin';
|
|
23
21
|
import { registerRequestHooks } from '@/hooks/request-timing.hook';
|
|
24
22
|
import { authenticateMiddleware } from '@/libs/auth/authenticate.middleware';
|
|
25
23
|
import { healthRoutes } from '@/routes/health.routes';
|
|
@@ -47,7 +45,6 @@ const buildApp = async () => {
|
|
|
47
45
|
// 1. Plugins
|
|
48
46
|
await registerSecurityPlugins(app);
|
|
49
47
|
await registerRateLimit(app);
|
|
50
|
-
await registerSwagger(app);
|
|
51
48
|
|
|
52
49
|
// 2. Decorators
|
|
53
50
|
app.decorate('authenticate', authenticateMiddleware);
|
|
@@ -54,13 +54,6 @@ const envSchema = z.object({
|
|
|
54
54
|
RATE_LIMIT_MAX: z.coerce.number().int().positive().default(100),
|
|
55
55
|
RATE_LIMIT_WINDOW: z.coerce.number().int().positive().default(900000), // 15 minutes
|
|
56
56
|
|
|
57
|
-
// API Documentation Configuration
|
|
58
|
-
SWAGGER_ENABLED: z
|
|
59
|
-
.string()
|
|
60
|
-
.transform((val) => val === 'true')
|
|
61
|
-
.default('true'),
|
|
62
|
-
SWAGGER_ROUTE: z.string().default('/docs'),
|
|
63
|
-
|
|
64
57
|
// Development Tools
|
|
65
58
|
PRISMA_QUERY_LOG: z
|
|
66
59
|
.string()
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { FastifyInstance } from 'fastify';
|
|
2
|
-
import { toJsonSchema } from '@/libs/swagger-schemas';
|
|
3
2
|
import * as adminController from './admin.controller';
|
|
4
|
-
import * as schemas from './admin.schemas';
|
|
5
3
|
|
|
6
4
|
/**
|
|
7
5
|
* Admin Routes
|
|
@@ -13,12 +11,6 @@ export async function adminRoutes(app: FastifyInstance) {
|
|
|
13
11
|
* List all users with pagination
|
|
14
12
|
*/
|
|
15
13
|
app.get('/users', {
|
|
16
|
-
schema: {
|
|
17
|
-
description: 'List all users (admin only)',
|
|
18
|
-
tags: ['admin'],
|
|
19
|
-
querystring: toJsonSchema(schemas.ListUsersSchema, 'ListUsersSchema'),
|
|
20
|
-
security: [{ bearerAuth: [] }],
|
|
21
|
-
},
|
|
22
14
|
preHandler: [app.authenticate, app.requireAdmin()],
|
|
23
15
|
handler: adminController.listAllUsers,
|
|
24
16
|
});
|
|
@@ -28,12 +20,6 @@ export async function adminRoutes(app: FastifyInstance) {
|
|
|
28
20
|
* Get user details
|
|
29
21
|
*/
|
|
30
22
|
app.get('/users/:id', {
|
|
31
|
-
schema: {
|
|
32
|
-
description: 'Get user by ID (admin only)',
|
|
33
|
-
tags: ['admin'],
|
|
34
|
-
params: toJsonSchema(schemas.UserIdSchema, 'UserIdSchema'),
|
|
35
|
-
security: [{ bearerAuth: [] }],
|
|
36
|
-
},
|
|
37
23
|
preHandler: [app.authenticate, app.requireAdmin()],
|
|
38
24
|
handler: adminController.getUserById,
|
|
39
25
|
});
|
|
@@ -43,12 +29,6 @@ export async function adminRoutes(app: FastifyInstance) {
|
|
|
43
29
|
* Delete user
|
|
44
30
|
*/
|
|
45
31
|
app.delete('/users/:id', {
|
|
46
|
-
schema: {
|
|
47
|
-
description: 'Delete user (admin only)',
|
|
48
|
-
tags: ['admin'],
|
|
49
|
-
params: toJsonSchema(schemas.UserIdSchema, 'UserIdSchema'),
|
|
50
|
-
security: [{ bearerAuth: [] }],
|
|
51
|
-
},
|
|
52
32
|
preHandler: [app.authenticate, app.requireAdmin()],
|
|
53
33
|
handler: adminController.deleteUser,
|
|
54
34
|
});
|
|
@@ -58,13 +38,6 @@ export async function adminRoutes(app: FastifyInstance) {
|
|
|
58
38
|
* Change user role
|
|
59
39
|
*/
|
|
60
40
|
app.post('/users/:id/change-role', {
|
|
61
|
-
schema: {
|
|
62
|
-
description: 'Change user role (admin only)',
|
|
63
|
-
tags: ['admin'],
|
|
64
|
-
params: toJsonSchema(schemas.UserIdSchema, 'UserIdSchema'),
|
|
65
|
-
body: toJsonSchema(schemas.ChangeRoleSchema, 'ChangeRoleSchema'),
|
|
66
|
-
security: [{ bearerAuth: [] }],
|
|
67
|
-
},
|
|
68
41
|
preHandler: [app.authenticate, app.requireAdmin()],
|
|
69
42
|
handler: adminController.changeUserRole,
|
|
70
43
|
});
|
|
@@ -74,12 +47,6 @@ export async function adminRoutes(app: FastifyInstance) {
|
|
|
74
47
|
* Manually verify user email
|
|
75
48
|
*/
|
|
76
49
|
app.post('/users/:id/verify-email', {
|
|
77
|
-
schema: {
|
|
78
|
-
description: 'Verify user email manually (admin only)',
|
|
79
|
-
tags: ['admin'],
|
|
80
|
-
params: toJsonSchema(schemas.UserIdSchema, 'UserIdSchema'),
|
|
81
|
-
security: [{ bearerAuth: [] }],
|
|
82
|
-
},
|
|
83
50
|
preHandler: [app.authenticate, app.requireAdmin()],
|
|
84
51
|
handler: adminController.verifyUserEmail,
|
|
85
52
|
});
|
|
@@ -89,11 +56,6 @@ export async function adminRoutes(app: FastifyInstance) {
|
|
|
89
56
|
* Get system statistics
|
|
90
57
|
*/
|
|
91
58
|
app.get('/stats', {
|
|
92
|
-
schema: {
|
|
93
|
-
description: 'Get system statistics (admin only)',
|
|
94
|
-
tags: ['admin'],
|
|
95
|
-
security: [{ bearerAuth: [] }],
|
|
96
|
-
},
|
|
97
59
|
preHandler: [app.authenticate, app.requireAdmin()],
|
|
98
60
|
handler: adminController.getSystemStats,
|
|
99
61
|
});
|