lapeh 2.4.12 → 2.6.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.
Files changed (52) hide show
  1. package/bin/index.js +669 -942
  2. package/dist/generated/prisma/internal/prismaNamespace.d.ts +21 -16
  3. package/dist/generated/prisma/internal/prismaNamespace.d.ts.map +1 -1
  4. package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +3 -3
  5. package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts.map +1 -1
  6. package/dist/lib/bootstrap.d.ts.map +1 -1
  7. package/dist/lib/bootstrap.js +34 -11
  8. package/dist/lib/core/database.d.ts.map +1 -1
  9. package/dist/lib/core/database.js +7 -1
  10. package/dist/lib/utils/response.d.ts +1 -1
  11. package/dist/lib/utils/response.d.ts.map +1 -1
  12. package/dist/src/config/app.d.ts +10 -0
  13. package/dist/src/config/app.d.ts.map +1 -0
  14. package/dist/src/config/app.js +12 -0
  15. package/dist/src/config/cors.d.ts +6 -0
  16. package/dist/src/config/cors.d.ts.map +1 -0
  17. package/dist/src/config/cors.js +8 -0
  18. package/dist/src/modules/Auth/auth.controller.d.ts +11 -0
  19. package/dist/src/modules/Auth/auth.controller.d.ts.map +1 -0
  20. package/dist/src/modules/Auth/auth.controller.js +414 -0
  21. package/dist/src/modules/Pets/pets.controller.d.ts +7 -0
  22. package/dist/src/modules/Pets/pets.controller.d.ts.map +1 -0
  23. package/dist/src/modules/Pets/pets.controller.js +163 -0
  24. package/dist/src/modules/Rbac/rbac.controller.d.ts +16 -0
  25. package/dist/src/modules/Rbac/rbac.controller.d.ts.map +1 -0
  26. package/dist/src/modules/Rbac/rbac.controller.js +437 -0
  27. package/dist/src/routes/auth.js +9 -9
  28. package/dist/src/routes/pets.js +1 -1
  29. package/dist/src/routes/rbac.js +15 -15
  30. package/lib/bootstrap.ts +34 -13
  31. package/lib/core/database.ts +7 -1
  32. package/lib/utils/response.ts +4 -4
  33. package/package.json +4 -5
  34. package/prisma/base.prisma.template +0 -1
  35. package/prisma/schema.prisma +0 -1
  36. package/prisma.config.ts +14 -0
  37. package/scripts/compile-schema.js +28 -10
  38. package/scripts/make-module.js +100 -158
  39. package/src/config/app.ts +9 -0
  40. package/src/config/cors.ts +5 -0
  41. package/src/routes/auth.ts +1 -1
  42. package/src/routes/pets.ts +1 -1
  43. package/src/routes/rbac.ts +1 -1
  44. package/storage/logs/.0337f5062fe676994d1dc340156e089444e3d6e0-audit.json +5 -0
  45. package/storage/logs/lapeh-2025-12-29.log +94 -0
  46. package/scripts/make-controller.js +0 -205
  47. package/scripts/make-model.js +0 -42
  48. /package/src/{controllers/authController.ts → modules/Auth/auth.controller.ts} +0 -0
  49. /package/src/{models/core.prisma → modules/Auth/auth.prisma} +0 -0
  50. /package/src/{controllers/petController.ts → modules/Pets/pets.controller.ts} +0 -0
  51. /package/src/{models → modules/Pets}/pets.prisma +0 -0
  52. /package/src/{controllers/rbacController.ts → modules/Rbac/rbac.controller.ts} +0 -0
@@ -0,0 +1,14 @@
1
+ import { defineConfig } from "@prisma/config";
2
+ import * as dotenv from "dotenv";
3
+
4
+ dotenv.config();
5
+
6
+ export default defineConfig({
7
+ schema: "prisma/schema.prisma",
8
+ datasource: {
9
+ url: process.env.DATABASE_URL,
10
+ },
11
+ migrations: {
12
+ seed: 'ts-node prisma/seed.ts',
13
+ },
14
+ });
@@ -2,16 +2,16 @@ const fs = require('fs');
2
2
  const path = require('path');
