lapeh 2.6.17 → 3.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/.env.example +1 -6
- package/README.md +19 -85
- package/bin/index.js +84 -180
- package/dist/lib/bootstrap.d.ts.map +1 -1
- package/dist/lib/bootstrap.js +17 -16
- package/dist/lib/core/store.d.ts +55 -0
- package/dist/lib/core/store.d.ts.map +1 -0
- package/dist/lib/core/store.js +66 -0
- package/dist/lib/middleware/error.d.ts.map +1 -1
- package/dist/lib/middleware/error.js +1 -20
- package/dist/lib/utils/validator.d.ts.map +1 -1
- package/dist/lib/utils/validator.js +3 -32
- package/dist/src/modules/Auth/auth.controller.d.ts.map +1 -1
- package/dist/src/modules/Auth/auth.controller.js +118 -105
- package/dist/src/modules/Rbac/rbac.controller.d.ts.map +1 -1
- package/dist/src/modules/Rbac/rbac.controller.js +141 -140
- package/dist/src/routes/index.d.ts.map +1 -1
- package/dist/src/routes/index.js +0 -5
- package/doc/en/CHEATSHEET.md +3 -7
- package/doc/en/CLI.md +16 -41
- package/doc/en/DEPLOYMENT.md +171 -245
- package/doc/en/GETTING_STARTED.md +1 -25
- package/doc/en/PACKAGES.md +2 -3
- package/doc/en/STRUCTURE.md +1 -11
- package/doc/en/TUTORIAL.md +61 -119
- package/doc/id/CHANGELOG.md +16 -0
- package/doc/id/CHEATSHEET.md +0 -4
- package/doc/id/CLI.md +19 -54
- package/doc/id/DEPLOYMENT.md +171 -245
- package/doc/id/GETTING_STARTED.md +91 -115
- package/doc/id/PACKAGES.md +0 -1
- package/doc/id/STRUCTURE.md +1 -11
- package/doc/id/TUTORIAL.md +51 -109
- package/gitignore.template +0 -10
- package/lib/bootstrap.ts +39 -38
- package/lib/core/store.ts +116 -0
- package/lib/middleware/error.ts +1 -21
- package/lib/utils/validator.ts +3 -39
- package/package.json +4 -18
- package/scripts/init-project.js +2 -108
- package/scripts/make-module.js +1 -12
- package/scripts/seed-json.js +158 -0
- package/src/modules/Auth/auth.controller.ts +156 -106
- package/src/modules/Rbac/rbac.controller.ts +193 -138
- package/src/routes/index.ts +0 -3
- package/src/routes/rbac.ts +42 -42
- package/storage/logs/.0337f5062fe676994d1dc340156e089444e3d6e0-audit.json +5 -10
- package/storage/logs/lapeh-2025-12-30.log +1093 -0
- package/tsconfig.build.json +1 -3
- package/tsconfig.json +0 -1
- package/lib/core/database.ts +0 -5
- package/prisma/base.prisma.template +0 -8
- package/prisma/migrations/20251225163737_init/migration.sql +0 -236
- package/prisma/migrations/20251226000329_create_pets_table/migration.sql +0 -11
- package/prisma/migrations/20251226001249_create_pets_table/migration.sql +0 -82
- package/prisma/migrations/20251226001717_restore_core_models/migration.sql +0 -236
- package/prisma/migrations/migration_lock.toml +0 -3
- package/prisma/schema.prisma +0 -197
- package/prisma/seed.ts +0 -411
- package/scripts/compile-schema.js +0 -64
- package/src/modules/Auth/auth.prisma +0 -106
- package/src/modules/Pets/pets.controller.ts +0 -238
- package/src/modules/Pets/pets.prisma +0 -9
- package/src/modules/Rbac/rbac.prisma +0 -68
- package/src/routes/pets.ts +0 -13
- package/storage/logs/lapeh-2025-12-26.log +0 -88
- package/storage/logs/lapeh-2025-12-27.log +0 -217
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
model cache {
|
|
2
|
-
id String @id @default(auto()) @map("_id") @db.ObjectId
|
|
3
|
-
key String @unique
|
|
4
|
-
value String
|
|
5
|
-
expiration Int
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
model cache_locks {
|
|
9
|
-
id String @id @default(auto()) @map("_id") @db.ObjectId
|
|
10
|
-
key String @unique
|
|
11
|
-
owner String
|
|
12
|
-
expiration Int
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
model failed_jobs {
|
|
16
|
-
id String @id @default(auto()) @map("_id") @db.ObjectId
|
|
17
|
-
uuid String @unique
|
|
18
|
-
connection String
|
|
19
|
-
queue String
|
|
20
|
-
payload String
|
|
21
|
-
exception String
|
|
22
|
-
failed_at DateTime @default(now())
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
model job_batches {
|
|
26
|
-
id String @id @map("_id")
|
|
27
|
-
name String
|
|
28
|
-
total_jobs Int
|
|
29
|
-
pending_jobs Int
|
|
30
|
-
failed_jobs Int
|
|
31
|
-
failed_job_ids String
|
|
32
|
-
options String?
|
|
33
|
-
cancelled_at Int?
|
|
34
|
-
created_at Int
|
|
35
|
-
finished_at Int?
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
model jobs {
|
|
39
|
-
id String @id @default(auto()) @map("_id") @db.ObjectId
|
|
40
|
-
queue String
|
|
41
|
-
payload String
|
|
42
|
-
attempts Int
|
|
43
|
-
reserved_at Int?
|
|
44
|
-
available_at Int
|
|
45
|
-
created_at Int
|
|
46
|
-
|
|
47
|
-
@@index([queue])
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
model migrations {
|
|
51
|
-
id String @id @default(auto()) @map("_id") @db.ObjectId
|
|
52
|
-
migration String
|
|
53
|
-
batch Int
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
model password_reset_tokens {
|
|
57
|
-
id String @id @default(auto()) @map("_id") @db.ObjectId
|
|
58
|
-
email String @unique
|
|
59
|
-
token String
|
|
60
|
-
created_at DateTime?
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
model personal_access_tokens {
|
|
64
|
-
id String @id @default(auto()) @map("_id") @db.ObjectId
|
|
65
|
-
tokenable_type String
|
|
66
|
-
tokenable_id String
|
|
67
|
-
name String
|
|
68
|
-
token String @unique
|
|
69
|
-
abilities String?
|
|
70
|
-
last_used_at DateTime?
|
|
71
|
-
expires_at DateTime?
|
|
72
|
-
created_at DateTime?
|
|
73
|
-
updated_at DateTime?
|
|
74
|
-
|
|
75
|
-
@@index([expires_at])
|
|
76
|
-
@@index([tokenable_type, tokenable_id])
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
model sessions {
|
|
80
|
-
id String @id @map("_id")
|
|
81
|
-
user_id String?
|
|
82
|
-
ip_address String?
|
|
83
|
-
user_agent String?
|
|
84
|
-
payload String
|
|
85
|
-
last_activity Int
|
|
86
|
-
|
|
87
|
-
@@index([last_activity])
|
|
88
|
-
@@index([user_id])
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
model users {
|
|
92
|
-
id String @id @default(auto()) @map("_id") @db.ObjectId
|
|
93
|
-
uuid String @unique
|
|
94
|
-
name String
|
|
95
|
-
email String @unique
|
|
96
|
-
avatar String?
|
|
97
|
-
avatar_url String?
|
|
98
|
-
email_verified_at DateTime?
|
|
99
|
-
password String
|
|
100
|
-
remember_token String?
|
|
101
|
-
created_at DateTime?
|
|
102
|
-
updated_at DateTime?
|
|
103
|
-
|
|
104
|
-
user_roles user_roles[]
|
|
105
|
-
user_permissions user_permissions[]
|
|
106
|
-
}
|
|
@@ -1,238 +0,0 @@
|
|
|
1
|
-
import { Request, Response } from "express";
|
|
2
|
-
import { prisma } from "@lapeh/core/database";
|
|
3
|
-
import { sendSuccess, sendError, sendFastSuccess } from "@lapeh/utils/response";
|
|
4
|
-
import { getPagination, buildPaginationMeta } from "@lapeh/utils/pagination";
|
|
5
|
-
import { Validator } from "@lapeh/utils/validator";
|
|
6
|
-
import {
|
|
7
|
-
getSerializer,
|
|
8
|
-
createResponseSchema,
|
|
9
|
-
createPaginatedResponseSchema,
|
|
10
|
-
} from "@lapeh/core/serializer";
|
|
11
|
-
import {
|
|
12
|
-
getCache,
|
|
13
|
-
setCache,
|
|
14
|
-
delCache,
|
|
15
|
-
delCachePattern,
|
|
16
|
-
} from "../../../lib/core/redis";
|
|
17
|
-
|
|
18
|
-
// 1. Definisikan Schema Output untuk performa tinggi
|
|
19
|
-
const petSchema = {
|
|
20
|
-
type: "object",
|
|
21
|
-
properties: {
|
|
22
|
-
id: { type: "string" }, // BigInt dikonversi ke string
|
|
23
|
-
name: { type: "string" },
|
|
24
|
-
species: { type: "string" },
|
|
25
|
-
age: { type: "integer" },
|
|
26
|
-
created_at: { type: "string", format: "date-time" },
|
|
27
|
-
updated_at: { type: "string", format: "date-time" },
|
|
28
|
-
},
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
// 2. Compile Serializer
|
|
32
|
-
// Untuk Single Item
|
|
33
|
-
const petSerializer = getSerializer(
|
|
34
|
-
"pet-single",
|
|
35
|
-
createResponseSchema(petSchema)
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
// Untuk List Item (Paginated)
|
|
39
|
-
const petListSerializer = getSerializer(
|
|
40
|
-
"pet-list",
|
|
41
|
-
createPaginatedResponseSchema(petSchema)
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
export async function index(req: Request, res: Response) {
|
|
45
|
-
const { page, perPage, skip, take } = getPagination(req.query);
|
|
46
|
-
const search = req.query.search as string;
|
|
47
|
-
|
|
48
|
-
// Cache Strategy: Cache list based on query params
|
|
49
|
-
const cacheKey = `pets:list:${JSON.stringify(req.query)}`;
|
|
50
|
-
const cached = await getCache(cacheKey);
|
|
51
|
-
|
|
52
|
-
if (cached) {
|
|
53
|
-
sendFastSuccess(res, 200, petListSerializer, cached);
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const where: any = {};
|
|
58
|
-
if (search) {
|
|
59
|
-
where.OR = [
|
|
60
|
-
{ name: { contains: search, mode: "insensitive" } },
|
|
61
|
-
{ species: { contains: search, mode: "insensitive" } },
|
|
62
|
-
];
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const [data, total] = await Promise.all([
|
|
66
|
-
prisma.pets.findMany({
|
|
67
|
-
where,
|
|
68
|
-
skip,
|
|
69
|
-
take,
|
|
70
|
-
orderBy: { created_at: "desc" },
|
|
71
|
-
}),
|
|
72
|
-
prisma.pets.count({ where }),
|
|
73
|
-
]);
|
|
74
|
-
|
|
75
|
-
// Kita perlu convert BigInt ke string sebelum masuk serializer
|
|
76
|
-
// Karena fast-json-stringify mengharapkan tipe data yang sesuai dengan schema
|
|
77
|
-
const serialized = data.map((item: any) => ({
|
|
78
|
-
...item,
|
|
79
|
-
id: item.id.toString(),
|
|
80
|
-
}));
|
|
81
|
-
|
|
82
|
-
const meta = buildPaginationMeta(page, perPage, total);
|
|
83
|
-
|
|
84
|
-
const responseData = {
|
|
85
|
-
status: "success",
|
|
86
|
-
message: "Pets retrieved successfully",
|
|
87
|
-
data: {
|
|
88
|
-
data: serialized,
|
|
89
|
-
meta,
|
|
90
|
-
},
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
// Cache for 60 seconds
|
|
94
|
-
await setCache(cacheKey, responseData, 60);
|
|
95
|
-
|
|
96
|
-
// Gunakan sendFastSuccess untuk performa maksimal
|
|
97
|
-
// Struktur data disesuaikan dengan createPaginatedResponseSchema: { data: [], meta: {} }
|
|
98
|
-
sendFastSuccess(res, 200, petListSerializer, responseData);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export async function show(req: Request, res: Response) {
|
|
102
|
-
const { id } = req.params;
|
|
103
|
-
const cacheKey = `pets:${id}`;
|
|
104
|
-
|
|
105
|
-
const cached = await getCache(cacheKey);
|
|
106
|
-
if (cached) {
|
|
107
|
-
sendFastSuccess(res, 200, petSerializer, cached);
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const pet = await prisma.pets.findUnique({
|
|
112
|
-
where: { id: id },
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
if (!pet) {
|
|
116
|
-
sendError(res, 404, "Pet not found");
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const responseData = {
|
|
121
|
-
status: "success",
|
|
122
|
-
message: "Pet retrieved successfully",
|
|
123
|
-
data: {
|
|
124
|
-
...pet,
|
|
125
|
-
id: pet.id.toString(),
|
|
126
|
-
},
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
// Cache for 5 minutes
|
|
130
|
-
await setCache(cacheKey, responseData, 300);
|
|
131
|
-
|
|
132
|
-
// Gunakan sendFastSuccess
|
|
133
|
-
sendFastSuccess(res, 200, petSerializer, responseData);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export async function store(req: Request, res: Response) {
|
|
137
|
-
const validator = Validator.make(req.body || {}, {
|
|
138
|
-
name: "required|string",
|
|
139
|
-
species: "required|string",
|
|
140
|
-
age: "required|integer|min:1",
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
if (await validator.fails()) {
|
|
144
|
-
sendError(res, 422, "Validation error", validator.errors());
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const validatedData = await validator.validated();
|
|
149
|
-
const pet = await prisma.pets.create({
|
|
150
|
-
data: {
|
|
151
|
-
...validatedData,
|
|
152
|
-
created_at: new Date(),
|
|
153
|
-
updated_at: new Date(),
|
|
154
|
-
},
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
// Invalidate list cache
|
|
158
|
-
await delCachePattern("pets:list:*");
|
|
159
|
-
|
|
160
|
-
// Gunakan sendFastSuccess
|
|
161
|
-
sendFastSuccess(res, 201, petSerializer, {
|
|
162
|
-
status: "success",
|
|
163
|
-
message: "Pet created successfully",
|
|
164
|
-
data: {
|
|
165
|
-
...pet,
|
|
166
|
-
id: pet.id.toString(),
|
|
167
|
-
},
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
export async function update(req: Request, res: Response) {
|
|
172
|
-
const { id } = req.params;
|
|
173
|
-
const validator = Validator.make(req.body || {}, {
|
|
174
|
-
name: "string",
|
|
175
|
-
species: "string",
|
|
176
|
-
age: "integer|min:1",
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
if (await validator.fails()) {
|
|
180
|
-
sendError(res, 422, "Validation error", validator.errors());
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const existing = await prisma.pets.findUnique({
|
|
185
|
-
where: { id: id },
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
if (!existing) {
|
|
189
|
-
sendError(res, 404, "Pet not found");
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const validatedData = await validator.validated();
|
|
194
|
-
const updated = await prisma.pets.update({
|
|
195
|
-
where: { id: id },
|
|
196
|
-
data: {
|
|
197
|
-
...validatedData,
|
|
198
|
-
updated_at: new Date(),
|
|
199
|
-
},
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
// Invalidate specific cache and list cache
|
|
203
|
-
await delCache(`pets:${id}`);
|
|
204
|
-
await delCachePattern("pets:list:*");
|
|
205
|
-
|
|
206
|
-
// Gunakan sendFastSuccess
|
|
207
|
-
sendFastSuccess(res, 200, petSerializer, {
|
|
208
|
-
status: "success",
|
|
209
|
-
message: "Pet updated successfully",
|
|
210
|
-
data: {
|
|
211
|
-
...updated,
|
|
212
|
-
id: updated.id.toString(),
|
|
213
|
-
},
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
export async function destroy(req: Request, res: Response) {
|
|
218
|
-
const { id } = req.params;
|
|
219
|
-
|
|
220
|
-
const existing = await prisma.pets.findUnique({
|
|
221
|
-
where: { id: id },
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
if (!existing) {
|
|
225
|
-
sendError(res, 404, "Pet not found");
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
await prisma.pets.delete({
|
|
230
|
-
where: { id: id },
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
// Invalidate specific cache and list cache
|
|
234
|
-
await delCache(`pets:${id}`);
|
|
235
|
-
await delCachePattern("pets:list:*");
|
|
236
|
-
|
|
237
|
-
sendSuccess(res, 200, "Pet deleted successfully", null);
|
|
238
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
model roles {
|
|
2
|
-
id String @id @default(auto()) @map("_id") @db.ObjectId
|
|
3
|
-
name String
|
|
4
|
-
slug String @unique
|
|
5
|
-
description String?
|
|
6
|
-
created_at DateTime @default(now())
|
|
7
|
-
updated_at DateTime @updatedAt
|
|
8
|
-
|
|
9
|
-
user_roles user_roles[]
|
|
10
|
-
role_permissions role_permissions[]
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
model permissions {
|
|
14
|
-
id String @id @default(auto()) @map("_id") @db.ObjectId
|
|
15
|
-
name String
|
|
16
|
-
slug String @unique
|
|
17
|
-
description String?
|
|
18
|
-
created_at DateTime @default(now())
|
|
19
|
-
updated_at DateTime @updatedAt
|
|
20
|
-
|
|
21
|
-
role_permissions role_permissions[]
|
|
22
|
-
user_permissions user_permissions[]
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
model user_roles {
|
|
26
|
-
id String @id @default(auto()) @map("_id") @db.ObjectId
|
|
27
|
-
user_id String @db.ObjectId
|
|
28
|
-
role_id String @db.ObjectId
|
|
29
|
-
created_at DateTime @default(now())
|
|
30
|
-
updated_at DateTime @updatedAt
|
|
31
|
-
|
|
32
|
-
user users @relation(fields: [user_id], references: [id], onDelete: Cascade)
|
|
33
|
-
role roles @relation(fields: [role_id], references: [id], onDelete: Cascade)
|
|
34
|
-
|
|
35
|
-
@@unique([user_id, role_id])
|
|
36
|
-
@@index([user_id])
|
|
37
|
-
@@index([role_id])
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
model role_permissions {
|
|
41
|
-
id String @id @default(auto()) @map("_id") @db.ObjectId
|
|
42
|
-
role_id String @db.ObjectId
|
|
43
|
-
permission_id String @db.ObjectId
|
|
44
|
-
created_at DateTime @default(now())
|
|
45
|
-
updated_at DateTime @updatedAt
|
|
46
|
-
|
|
47
|
-
role roles @relation(fields: [role_id], references: [id], onDelete: Cascade)
|
|
48
|
-
permission permissions @relation(fields: [permission_id], references: [id], onDelete: Cascade)
|
|
49
|
-
|
|
50
|
-
@@unique([role_id, permission_id])
|
|
51
|
-
@@index([role_id])
|
|
52
|
-
@@index([permission_id])
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
model user_permissions {
|
|
56
|
-
id String @id @default(auto()) @map("_id") @db.ObjectId
|
|
57
|
-
user_id String @db.ObjectId
|
|
58
|
-
permission_id String @db.ObjectId
|
|
59
|
-
created_at DateTime @default(now())
|
|
60
|
-
updated_at DateTime @updatedAt
|
|
61
|
-
|
|
62
|
-
user users @relation(fields: [user_id], references: [id], onDelete: Cascade)
|
|
63
|
-
permission permissions @relation(fields: [permission_id], references: [id], onDelete: Cascade)
|
|
64
|
-
|
|
65
|
-
@@unique([user_id, permission_id])
|
|
66
|
-
@@index([user_id])
|
|
67
|
-
@@index([permission_id])
|
|
68
|
-
}
|
package/src/routes/pets.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { Router } from "express";
|
|
2
|
-
import * as PetController from "@/modules/Pets/pets.controller";
|
|
3
|
-
import { parseMultipart } from "@lapeh/middleware/multipart";
|
|
4
|
-
|
|
5
|
-
const router = Router();
|
|
6
|
-
|
|
7
|
-
router.get("/", PetController.index);
|
|
8
|
-
router.get("/:id", PetController.show);
|
|
9
|
-
router.post("/", parseMultipart, PetController.store);
|
|
10
|
-
router.put("/:id", parseMultipart, PetController.update);
|
|
11
|
-
router.delete("/:id", PetController.destroy);
|
|
12
|
-
|
|
13
|
-
export default router;
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
[2025-12-26 23:24:48] INFO: This is an info message from test script
|
|
2
|
-
[2025-12-26 23:24:48] ERROR: This is an error message from test script
|
|
3
|
-
[2025-12-26 23:24:48] WARN: This is a warning
|
|
4
|
-
[2025-12-26 23:25:18] INFO: This is an info message from test script
|
|
5
|
-
[2025-12-26 23:25:18] ERROR: This is an error message from test script
|
|
6
|
-
[2025-12-26 23:25:18] WARN: This is a warning
|
|
7
|
-
[2025-12-26 23:25:42] INFO: This is an info message from test script
|
|
8
|
-
[2025-12-26 23:25:42] ERROR: This is an error message from test script
|
|
9
|
-
[2025-12-26 23:25:42] WARN: This is a warning
|
|
10
|
-
[2025-12-26 23:35:47] WARN: Validation error
|
|
11
|
-
[2025-12-26 23:35:48] WARN: Validation error
|
|
12
|
-
[2025-12-26 23:35:49] WARN: Validation error
|
|
13
|
-
[2025-12-26 23:35:50] WARN: Validation error
|
|
14
|
-
[2025-12-26 23:35:51] WARN: Validation error
|
|
15
|
-
[2025-12-26 23:35:54] WARN: Validation error
|
|
16
|
-
[2025-12-26 23:36:06] WARN: Validation error
|
|
17
|
-
[2025-12-26 23:36:07] WARN: Validation error
|
|
18
|
-
[2025-12-26 23:36:08] WARN: Validation error
|
|
19
|
-
[2025-12-26 23:36:21] WARN: Validation error
|
|
20
|
-
[2025-12-26 23:41:33] WARN: Validation error
|
|
21
|
-
Errors: {
|
|
22
|
-
"age": [
|
|
23
|
-
"Age must be a number"
|
|
24
|
-
]
|
|
25
|
-
}
|
|
26
|
-
Meta: {"statusCode":422}
|
|
27
|
-
[2025-12-26 23:41:36] WARN: Validation error
|
|
28
|
-
Errors: {
|
|
29
|
-
"age": [
|
|
30
|
-
"Age must be a number"
|
|
31
|
-
]
|
|
32
|
-
}
|
|
33
|
-
Meta: {"statusCode":422}
|
|
34
|
-
[2025-12-26 23:41:38] WARN: Validation error
|
|
35
|
-
Errors: {
|
|
36
|
-
"age": [
|
|
37
|
-
"Age must be a number"
|
|
38
|
-
]
|
|
39
|
-
}
|
|
40
|
-
Meta: {"statusCode":422}
|
|
41
|
-
[2025-12-26 23:41:39] WARN: Validation error
|
|
42
|
-
Errors: {
|
|
43
|
-
"age": [
|
|
44
|
-
"Age must be a number"
|
|
45
|
-
]
|
|
46
|
-
}
|
|
47
|
-
Meta: {"statusCode":422}
|
|
48
|
-
[2025-12-26 23:41:47] WARN: Validation error
|
|
49
|
-
Errors: {
|
|
50
|
-
"species": [
|
|
51
|
-
"Species is required"
|
|
52
|
-
],
|
|
53
|
-
"age": [
|
|
54
|
-
"Age is required"
|
|
55
|
-
]
|
|
56
|
-
}
|
|
57
|
-
Meta: {"statusCode":422}
|
|
58
|
-
[2025-12-26 23:42:10] WARN: Validation error
|
|
59
|
-
Errors: {
|
|
60
|
-
"species": [
|
|
61
|
-
"Species is required"
|
|
62
|
-
],
|
|
63
|
-
"age": [
|
|
64
|
-
"Age is required"
|
|
65
|
-
]
|
|
66
|
-
}
|
|
67
|
-
Meta: {"statusCode":422}
|
|
68
|
-
[2025-12-26 23:42:27] WARN: Validation error
|
|
69
|
-
Errors: {
|
|
70
|
-
"age": [
|
|
71
|
-
"Age must be a number"
|
|
72
|
-
]
|
|
73
|
-
}
|
|
74
|
-
Meta: {"statusCode":422}
|
|
75
|
-
[2025-12-26 23:56:33] WARN: Validation error
|
|
76
|
-
Errors: {
|
|
77
|
-
"age": [
|
|
78
|
-
"Age must be a number"
|
|
79
|
-
]
|
|
80
|
-
}
|
|
81
|
-
Meta: {"statusCode":422}
|
|
82
|
-
[2025-12-26 23:56:35] WARN: Validation error
|
|
83
|
-
Errors: {
|
|
84
|
-
"age": [
|
|
85
|
-
"Age must be a number"
|
|
86
|
-
]
|
|
87
|
-
}
|
|
88
|
-
Meta: {"statusCode":422}
|