create-craftjs 1.0.13 → 1.0.15
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/index.js +2 -0
- package/package.json +1 -1
- package/template/craft/commands/key-generate.js +12 -1
- package/template/package-lock.json +2 -2
- package/template/package.json +1 -1
- package/template/prisma/migrations/20250518142257_create_table_users/migration.sql +1 -1
- package/template/prisma/migrations/20260118135332_create_table_auth_refresh_tokens/migration.sql +16 -0
- package/template/prisma/schema.prisma +20 -4
- package/template/prisma/seed.ts +1 -1
- package/template/src/apidocs/auth-docs.ts +8 -28
- package/template/src/apidocs/users-docs.ts +87 -57
- package/template/src/config/database.ts +0 -4
- package/template/src/config/env.ts +2 -1
- package/template/src/config/logger.ts +2 -2
- package/template/src/controllers/auth-controller.ts +10 -4
- package/template/src/controllers/user-controller.ts +21 -17
- package/template/src/dtos/pagination-dto.ts +21 -0
- package/template/src/dtos/user-dto.ts +37 -16
- package/template/src/main.ts +2 -7
- package/template/src/middleware/auth-middleware.ts +41 -34
- package/template/src/repositories/auth-token-repository.ts +25 -0
- package/template/src/repositories/user-repository.ts +20 -9
- package/template/src/routes/auth-route.ts +3 -12
- package/template/src/routes/user-route.ts +5 -29
- package/template/src/services/auth-service.ts +56 -41
- package/template/src/services/user-service.ts +60 -30
- package/template/src/utils/cookieEncrypt.ts +39 -0
- package/template/src/utils/pagination.ts +32 -0
- package/template/src/utils/response.ts +9 -31
- package/template/src/utils/swagger.ts +10 -9
- package/template/src/utils/validation.ts +8 -1
- package/template/src/validations/user-validation.ts +25 -27
- package/template/test/user.test.ts +2 -2
- package/template/tsconfig.json +3 -2
- package/template/src/dtos/list-dto.ts +0 -12
package/bin/index.js
CHANGED
|
@@ -90,6 +90,7 @@ BASE_URL="http://localhost:4444"
|
|
|
90
90
|
BASE_API_URL="http://localhost:4444/api"
|
|
91
91
|
PORT=4444
|
|
92
92
|
JWT_SECRET=
|
|
93
|
+
COOKIE_ENCRYPTION_KEY=
|
|
93
94
|
`;
|
|
94
95
|
|
|
95
96
|
const envExampleContent = envContent.replace(/=.*/g, "=");
|
|
@@ -124,6 +125,7 @@ JWT_SECRET=
|
|
|
124
125
|
`node_modules
|
|
125
126
|
.env
|
|
126
127
|
dist
|
|
128
|
+
logs
|
|
127
129
|
`
|
|
128
130
|
);
|
|
129
131
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-craftjs",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.15",
|
|
4
4
|
"description": "A starter kit backend framework powered by Express, TypeScript, EJS Engine, and Prisma — designed for rapid development, simplicity, and scalability.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"create-craftjs": "bin/index.js"
|
|
@@ -32,10 +32,21 @@ function keyGenerate() {
|
|
|
32
32
|
envContent += `\APP_SECRET=${generateKey(32)}`;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
if (envContent.includes("COOKIE_ENCRYPTION_KEY=")) {
|
|
36
|
+
envContent = envContent.replace(
|
|
37
|
+
/COOKIE_ENCRYPTION_KEY=.*/g,
|
|
38
|
+
`COOKIE_ENCRYPTION_KEY=${generateKey(32)}`
|
|
39
|
+
);
|
|
40
|
+
} else {
|
|
41
|
+
envContent += `\COOKIE_ENCRYPTION_KEY=${generateKey(32)}`;
|
|
42
|
+
}
|
|
43
|
+
|
|
35
44
|
fs.writeFileSync(envPath, envContent);
|
|
36
45
|
|
|
37
46
|
console.log(
|
|
38
|
-
chalk.green(
|
|
47
|
+
chalk.green(
|
|
48
|
+
"✅ App Secret, JWT Secret , and Cookie Encryption Key generated successfully."
|
|
49
|
+
)
|
|
39
50
|
);
|
|
40
51
|
}
|
|
41
52
|
module.exports = keyGenerate;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "craftjs",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.15",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "craftjs",
|
|
9
|
-
"version": "1.0.
|
|
9
|
+
"version": "1.0.14",
|
|
10
10
|
"license": "UNLICENSED",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@prisma/client": "^6.6.0",
|
package/template/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "craftjs",
|
|
3
3
|
"description": "A starter kit backend framework powered by Express, TypeScript, EJS Engine, and Prisma — designed for rapid development, simplicity, and scalability.",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.15",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"express",
|
|
7
7
|
"typescript",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
-- CreateTable
|
|
2
2
|
CREATE TABLE `users` (
|
|
3
3
|
`id` VARCHAR(191) NOT NULL,
|
|
4
|
-
`
|
|
4
|
+
`full_name` VARCHAR(100) NOT NULL,
|
|
5
5
|
`email` VARCHAR(100) NOT NULL,
|
|
6
6
|
`password` VARCHAR(255) NOT NULL,
|
|
7
7
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
package/template/prisma/migrations/20260118135332_create_table_auth_refresh_tokens/migration.sql
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
-- CreateTable
|
|
2
|
+
CREATE TABLE `auth_refresh_tokens` (
|
|
3
|
+
`id` VARCHAR(191) NOT NULL,
|
|
4
|
+
`token` TEXT NOT NULL,
|
|
5
|
+
`user_id` VARCHAR(191) NOT NULL,
|
|
6
|
+
`expires_at` DATETIME(3) NOT NULL,
|
|
7
|
+
`revoked` BOOLEAN NOT NULL DEFAULT false,
|
|
8
|
+
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
9
|
+
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
10
|
+
`deleted_at` TIMESTAMP(0) NULL,
|
|
11
|
+
|
|
12
|
+
PRIMARY KEY (`id`)
|
|
13
|
+
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
14
|
+
|
|
15
|
+
-- AddForeignKey
|
|
16
|
+
ALTER TABLE `auth_refresh_tokens` ADD CONSTRAINT `auth_refresh_tokens_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
@@ -10,13 +10,29 @@ datasource db {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
model User {
|
|
13
|
+
id String @id @default(uuid())
|
|
14
|
+
full_name String @db.VarChar(100)
|
|
15
|
+
email String @unique @db.VarChar(100)
|
|
16
|
+
password String @db.VarChar(255)
|
|
17
|
+
created_at DateTime @default(now()) @db.Timestamp(0)
|
|
18
|
+
updated_at DateTime @updatedAt @db.Timestamp(0)
|
|
19
|
+
deleted_at DateTime? @db.Timestamp(0)
|
|
20
|
+
authRefreshTokens AuthRefreshToken[]
|
|
21
|
+
|
|
22
|
+
@@map("users")
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
model AuthRefreshToken {
|
|
13
26
|
id String @id @default(uuid())
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
27
|
+
token String @db.Text
|
|
28
|
+
user_id String
|
|
29
|
+
expires_at DateTime
|
|
30
|
+
revoked Boolean @default(false)
|
|
17
31
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
|
18
32
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
|
19
33
|
deleted_at DateTime? @db.Timestamp(0)
|
|
20
34
|
|
|
21
|
-
|
|
35
|
+
user User @relation(fields: [user_id], references: [id])
|
|
36
|
+
|
|
37
|
+
@@map("auth_refresh_tokens")
|
|
22
38
|
}
|
package/template/prisma/seed.ts
CHANGED
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
* schema:
|
|
12
12
|
* type: object
|
|
13
13
|
* required:
|
|
14
|
-
* -
|
|
14
|
+
* - full_name
|
|
15
15
|
* - email
|
|
16
16
|
* - password
|
|
17
17
|
* properties:
|
|
18
|
-
*
|
|
18
|
+
* full_name:
|
|
19
19
|
* type: string
|
|
20
20
|
* email:
|
|
21
21
|
* type: string
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
* id:
|
|
43
43
|
* type: string
|
|
44
44
|
* format: uuid
|
|
45
|
-
*
|
|
45
|
+
* full_name:
|
|
46
46
|
* type: string
|
|
47
47
|
* email:
|
|
48
48
|
* type: string
|
|
@@ -110,18 +110,16 @@
|
|
|
110
110
|
* properties:
|
|
111
111
|
* id:
|
|
112
112
|
* type: string
|
|
113
|
-
*
|
|
113
|
+
* full_name:
|
|
114
114
|
* type: string
|
|
115
115
|
* email:
|
|
116
116
|
* type: string
|
|
117
117
|
* accessToken:
|
|
118
118
|
* type: string
|
|
119
|
-
* refreshToken:
|
|
120
|
-
* type: string
|
|
121
119
|
* 400:
|
|
122
120
|
* $ref: '#/components/responses/ValidationError'
|
|
123
121
|
* 401:
|
|
124
|
-
* description: Login gagal -
|
|
122
|
+
* description: Login gagal - email atau password salah
|
|
125
123
|
* content:
|
|
126
124
|
* application/json:
|
|
127
125
|
* example:
|
|
@@ -158,7 +156,7 @@
|
|
|
158
156
|
* properties:
|
|
159
157
|
* id:
|
|
160
158
|
* type: string
|
|
161
|
-
*
|
|
159
|
+
* full_name:
|
|
162
160
|
* type: string
|
|
163
161
|
* email:
|
|
164
162
|
* type: string
|
|
@@ -232,24 +230,6 @@
|
|
|
232
230
|
* data:
|
|
233
231
|
* type: object
|
|
234
232
|
* properties:
|
|
235
|
-
* user:
|
|
236
|
-
* type: object
|
|
237
|
-
* properties:
|
|
238
|
-
* id:
|
|
239
|
-
* type: string
|
|
240
|
-
* fullName:
|
|
241
|
-
* type: string
|
|
242
|
-
* email:
|
|
243
|
-
* type: string
|
|
244
|
-
* password:
|
|
245
|
-
* type: string
|
|
246
|
-
* created_at:
|
|
247
|
-
* type: string
|
|
248
|
-
* updated_at:
|
|
249
|
-
* type: string
|
|
250
|
-
* deleted_at:
|
|
251
|
-
* type: string
|
|
252
|
-
* nullable: true
|
|
253
233
|
* accessToken:
|
|
254
234
|
* type: string
|
|
255
235
|
* 401:
|
|
@@ -271,7 +251,7 @@
|
|
|
271
251
|
* schema:
|
|
272
252
|
* type: object
|
|
273
253
|
* properties:
|
|
274
|
-
*
|
|
254
|
+
* full_name:
|
|
275
255
|
* type: string
|
|
276
256
|
* example: tes
|
|
277
257
|
* email:
|
|
@@ -301,7 +281,7 @@
|
|
|
301
281
|
* type: string
|
|
302
282
|
* format: uuid
|
|
303
283
|
* example: c1fa015f-48b0-456f-8c41-baf54ce092f5
|
|
304
|
-
*
|
|
284
|
+
* full_name:
|
|
305
285
|
* type: string
|
|
306
286
|
* example: tes update
|
|
307
287
|
* email:
|
|
@@ -11,20 +11,33 @@
|
|
|
11
11
|
* name: page
|
|
12
12
|
* schema:
|
|
13
13
|
* type: integer
|
|
14
|
-
* required: false
|
|
15
14
|
* description: Nomor halaman
|
|
16
15
|
* - in: query
|
|
17
16
|
* name: take
|
|
18
17
|
* schema:
|
|
19
18
|
* type: integer
|
|
20
|
-
* required: false
|
|
21
19
|
* description: Jumlah data per halaman
|
|
22
20
|
* - in: query
|
|
23
|
-
* name:
|
|
21
|
+
* name: search
|
|
24
22
|
* schema:
|
|
25
23
|
* type: string
|
|
26
|
-
*
|
|
27
|
-
*
|
|
24
|
+
* description: Filter berdasarkan nama atau email
|
|
25
|
+
* - in: query
|
|
26
|
+
* name: sort_field
|
|
27
|
+
* schema:
|
|
28
|
+
* type: string
|
|
29
|
+
* description: Urutkan berdasarkan field
|
|
30
|
+
* - in: query
|
|
31
|
+
* name: sort_order
|
|
32
|
+
* schema:
|
|
33
|
+
* type: string
|
|
34
|
+
* enum: [asc, desc]
|
|
35
|
+
* description: Urutkan berdasarkan asc atau desc
|
|
36
|
+
* - in: query
|
|
37
|
+
* name: no_paginate
|
|
38
|
+
* schema:
|
|
39
|
+
* type: boolean
|
|
40
|
+
* description: Menampilkan semua data tanpa paginasi
|
|
28
41
|
* responses:
|
|
29
42
|
* 200:
|
|
30
43
|
* description: Berhasil Get All Data
|
|
@@ -35,61 +48,78 @@
|
|
|
35
48
|
* properties:
|
|
36
49
|
* status:
|
|
37
50
|
* type: boolean
|
|
51
|
+
* example: true
|
|
38
52
|
* status_code:
|
|
39
53
|
* type: integer
|
|
54
|
+
* example: 200
|
|
40
55
|
* message:
|
|
41
56
|
* type: string
|
|
57
|
+
* example: Berhasil Get All Data
|
|
42
58
|
* data:
|
|
59
|
+
* type: array
|
|
60
|
+
* items:
|
|
61
|
+
* type: object
|
|
62
|
+
* properties:
|
|
63
|
+
* id:
|
|
64
|
+
* type: string
|
|
65
|
+
* format: uuid
|
|
66
|
+
* example: da613a6c-86e2-45f2-b583-157d9e7214a8
|
|
67
|
+
* full_name:
|
|
68
|
+
* type: string
|
|
69
|
+
* example: Tes
|
|
70
|
+
* email:
|
|
71
|
+
* type: string
|
|
72
|
+
* example: tes@gmail.com
|
|
73
|
+
* created_at:
|
|
74
|
+
* type: string
|
|
75
|
+
* example: 18-01-2026 21:55:22
|
|
76
|
+
* updated_at:
|
|
77
|
+
* type: string
|
|
78
|
+
* example: 18-01-2026 21:55:22
|
|
79
|
+
* deleted_at:
|
|
80
|
+
* type: string
|
|
81
|
+
* nullable: true
|
|
82
|
+
* example: ""
|
|
83
|
+
* meta:
|
|
43
84
|
* type: object
|
|
44
85
|
* properties:
|
|
45
|
-
*
|
|
46
|
-
* type: array
|
|
47
|
-
* items:
|
|
48
|
-
* type: object
|
|
49
|
-
* properties:
|
|
50
|
-
* id:
|
|
51
|
-
* type: string
|
|
52
|
-
* format: uuid
|
|
53
|
-
* fullName:
|
|
54
|
-
* type: string
|
|
55
|
-
* email:
|
|
56
|
-
* type: string
|
|
57
|
-
* username:
|
|
58
|
-
* type: string
|
|
59
|
-
* password:
|
|
60
|
-
* type: string
|
|
61
|
-
* description: (Hashed password)
|
|
62
|
-
* image_id:
|
|
63
|
-
* type: string
|
|
64
|
-
* image_url:
|
|
65
|
-
* type: string
|
|
66
|
-
* format: uri
|
|
67
|
-
* is_verify:
|
|
68
|
-
* type: boolean
|
|
69
|
-
* created_at:
|
|
70
|
-
* type: string
|
|
71
|
-
* format: date-time
|
|
72
|
-
* updated_at:
|
|
73
|
-
* type: string
|
|
74
|
-
* format: date-time
|
|
75
|
-
* deleted_at:
|
|
76
|
-
* type: string
|
|
77
|
-
* format: date-time
|
|
78
|
-
* nullable: true
|
|
79
|
-
* role_id:
|
|
80
|
-
* type: string
|
|
81
|
-
* format: uuid
|
|
82
|
-
* total_data:
|
|
86
|
+
* current_page:
|
|
83
87
|
* type: integer
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
|
|
88
|
+
* example: 1
|
|
89
|
+
* from:
|
|
90
|
+
* type: integer
|
|
91
|
+
* example: 1
|
|
92
|
+
* last_page:
|
|
93
|
+
* type: integer
|
|
94
|
+
* example: 1
|
|
95
|
+
* per_page:
|
|
96
|
+
* type: integer
|
|
97
|
+
* example: 10
|
|
98
|
+
* to:
|
|
99
|
+
* type: integer
|
|
100
|
+
* example: 1
|
|
101
|
+
* total:
|
|
102
|
+
* type: integer
|
|
103
|
+
* example: 1
|
|
104
|
+
* links:
|
|
105
|
+
* type: object
|
|
106
|
+
* properties:
|
|
107
|
+
* first:
|
|
108
|
+
* type: string
|
|
109
|
+
* example: http://localhost:4444/api/users?page=1
|
|
110
|
+
* last:
|
|
111
|
+
* type: string
|
|
112
|
+
* example: http://localhost:4444/api/users?page=1
|
|
113
|
+
* prev:
|
|
114
|
+
* type: string
|
|
115
|
+
* nullable: true
|
|
116
|
+
* example: null
|
|
117
|
+
* next:
|
|
118
|
+
* type: string
|
|
119
|
+
* nullable: true
|
|
120
|
+
* example: null
|
|
92
121
|
*/
|
|
122
|
+
|
|
93
123
|
/**
|
|
94
124
|
* @swagger
|
|
95
125
|
* /api/users/{id}:
|
|
@@ -121,7 +151,7 @@
|
|
|
121
151
|
* type: object
|
|
122
152
|
* properties:
|
|
123
153
|
* id: { type: string, format: uuid }
|
|
124
|
-
*
|
|
154
|
+
* full_name: { type: string }
|
|
125
155
|
* email: { type: string, format: email }
|
|
126
156
|
* username: { type: string }
|
|
127
157
|
* role_id: { type: string, format: uuid }
|
|
@@ -141,9 +171,9 @@
|
|
|
141
171
|
* application/json:
|
|
142
172
|
* schema:
|
|
143
173
|
* type: object
|
|
144
|
-
* required: [
|
|
174
|
+
* required: [ full_name, email, password ]
|
|
145
175
|
* properties:
|
|
146
|
-
*
|
|
176
|
+
* full_name: { type: string }
|
|
147
177
|
* email: { type: string, format: email }
|
|
148
178
|
* password: { type: string, format: password }
|
|
149
179
|
* responses:
|
|
@@ -161,7 +191,7 @@
|
|
|
161
191
|
* type: object
|
|
162
192
|
* properties:
|
|
163
193
|
* id: { type: string, format: uuid }
|
|
164
|
-
*
|
|
194
|
+
* full_name: { type: string }
|
|
165
195
|
* email: { type: string }
|
|
166
196
|
*/
|
|
167
197
|
/**
|
|
@@ -187,7 +217,7 @@
|
|
|
187
217
|
* schema:
|
|
188
218
|
* type: object
|
|
189
219
|
* properties:
|
|
190
|
-
*
|
|
220
|
+
* full_name: { type: string }
|
|
191
221
|
* email: { type: string, format: email }
|
|
192
222
|
* responses:
|
|
193
223
|
* 200:
|
|
@@ -204,7 +234,7 @@
|
|
|
204
234
|
* type: object
|
|
205
235
|
* properties:
|
|
206
236
|
* id: { type: string, format: uuid }
|
|
207
|
-
*
|
|
237
|
+
* full_name: { type: string }
|
|
208
238
|
* email: { type: string }
|
|
209
239
|
*/
|
|
210
240
|
/**
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { PrismaClient } from "@prisma/client";
|
|
2
2
|
import { logger } from "./logger";
|
|
3
|
-
import { DateTime } from "luxon";
|
|
4
3
|
import { dbLogger } from "./logger";
|
|
5
|
-
import { env } from "./env";
|
|
6
4
|
|
|
7
5
|
export const prismaClient = new PrismaClient({
|
|
8
6
|
log: [
|
|
@@ -25,8 +23,6 @@ export const prismaClient = new PrismaClient({
|
|
|
25
23
|
],
|
|
26
24
|
});
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
|
|
30
26
|
prismaClient.$on("query", (e) => {
|
|
31
27
|
dbLogger.info(`${e.query} - ${e.params}`);
|
|
32
28
|
});
|
|
@@ -34,7 +34,8 @@ const envSchema = z.object({
|
|
|
34
34
|
"CLIENT_URL harus berupa URL valid, dipisah koma jika lebih dari satu",
|
|
35
35
|
}
|
|
36
36
|
),
|
|
37
|
-
PORT: z.coerce.number().default(
|
|
37
|
+
PORT: z.coerce.number().default(4444),
|
|
38
|
+
COOKIE_ENCRYPTION_KEY: z.string(),
|
|
38
39
|
JWT_SECRET: z.string(),
|
|
39
40
|
CLOUDINARY_CLOUD_NAME: z.string().optional(),
|
|
40
41
|
CLOUDINARY_API_KEY: z.string().optional(),
|
|
@@ -65,7 +65,7 @@ export const dbLogger = winston.createLogger({
|
|
|
65
65
|
],
|
|
66
66
|
});
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
const plainFormat = winston.format.printf(({ timestamp, level, message }) => {
|
|
70
70
|
return `[${timestamp}] ${level.toUpperCase()}: ${message}`;
|
|
71
71
|
});
|
|
@@ -93,7 +93,7 @@ const coloredHttpFormat = winston.format.printf(
|
|
|
93
93
|
break;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
|
|
96
|
+
|
|
97
97
|
const methodMatch = msg.match(/^(GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD)/);
|
|
98
98
|
const methodColors = {
|
|
99
99
|
GET: chalk.green.bold("GET"),
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
CreateUserRequest,
|
|
5
5
|
UpdateUserRequest,
|
|
6
6
|
} from "../dtos/user-dto";
|
|
7
|
-
import { successResponse
|
|
7
|
+
import { successResponse } from "../utils/response";
|
|
8
8
|
import { AuthService } from "../services/auth-service";
|
|
9
9
|
import { UserRequest } from "../types/type-request";
|
|
10
10
|
import { env } from "../config/env";
|
|
@@ -61,7 +61,9 @@ export class AuthController {
|
|
|
61
61
|
try {
|
|
62
62
|
const request: UpdateUserRequest = req.body as UpdateUserRequest;
|
|
63
63
|
const response = await AuthService.updateProfile(req.user!, request);
|
|
64
|
-
res
|
|
64
|
+
res
|
|
65
|
+
.status(200)
|
|
66
|
+
.json(successResponse("Update User Berhasil", 200, response));
|
|
65
67
|
} catch (error) {
|
|
66
68
|
next(error);
|
|
67
69
|
}
|
|
@@ -69,7 +71,12 @@ export class AuthController {
|
|
|
69
71
|
|
|
70
72
|
static async logout(req: UserRequest, res: Response, next: NextFunction) {
|
|
71
73
|
await AuthService.logout(req);
|
|
72
|
-
res.clearCookie("refresh_token"
|
|
74
|
+
res.clearCookie("refresh_token", {
|
|
75
|
+
httpOnly: true,
|
|
76
|
+
secure: process.env.NODE_ENV === "production",
|
|
77
|
+
sameSite: "lax",
|
|
78
|
+
path: "/",
|
|
79
|
+
});
|
|
73
80
|
res.status(200).json(successResponse("Logout berhasil", 200));
|
|
74
81
|
}
|
|
75
82
|
static async refreshToken(req: Request, res: Response, next: NextFunction) {
|
|
@@ -77,7 +84,6 @@ export class AuthController {
|
|
|
77
84
|
const response = await AuthService.refreshToken(req);
|
|
78
85
|
res.status(200).json(
|
|
79
86
|
successResponse("Get Access Token Berhasil", 200, {
|
|
80
|
-
user: response.user,
|
|
81
87
|
accessToken: response.accessToken,
|
|
82
88
|
})
|
|
83
89
|
);
|
|
@@ -5,16 +5,11 @@ import {
|
|
|
5
5
|
UpdateUserRequest,
|
|
6
6
|
} from "../dtos/user-dto";
|
|
7
7
|
import { UserService } from "../services/user-service";
|
|
8
|
-
import {
|
|
9
|
-
successCreateResponse,
|
|
10
|
-
successDeleteResponse,
|
|
11
|
-
successResponse,
|
|
12
|
-
successUpdateResponse,
|
|
13
|
-
} from "../utils/response";
|
|
8
|
+
import { successResponse, paginateResponse } from "../utils/response";
|
|
14
9
|
import { UserRequest } from "../types/type-request";
|
|
15
|
-
|
|
10
|
+
import { env } from "../config/env";
|
|
16
11
|
export class UserController {
|
|
17
|
-
static async
|
|
12
|
+
static async get(req: Request, res: Response, next: NextFunction) {
|
|
18
13
|
try {
|
|
19
14
|
const page = Number(req.query.page) || 1;
|
|
20
15
|
const take = Number(req.query.take) || 10;
|
|
@@ -22,21 +17,27 @@ export class UserController {
|
|
|
22
17
|
page: page,
|
|
23
18
|
take: take,
|
|
24
19
|
skip: (page - 1) * take,
|
|
25
|
-
|
|
20
|
+
search: req.query.search as string,
|
|
21
|
+
sort_field: req.query.sort_field as any,
|
|
22
|
+
sort_order: req.query.sort_order as any,
|
|
23
|
+
no_paginate: req.query.no_paginate === "true",
|
|
26
24
|
};
|
|
27
|
-
|
|
25
|
+
|
|
26
|
+
const path = req.originalUrl.split("?")[0];
|
|
27
|
+
const baseUrl = `${env.BASE_URL}${path}`;
|
|
28
|
+
const response = await UserService.get(request, baseUrl, req.query);
|
|
28
29
|
res
|
|
29
30
|
.status(200)
|
|
30
|
-
.json(
|
|
31
|
+
.json(paginateResponse("Berhasil Get All Data", 200, response));
|
|
31
32
|
} catch (e) {
|
|
32
33
|
next(e);
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
static async
|
|
37
|
+
static async detail(req: Request, res: Response, next: NextFunction) {
|
|
37
38
|
try {
|
|
38
39
|
const id = req.params.id;
|
|
39
|
-
const response = await UserService.
|
|
40
|
+
const response = await UserService.detail(id);
|
|
40
41
|
res
|
|
41
42
|
.status(200)
|
|
42
43
|
.json(successResponse("Berhasil Get Detail Data", 200, response));
|
|
@@ -48,9 +49,10 @@ export class UserController {
|
|
|
48
49
|
static async create(req: Request, res: Response, next: NextFunction) {
|
|
49
50
|
try {
|
|
50
51
|
const request: CreateUserRequest = req.body as CreateUserRequest;
|
|
51
|
-
console.log(request);
|
|
52
52
|
const response = await UserService.create(request);
|
|
53
|
-
res
|
|
53
|
+
res
|
|
54
|
+
.status(201)
|
|
55
|
+
.json(successResponse("Create User Berhasil", 201, response));
|
|
54
56
|
} catch (error) {
|
|
55
57
|
next(error);
|
|
56
58
|
}
|
|
@@ -61,7 +63,9 @@ export class UserController {
|
|
|
61
63
|
const id = req.params.id;
|
|
62
64
|
const request: UpdateUserRequest = req.body as UpdateUserRequest;
|
|
63
65
|
const response = await UserService.update(id, request);
|
|
64
|
-
res
|
|
66
|
+
res
|
|
67
|
+
.status(200)
|
|
68
|
+
.json(successResponse("Update User Berhasil", 200, response));
|
|
65
69
|
} catch (error) {
|
|
66
70
|
next(error);
|
|
67
71
|
}
|
|
@@ -71,7 +75,7 @@ export class UserController {
|
|
|
71
75
|
try {
|
|
72
76
|
const id = req.params.id;
|
|
73
77
|
await UserService.delete(id);
|
|
74
|
-
res.status(200).json(
|
|
78
|
+
res.status(200).json(successResponse("Delete User Berhasil", 200));
|
|
75
79
|
} catch (e) {
|
|
76
80
|
next(e);
|
|
77
81
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type PaginationMeta = {
|
|
2
|
+
current_page: number;
|
|
3
|
+
from: number | null;
|
|
4
|
+
last_page: number;
|
|
5
|
+
per_page: number;
|
|
6
|
+
to: number | null;
|
|
7
|
+
total: number;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type PaginationLinks = {
|
|
11
|
+
first: string;
|
|
12
|
+
last: string;
|
|
13
|
+
prev: string | null;
|
|
14
|
+
next: string | null;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type PaginatedResponse<T> = {
|
|
18
|
+
data: T[];
|
|
19
|
+
meta: PaginationMeta;
|
|
20
|
+
links: PaginationLinks;
|
|
21
|
+
};
|