3
3
 
4
4
  const prismaDir = path.join(__dirname, '..', 'prisma');
5
- const modelsDir = path.join(__dirname, '..', 'src', 'models');
5
+ const modulesDir = path.join(__dirname, '..', 'src', 'modules');
6
6
  const schemaFile = path.join(prismaDir, 'schema.prisma');
7
7
  const baseFile = path.join(prismaDir, 'base.prisma.template');
8
8
 
9
- // Ensure models directory exists
10
- if (!fs.existsSync(modelsDir)) {
11
- fs.mkdirSync(modelsDir, { recursive: true });
9
+ // Read base schema (datasource & generator)
10
+ if (!fs.existsSync(baseFile)) {
11
+ console.error(`❌ Base schema template not found at ${baseFile}`);
12
+ process.exit(1);
12
13
  }
13
14
 
14
- // Read base schema (datasource & generator)
15
15
  let schemaContent = fs.readFileSync(baseFile, 'utf8');
16
16
 
17
17
  // Detect provider from datasource block
@@ -19,11 +19,28 @@ const providerMatch = schemaContent.match(/datasource\s+\w+\s+\{[\s\S]*?provider
19
19
  const provider = providerMatch ? providerMatch[1] : 'postgresql';
20
20
  const isMongo = provider === 'mongodb';
21
21
 
22
- // Read all .prisma files in src/models
23
- const modelFiles = fs.readdirSync(modelsDir).filter(file => file.endsWith('.prisma'));
22
+ // Helper to find all .prisma files recursively
23
+ function findPrismaFiles(dir, fileList = []) {
24
+ if (!fs.existsSync(dir)) return fileList;
25
+ const files = fs.readdirSync(dir);
26
+ files.forEach(file => {
27
+ const filePath = path.join(dir, file);
28
+ const stat = fs.statSync(filePath);
29
+ if (stat.isDirectory()) {
30
+ findPrismaFiles(filePath, fileList);
31
+ } else {
32
+ if (file.endsWith('.prisma')) {
33
+ fileList.push(filePath);
34
+ }
35
+ }
36
+ });
37
+ return fileList;
38
+ }
39
+
40
+ const modelFiles = findPrismaFiles(modulesDir);
24
41
 
25
- modelFiles.forEach(file => {
26
- let content = fs.readFileSync(path.join(modelsDir, file), 'utf8');
42
+ modelFiles.forEach(filePath => {
43
+ let content = fs.readFileSync(filePath, 'utf8');
27
44
 
28
45
  if (!isMongo) {
29
46
  // Transform MongoDB specific syntax to SQL compatible syntax
@@ -33,6 +50,7 @@ modelFiles.forEach(file => {
33
50
  // Remove @map("_id")
34
51
  .replace(/@map\("_id"\)/g, '')
35
52
  // Replace @default(auto()) with @default(uuid()) for Strings
53
+ // Note: This is a simple replacement, check your schema if you use auto() for Int
36
54
  .replace(/@default\(auto\(\)\)/g, '@default(uuid())');
37
55
  }
38
56
 
@@ -43,4 +61,4 @@ modelFiles.forEach(file => {
43
61
  fs.writeFileSync(schemaFile, schemaContent);
44
62
 
45
63
  console.log('✅ Prisma schema compiled successfully!');
46
- console.log(` Merged ${modelFiles.length} model files from src/models/ into prisma/schema.prisma`);
64
+ console.log(` Merged ${modelFiles.length} model files from src/modules/ into prisma/schema.prisma`);
@@ -1,158 +1,100 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
-
4
- const moduleName = process.argv[2];
5
-
6
- if (!moduleName) {
7
- console.error('❌ Please specify the module name.');
8
- console.error(' Usage: npm run make:module <name>');
9
- console.error(' Example: npm run make:module product');
10
- process.exit(1);
11
- }
12
-
13
- // Convert "product" -> "Product" (PascalCase) for Class names
14
- const PascalCaseName = moduleName.charAt(0).toUpperCase() + moduleName.slice(1);
15
- // Convert "product" -> "product" (camelCase) for variables/files
16
- const camelCaseName = moduleName.toLowerCase();
17
-
18
- const srcDir = path.join(__dirname, '..', 'src');
19
-
20
- // 1. Create Controller
21
- const controllerContent = `import { Request, Response } from 'express';
22
- import { ${PascalCaseName}Service } from '../services/${camelCaseName}Service';
23
- import { successResponse, errorResponse } from '../utils/response';
24
-
25
- export const ${PascalCaseName}Controller = {
26
- async getAll(req: Request, res: Response) {
27
- try {
28
- const data = await ${PascalCaseName}Service.getAll();
29
- return successResponse(res, data, '${PascalCaseName}s retrieved successfully');
30
- } catch (error) {
31
- return errorResponse(res, error as Error);
32
- }
33
- },
34
-
35
- async getById(req: Request, res: Response) {
36
- try {
37
- const { id } = req.params;
38
- const data = await ${PascalCaseName}Service.getById(id);
39
- if (!data) return errorResponse(res, new Error('${PascalCaseName} not found'), 404);
40
- return successResponse(res, data, '${PascalCaseName} retrieved successfully');
41
- } catch (error) {
42
- return errorResponse(res, error as Error);
43
- }
44
- },
45
-
46
- async create(req: Request, res: Response) {
47
- try {
48
- const data = await ${PascalCaseName}Service.create(req.body);
49
- return successResponse(res, data, '${PascalCaseName} created successfully', 201);
50
- } catch (error) {
51
- return errorResponse(res, error as Error);
52
- }
53
- },
54
-
55
- async update(req: Request, res: Response) {
56
- try {
57
- const { id } = req.params;
58
- const data = await ${PascalCaseName}Service.update(id, req.body);
59
- return successResponse(res, data, '${PascalCaseName} updated successfully');
60
- } catch (error) {
61
- return errorResponse(res, error as Error);
62
- }
63
- },
64
-
65
- async delete(req: Request, res: Response) {
66
- try {
67
- const { id } = req.params;
68
- await ${PascalCaseName}Service.delete(id);
69
- return successResponse(res, null, '${PascalCaseName} deleted successfully');
70
- } catch (error) {
71
- return errorResponse(res, error as Error);
72
- }
73
- }
74
- };
75
- `;
76
-
77
- // 2. Create Service
78
- const serviceContent = `// import prisma from '../prisma'; // Uncomment this line if you use Prisma
79
-
80
- export const ${PascalCaseName}Service = {
81
- async getAll() {
82
- // return prisma.${camelCaseName}.findMany();
83
- return [{ id: 1, name: 'Sample ${PascalCaseName}' }]; // Placeholder
84
- },
85
-
86
- async getById(id: string) {
87
- // return prisma.${camelCaseName}.findUnique({ where: { id } });
88
- return { id, name: 'Sample ${PascalCaseName}' }; // Placeholder
89
- },
90
-
91
- async create(data: any) {
92
- // return prisma.${camelCaseName}.create({ data });
93
- return { id: Date.now(), ...data }; // Placeholder
94
- },
95
-
96
- async update(id: string, data: any) {
97
- // return prisma.${camelCaseName}.update({ where: { id }, data });
98
- return { id, ...data }; // Placeholder
99
- },
100
-
101
- async delete(id: string) {
102
- // return prisma.${camelCaseName}.delete({ where: { id } });
103
- return true; // Placeholder
104
- }
105
- };
106
- `;
107
-
108
- // 3. Create Route
109
- const routeContent = `import { Router } from 'express';
110
- import { ${PascalCaseName}Controller } from '../controllers/${camelCaseName}Controller';
111
- import { authenticateToken } from '../middleware/auth';
112
-
113
- const router = Router();
114
-
115
- router.get('/', authenticateToken, ${PascalCaseName}Controller.getAll);
116
- router.get('/:id', authenticateToken, ${PascalCaseName}Controller.getById);
117
- router.post('/', authenticateToken, ${PascalCaseName}Controller.create);
118
- router.put('/:id', authenticateToken, ${PascalCaseName}Controller.update);
119
- router.delete('/:id', authenticateToken, ${PascalCaseName}Controller.delete);
120
-
121
- export default router;
122
- `;
123
-
124
- const paths = {
125
- controller: path.join(srcDir, 'controllers', `${camelCaseName}Controller.ts`),
126
- service: path.join(srcDir, 'services', `${camelCaseName}Service.ts`),
127
- route: path.join(srcDir, 'routes', `${camelCaseName}.ts`),
128
- };
129
-
130
- // Helper to create directory if not exists
131
- function ensureDir(filePath) {
132
- const dirname = path.dirname(filePath);
133
- if (!fs.existsSync(dirname)) {
134
- fs.mkdirSync(dirname, { recursive: true });
135
- }
136
- }
137
-
138
- try {
139
- ensureDir(paths.controller);
140
- fs.writeFileSync(paths.controller, controllerContent);
141
- console.log(`✅ Created Controller: src/controllers/${camelCaseName}Controller.ts`);
142
-
143
- ensureDir(paths.service);
144
- fs.writeFileSync(paths.service, serviceContent);
145
- console.log(`✅ Created Service: src/services/${camelCaseName}Service.ts`);
146
-
147
- ensureDir(paths.route);
148
- fs.writeFileSync(paths.route, routeContent);
149
- console.log(`✅ Created Route: src/routes/${camelCaseName}.ts`);
150
-
151
- console.log('\n⚠️ Don\'t forget to register the new route in src/index.ts or src/server.ts!');
152
- console.log(` import ${camelCaseName}Routes from './routes/${camelCaseName}';`);
153
- console.log(` app.use('/${camelCaseName}s', ${camelCaseName}Routes);`);
154
-
155
- } catch (error) {
156
- console.error('❌ Error creating module:', error);
157
- process.exit(1);
158
- }
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const args = process.argv.slice(2);
5
+ const moduleName = args[0];
6
+
7
+ if (!moduleName) {
8
+ console.error(' Please specify the module name.');
9
+ console.error(' Usage: npm run make:module <ModuleName>');
10
+ process.exit(1);
11
+ }
12
+
13
+ // Capitalize first letter
14
+ const name = moduleName.charAt(0).toUpperCase() + moduleName.slice(1);
15
+ const lowerName = moduleName.toLowerCase();
16
+
17
+ const moduleDir = path.join(__dirname, '..', 'src', 'modules', name);
18
+
19
+ if (fs.existsSync(moduleDir)) {
20
+ console.error(`❌ Module ${name} already exists at ${moduleDir}`);
21
+ process.exit(1);
22
+ }
23
+
24
+ fs.mkdirSync(moduleDir, { recursive: true });
25
+
26
+ // Controller
27
+ const controllerContent = `import { Request, Response } from "express";
28
+ import { sendSuccess } from "@lapeh/utils/response";
29
+ // import * as ${name}Service from "./${lowerName}.service";
30
+
31
+ export async function index(_req: Request, res: Response) {
32
+ sendSuccess(res, 200, "Index ${name}");
33
+ }
34
+
35
+ export async function show(req: Request, res: Response) {
36
+ const { id } = req.params;
37
+ sendSuccess(res, 200, "Show ${name} " + id);
38
+ }
39
+
40
+ export async function create(_req: Request, res: Response) {
41
+ sendSuccess(res, 201, "Create ${name}");
42
+ }
43
+
44
+ export async function update(req: Request, res: Response) {
45
+ const { id } = req.params;
46
+ sendSuccess(res, 200, "Update ${name} " + id);
47
+ }
48
+
49
+ export async function destroy(req: Request, res: Response) {
50
+ const { id } = req.params;
51
+ sendSuccess(res, 200, "Delete ${name} " + id);
52
+ }
53
+ `;
54
+
55
+ fs.writeFileSync(path.join(moduleDir, `${lowerName}.controller.ts`), controllerContent);
56
+
57
+ // Service (Optional but good for NestJS style)
58
+ const serviceContent = `// import { prisma } from "@lapeh/core/database";
59
+
60
+ export async function findAll() {
61
+ return [];
62
+ }
63
+
64
+ export async function findOne(_id: number) {
65
+ return null;
66
+ }
67
+ `;
68
+ fs.writeFileSync(path.join(moduleDir, `${lowerName}.service.ts`), serviceContent);
69
+
70
+ // Route Stub
71
+ const routeContent = `import { Router } from "express";
72
+ import * as ${name}Controller from "./${lowerName}.controller";
73
+
74
+ const router = Router();
75
+
76
+ router.get("/", ${name}Controller.index);
77
+ router.get("/:id", ${name}Controller.show);
78
+ router.post("/", ${name}Controller.create);
79
+ router.put("/:id", ${name}Controller.update);
80
+ router.delete("/:id", ${name}Controller.destroy);
81
+
82
+ export default router;
83
+ `;
84
+ fs.writeFileSync(path.join(moduleDir, `${lowerName}.routes.ts`), routeContent);
85
+
86
+ // Prisma Model
87
+ const prismaContent = `model ${name} {
88
+ id String @id @default(uuid())
89
+ createdAt DateTime @default(now())
90
+ updatedAt DateTime @updatedAt
91
+ }
92
+ `;
93
+ fs.writeFileSync(path.join(moduleDir, `${lowerName}.prisma`), prismaContent);
94
+
95
+ console.log(`✅ Module ${name} created successfully at src/modules/${name}`);
96
+ console.log(` - ${lowerName}.controller.ts`);
97
+ console.log(` - ${lowerName}.service.ts`);
98
+ console.log(` - ${lowerName}.routes.ts`);
99
+ console.log(` - ${lowerName}.prisma`);
100
+ console.log(`\n👉 Don't forget to register the route in src/routes/index.ts!`);
@@ -0,0 +1,9 @@
1
+ export const appConfig = {
2
+ name: 'Lapeh API',
3
+ timeout: 30000, // 30 seconds
4
+ compression: true,
5
+ rateLimit: {
6
+ windowMs: 15 * 60 * 1000, // 15 minutes
7
+ max: 100, // Limit each IP to 100 requests per windowMs
8
+ },
9
+ };
@@ -0,0 +1,5 @@
1
+ export const corsConfig = {
2
+ origin: process.env.CORS_ORIGIN || '*',
3
+ credentials: true,
4
+ exposedHeaders: ['x-access-token', 'x-access-expires-at'],
5
+ };
@@ -13,7 +13,7 @@ import {
13
13
  updatePassword,
14
14
  updateProfile,
15
15
  updateAvatar,
16
- } from "@/controllers/authController";
16
+ } from "@/modules/Auth/auth.controller";
17
17
  import { requireAuth } from "@lapeh/middleware/auth";
18
18
 
19
19
  const authLimiter = rateLimit({
@@ -1,5 +1,5 @@
1
1
  import { Router } from "express";
2
- import * as PetController from "@/controllers/petController";
2
+ import * as PetController from "@/modules/Pets/pets.controller";
3
3
  import { parseMultipart } from "@lapeh/middleware/multipart";
4
4
 
5
5
  const router = Router();
@@ -15,7 +15,7 @@ import {
15
15
  removePermissionFromRole,
16
16
  assignPermissionToUser,
17
17
  removePermissionFromUser,
18
- } from "@/controllers/rbacController";
18
+ } from "@/modules/Rbac/rbac.controller";
19
19
 
20
20
  export const rbacRouter = Router();
21
21
 
@@ -19,6 +19,11 @@
19
19
  "date": 1766895868212,
20
20
  "name": "E:\\PROJECT\\ANY\\2026\\lapeh\\storage\\logs\\lapeh-2025-12-28.log",
21
21
  "hash": "43121130a6745af0345b445cc3497d27a18a857e350d002848a27b0c71a577ae"
22
+ },
23
+ {
24
+ "date": 1766942707900,
25
+ "name": "E:\\PROJECT\\ANY\\2026\\lapeh\\storage\\logs\\lapeh-2025-12-29.log",
26
+ "hash": "319d94eefcace8d4eefdee311691c27d9b3ba62fa6ed32782055dc864369d5c5"
22
27
  }
23
28
  ],
24
29
  "hashType": "sha256"
@@ -0,0 +1,94 @@
1
+ [2025-12-29 00:25:08] WARN: Bad Request
2
+ Errors: {
3
+ "field": "Required"
4
+ }
5
+ Meta: {"statusCode":400}
6
+ [2025-12-29 00:25:16] INFO: GET /api/pets 200 - 17ms - ::ffff:127.0.0.1
7
+ [2025-12-29 00:25:16] INFO: GET / 200 - 15ms - ::ffff:127.0.0.1
8
+ [2025-12-29 00:25:16] INFO: GET /api/rbac/roles 200 - 16ms - ::ffff:127.0.0.1
9
+ [2025-12-29 00:25:16] INFO: GET /api/pets 200 - 18ms - ::ffff:127.0.0.1
10
+ [2025-12-29 00:25:16] INFO: GET /api/auth/me 200 - 15ms - ::ffff:127.0.0.1
11
+ [2025-12-29 00:25:16] INFO: GET /api/pets?search=Fluffy 200 - 1ms - ::ffff:127.0.0.1
12
+ [2025-12-29 00:25:16] WARN: GET /unknown 404 - 2ms - ::ffff:127.0.0.1
13
+ [2025-12-29 00:25:16] INFO: GET /api/pets/1 200 - 1ms - ::ffff:127.0.0.1
14
+ [2025-12-29 00:25:16] WARN: Pet not found
15
+ Meta: {"statusCode":404}
16
+ [2025-12-29 00:25:16] WARN: User not found
17
+ Meta: {"statusCode":404}
18
+ [2025-12-29 00:25:16] WARN: GET /api/pets/999 404 - 4ms - ::ffff:127.0.0.1
19
+ [2025-12-29 00:25:16] WARN: GET /api/auth/me 404 - 7ms - ::ffff:127.0.0.1
20
+ [2025-12-29 00:25:16] INFO: PUT /api/auth/profile 200 - 140ms - ::ffff:127.0.0.1
21
+ [2025-12-29 00:25:16] INFO: POST /api/rbac/roles 201 - 166ms - ::ffff:127.0.0.1
22
+ [2025-12-29 00:25:16] INFO: POST /api/pets 201 - 145ms - ::ffff:127.0.0.1
23
+ [2025-12-29 00:25:16] INFO: POST /api/pets 201 - 150ms - ::ffff:127.0.0.1
24
+ [2025-12-29 00:25:16] WARN: Validation error
25
+ Errors: {
26
+ "species": [
27
+ "Required"
28
+ ],
29
+ "age": [
30
+ "Expected number, received nan"
31
+ ]
32
+ }
33
+ Meta: {"statusCode":422}
34
+ [2025-12-29 00:25:16] INFO: POST /api/rbac/permissions 201 - 3ms - ::ffff:127.0.0.1
35
+ [2025-12-29 00:25:16] WARN: POST /api/pets 422 - 3ms - ::ffff:127.0.0.1
36
+ [2025-12-29 00:25:16] WARN: Validation error
37
+ Errors: {
38
+ "species": [
39
+ "Required"
40
+ ],
41
+ "age": [
42
+ "Expected number, received nan"
43
+ ]
44
+ }
45
+ Meta: {"statusCode":422}
46
+ [2025-12-29 00:25:16] INFO: GET /api/rbac/permissions 200 - 1ms - ::ffff:127.0.0.1
47
+ [2025-12-29 00:25:16] INFO: PUT /api/pets/1 200 - 2ms - ::ffff:127.0.0.1
48
+ [2025-12-29 00:25:16] WARN: POST /api/pets 422 - 9ms - ::ffff:127.0.0.1
49
+ [2025-12-29 00:25:16] WARN: Pet not found
50
+ Meta: {"statusCode":404}
51
+ [2025-12-29 00:25:16] WARN: PUT /api/pets/999 404 - 3ms - ::ffff:127.0.0.1
52
+ [2025-12-29 00:25:17] INFO: GET /api/pets/1 200 - 2ms - ::ffff:127.0.0.1
53
+ [2025-12-29 00:25:17] INFO: POST /api/rbac/users/assign-role 200 - 2ms - ::ffff:127.0.0.1
54
+ [2025-12-29 00:25:17] INFO: DELETE /api/pets/1 200 - 2ms - ::ffff:127.0.0.1
55
+ [2025-12-29 00:25:17] WARN: Pet not found
56
+ Meta: {"statusCode":404}
57
+ [2025-12-29 00:25:17] WARN: GET /api/pets/999 404 - 2ms - ::ffff:127.0.0.1
58
+ [2025-12-29 00:25:17] WARN: User not found
59
+ Meta: {"statusCode":404}
60
+ [2025-12-29 00:25:17] WARN: Pet not found
61
+ Meta: {"statusCode":404}
62
+ [2025-12-29 00:25:17] INFO: PUT /api/pets/1 200 - 1ms - ::ffff:127.0.0.1
63
+ [2025-12-29 00:25:17] WARN: DELETE /api/pets/999 404 - 2ms - ::ffff:127.0.0.1
64
+ [2025-12-29 00:25:17] WARN: POST /api/rbac/users/assign-role 404 - 6ms - ::ffff:127.0.0.1
65
+ [2025-12-29 00:25:17] WARN: Pet not found
66
+ Meta: {"statusCode":404}
67
+ [2025-12-29 00:25:17] WARN: PUT /api/pets/999 404 - 2ms - ::ffff:127.0.0.1
68
+ [2025-12-29 00:25:17] INFO: DELETE /api/pets/1 200 - 1ms - ::ffff:127.0.0.1
69
+ [2025-12-29 00:25:17] WARN: Pet not found
70
+ Meta: {"statusCode":404}
71
+ [2025-12-29 00:25:17] WARN: DELETE /api/pets/999 404 - 1ms - ::ffff:127.0.0.1
72
+ [2025-12-29 00:25:17] INFO: POST /api/auth/register 201 - 320ms - ::ffff:127.0.0.1
73
+ [2025-12-29 00:25:17] WARN: Validation error
74
+ Errors: {
75
+ "email": [
76
+ "The email has already been taken."
77
+ ]
78
+ }
79
+ Meta: {"statusCode":422}
80
+ [2025-12-29 00:25:17] WARN: POST /api/auth/register 422 - 5ms - ::ffff:127.0.0.1
81
+ [2025-12-29 00:25:17] INFO: PUT /api/auth/password 200 - 121ms - ::ffff:127.0.0.1
82
+ [2025-12-29 00:25:17] INFO: POST /api/auth/login 200 - 68ms - ::ffff:127.0.0.1
83
+ [2025-12-29 00:25:17] WARN: Invalid credentials
84
+ Errors: {
85
+ "field": "currentPassword",
86
+ "message": "Current password is incorrect"
87
+ }
88
+ Meta: {"statusCode":401}
89
+ [2025-12-29 00:25:17] WARN: PUT /api/auth/password 401 - 59ms - ::ffff:127.0.0.1
90
+ [2025-12-29 00:25:17] INFO: POST /api/auth/refresh 200 - 2ms - ::ffff:127.0.0.1
91
+ [2025-12-29 00:25:17] WARN: Invalid refresh token
92
+ Meta: {"statusCode":401}
93
+ [2025-12-29 00:25:17] WARN: POST /api/auth/refresh 401 - 2ms - ::ffff:127.0.0.1
94
+ [2025-12-29 00:25:17] INFO: POST /api/auth/avatar 200 - 5ms - ::ffff:127.0.0.1