lapeh 2.3.6 → 2.3.8
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 +39 -56
- package/dist/generated/prisma/browser.d.ts +80 -0
- package/dist/generated/prisma/browser.d.ts.map +1 -0
- package/dist/generated/prisma/browser.js +56 -0
- package/dist/generated/prisma/client.d.ts +97 -0
- package/dist/generated/prisma/client.d.ts.map +1 -0
- package/dist/generated/prisma/client.js +68 -0
- package/dist/generated/prisma/commonInputTypes.d.ts +486 -0
- package/dist/generated/prisma/commonInputTypes.d.ts.map +1 -0
- package/dist/generated/prisma/commonInputTypes.js +11 -0
- package/dist/generated/prisma/enums.d.ts +2 -0
- package/dist/generated/prisma/enums.d.ts.map +1 -0
- package/dist/generated/prisma/enums.js +11 -0
- package/dist/generated/prisma/internal/class.d.ts +281 -0
- package/dist/generated/prisma/internal/class.d.ts.map +1 -0
- package/dist/generated/prisma/internal/class.js +76 -0
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +1734 -0
- package/dist/generated/prisma/internal/prismaNamespace.d.ts.map +1 -0
- package/dist/generated/prisma/internal/prismaNamespace.js +260 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +200 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts.map +1 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +231 -0
- package/dist/generated/prisma/models/cache.d.ts +986 -0
- package/dist/generated/prisma/models/cache.d.ts.map +1 -0
- package/dist/generated/prisma/models/cache.js +2 -0
- package/dist/generated/prisma/models/cache_locks.d.ts +976 -0
- package/dist/generated/prisma/models/cache_locks.d.ts.map +1 -0
- package/dist/generated/prisma/models/cache_locks.js +2 -0
- package/dist/generated/prisma/models/failed_jobs.d.ts +1098 -0
- package/dist/generated/prisma/models/failed_jobs.d.ts.map +1 -0
- package/dist/generated/prisma/models/failed_jobs.js +2 -0
- package/dist/generated/prisma/models/job_batches.d.ts +1212 -0
- package/dist/generated/prisma/models/job_batches.d.ts.map +1 -0
- package/dist/generated/prisma/models/job_batches.js +2 -0
- package/dist/generated/prisma/models/jobs.d.ts +1112 -0
- package/dist/generated/prisma/models/jobs.d.ts.map +1 -0
- package/dist/generated/prisma/models/jobs.js +2 -0
- package/dist/generated/prisma/models/migrations.d.ts +979 -0
- package/dist/generated/prisma/models/migrations.d.ts.map +1 -0
- package/dist/generated/prisma/models/migrations.js +2 -0
- package/dist/generated/prisma/models/password_reset_tokens.d.ts +941 -0
- package/dist/generated/prisma/models/password_reset_tokens.d.ts.map +1 -0
- package/dist/generated/prisma/models/password_reset_tokens.js +2 -0
- package/dist/generated/prisma/models/permissions.d.ts +1333 -0
- package/dist/generated/prisma/models/permissions.d.ts.map +1 -0
- package/dist/generated/prisma/models/permissions.js +2 -0
- package/dist/generated/prisma/models/personal_access_tokens.d.ts +1178 -0
- package/dist/generated/prisma/models/personal_access_tokens.d.ts.map +1 -0
- package/dist/generated/prisma/models/personal_access_tokens.js +2 -0
- package/dist/generated/prisma/models/role_permissions.d.ts +1291 -0
- package/dist/generated/prisma/models/role_permissions.d.ts.map +1 -0
- package/dist/generated/prisma/models/role_permissions.js +2 -0
- package/dist/generated/prisma/models/roles.d.ts +1333 -0
- package/dist/generated/prisma/models/roles.d.ts.map +1 -0
- package/dist/generated/prisma/models/roles.js +2 -0
- package/dist/generated/prisma/models/sessions.d.ts +1073 -0
- package/dist/generated/prisma/models/sessions.d.ts.map +1 -0
- package/dist/generated/prisma/models/sessions.js +2 -0
- package/dist/generated/prisma/models/user_permissions.d.ts +1291 -0
- package/dist/generated/prisma/models/user_permissions.d.ts.map +1 -0
- package/dist/generated/prisma/models/user_permissions.js +2 -0
- package/dist/generated/prisma/models/user_roles.d.ts +1291 -0
- package/dist/generated/prisma/models/user_roles.d.ts.map +1 -0
- package/dist/generated/prisma/models/user_roles.js +2 -0
- package/dist/generated/prisma/models/users.d.ts +1513 -0
- package/dist/generated/prisma/models/users.d.ts.map +1 -0
- package/dist/generated/prisma/models/users.js +2 -0
- package/dist/generated/prisma/models.d.ts +17 -0
- package/dist/generated/prisma/models.d.ts.map +1 -0
- package/dist/generated/prisma/models.js +2 -0
- package/dist/lib/bootstrap.d.ts +2 -0
- package/dist/lib/bootstrap.d.ts.map +1 -0
- package/dist/lib/bootstrap.js +133 -0
- package/dist/lib/core/database.d.ts +3 -0
- package/dist/lib/core/database.d.ts.map +1 -0
- package/dist/lib/core/database.js +34 -0
- package/dist/lib/core/realtime.d.ts +3 -0
- package/dist/lib/core/realtime.d.ts.map +1 -0
- package/dist/lib/core/realtime.js +36 -0
- package/dist/lib/core/redis.d.ts +8 -0
- package/dist/lib/core/redis.d.ts.map +1 -0
- package/dist/lib/core/redis.js +123 -0
- package/dist/lib/core/serializer.d.ts +43 -0
- package/dist/lib/core/serializer.d.ts.map +1 -0
- package/dist/lib/core/serializer.js +66 -0
- package/dist/lib/core/server.d.ts +2 -0
- package/dist/lib/core/server.d.ts.map +1 -0
- package/dist/lib/core/server.js +60 -0
- package/dist/lib/middleware/auth.d.ts +4 -0
- package/dist/lib/middleware/auth.d.ts.map +1 -0
- package/dist/lib/middleware/auth.js +55 -0
- package/dist/lib/middleware/error.d.ts +3 -0
- package/dist/lib/middleware/error.d.ts.map +1 -0
- package/dist/lib/middleware/error.js +60 -0
- package/dist/lib/middleware/multipart.d.ts +4 -0
- package/dist/lib/middleware/multipart.d.ts.map +1 -0
- package/dist/lib/middleware/multipart.js +17 -0
- package/dist/lib/middleware/rateLimit.d.ts +2 -0
- package/dist/lib/middleware/rateLimit.d.ts.map +1 -0
- package/dist/lib/middleware/rateLimit.js +19 -0
- package/dist/lib/middleware/requestLogger.d.ts +3 -0
- package/dist/lib/middleware/requestLogger.d.ts.map +1 -0
- package/dist/lib/middleware/requestLogger.js +22 -0
- package/dist/lib/middleware/visitor.d.ts +3 -0
- package/dist/lib/middleware/visitor.d.ts.map +1 -0
- package/dist/lib/middleware/visitor.js +144 -0
- package/dist/lib/utils/logger.d.ts +11 -0
- package/dist/lib/utils/logger.d.ts.map +1 -0
- package/dist/lib/utils/logger.js +81 -0
- package/dist/lib/utils/pagination.d.ts +19 -0
- package/dist/lib/utils/pagination.d.ts.map +1 -0
- package/dist/lib/utils/pagination.js +34 -0
- package/dist/lib/utils/response.d.ts +11 -0
- package/dist/lib/utils/response.d.ts.map +1 -0
- package/dist/lib/utils/response.js +57 -0
- package/dist/lib/utils/validator.d.ts +38 -0
- package/dist/lib/utils/validator.d.ts.map +1 -0
- package/dist/lib/utils/validator.js +369 -0
- package/dist/prisma/seed.d.ts +2 -0
- package/dist/prisma/seed.d.ts.map +1 -0
- package/dist/prisma/seed.js +381 -0
- package/dist/src/controllers/authController.d.ts +11 -0
- package/dist/src/controllers/authController.d.ts.map +1 -0
- package/dist/src/controllers/authController.js +414 -0
- package/dist/src/controllers/petController.d.ts +7 -0
- package/dist/src/controllers/petController.d.ts.map +1 -0
- package/dist/src/controllers/petController.js +163 -0
- package/dist/src/controllers/rbacController.d.ts +16 -0
- package/dist/src/controllers/rbacController.d.ts.map +1 -0
- package/dist/src/controllers/rbacController.js +437 -0
- package/dist/src/core/database.d.ts +3 -0
- package/dist/src/core/database.d.ts.map +1 -0
- package/dist/src/core/database.js +34 -0
- package/dist/src/core/realtime.d.ts +3 -0
- package/dist/src/core/realtime.d.ts.map +1 -0
- package/dist/src/core/realtime.js +36 -0
- package/dist/src/core/redis.d.ts +8 -0
- package/dist/src/core/redis.d.ts.map +1 -0
- package/dist/src/core/redis.js +123 -0
- package/dist/src/core/serializer.d.ts +43 -0
- package/dist/src/core/serializer.d.ts.map +1 -0
- package/dist/src/core/serializer.js +66 -0
- package/dist/src/core/server.d.ts +2 -0
- package/dist/src/core/server.d.ts.map +1 -0
- package/dist/src/core/server.js +60 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +98 -0
- package/dist/src/middleware/auth.d.ts +4 -0
- package/dist/src/middleware/auth.d.ts.map +1 -0
- package/dist/src/middleware/auth.js +48 -0
- package/dist/src/middleware/error.d.ts +3 -0
- package/dist/src/middleware/error.d.ts.map +1 -0
- package/dist/src/middleware/error.js +60 -0
- package/dist/src/middleware/multipart.d.ts +4 -0
- package/dist/src/middleware/multipart.d.ts.map +1 -0
- package/dist/src/middleware/multipart.js +17 -0
- package/dist/src/middleware/rateLimit.d.ts +2 -0
- package/dist/src/middleware/rateLimit.d.ts.map +1 -0
- package/dist/src/middleware/rateLimit.js +19 -0
- package/dist/src/middleware/requestLogger.d.ts +3 -0
- package/dist/src/middleware/requestLogger.d.ts.map +1 -0
- package/dist/src/middleware/requestLogger.js +22 -0
- package/dist/src/middleware/visitor.d.ts +3 -0
- package/dist/src/middleware/visitor.d.ts.map +1 -0
- package/dist/src/middleware/visitor.js +144 -0
- package/dist/src/prisma.d.ts +3 -0
- package/dist/src/prisma.d.ts.map +1 -0
- package/dist/src/prisma.js +34 -0
- package/dist/src/realtime.d.ts +3 -0
- package/dist/src/realtime.d.ts.map +1 -0
- package/dist/src/realtime.js +36 -0
- package/dist/src/redis.d.ts +8 -0
- package/dist/src/redis.d.ts.map +1 -0
- package/dist/src/redis.js +122 -0
- package/dist/src/routes/auth.d.ts +2 -0
- package/dist/src/routes/auth.d.ts.map +1 -0
- package/dist/src/routes/auth.js +45 -0
- package/dist/src/routes/index.d.ts +2 -0
- package/dist/src/routes/index.d.ts.map +1 -0
- package/dist/src/routes/index.js +14 -0
- package/dist/src/routes/pets.d.ts +3 -0
- package/dist/src/routes/pets.d.ts.map +1 -0
- package/dist/src/routes/pets.js +45 -0
- package/dist/src/routes/rbac.d.ts +2 -0
- package/dist/src/routes/rbac.d.ts.map +1 -0
- package/dist/src/routes/rbac.js +23 -0
- package/dist/src/schema/auth-schema.d.ts +76 -0
- package/dist/src/schema/auth-schema.d.ts.map +1 -0
- package/dist/src/schema/auth-schema.js +63 -0
- package/dist/src/schema/pet-schema.d.ts +28 -0
- package/dist/src/schema/pet-schema.d.ts.map +1 -0
- package/dist/src/schema/pet-schema.js +14 -0
- package/dist/src/server.d.ts +2 -0
- package/dist/src/server.d.ts.map +1 -0
- package/dist/src/server.js +31 -0
- package/dist/src/utils/logger.d.ts +11 -0
- package/dist/src/utils/logger.d.ts.map +1 -0
- package/dist/src/utils/logger.js +81 -0
- package/dist/src/utils/pagination.d.ts +19 -0
- package/dist/src/utils/pagination.d.ts.map +1 -0
- package/dist/src/utils/pagination.js +34 -0
- package/dist/src/utils/response.d.ts +11 -0
- package/dist/src/utils/response.d.ts.map +1 -0
- package/dist/src/utils/response.js +57 -0
- package/dist/src/utils/validator.d.ts +38 -0
- package/dist/src/utils/validator.d.ts.map +1 -0
- package/dist/src/utils/validator.js +369 -0
- package/lib/bootstrap.ts +6 -0
- package/package.json +26 -14
- package/.env.example +0 -19
- package/doc/ARCHITECTURE_GUIDE.md +0 -73
- package/doc/CHANGELOG.md +0 -77
- package/doc/CHEATSHEET.md +0 -94
- package/doc/CLI.md +0 -139
- package/doc/CONTRIBUTING.md +0 -105
- package/doc/DEPLOYMENT.md +0 -122
- package/doc/FAQ.md +0 -81
- package/doc/FEATURES.md +0 -165
- package/doc/GETTING_STARTED.md +0 -108
- package/doc/INTRODUCTION.md +0 -60
- package/doc/PACKAGES.md +0 -66
- package/doc/PERFORMANCE.md +0 -91
- package/doc/ROADMAP.md +0 -93
- package/doc/SECURITY.md +0 -93
- package/doc/STRUCTURE.md +0 -90
- package/doc/TUTORIAL.md +0 -192
- package/docker-compose.yml +0 -24
- package/eslint.config.mjs +0 -26
- package/framework.md +0 -168
- package/nodemon.json +0 -6
- package/prisma.config.ts +0 -15
- package/src/controllers/authController.ts +0 -469
- package/src/controllers/petController.ts +0 -194
- package/src/controllers/rbacController.ts +0 -478
- package/src/models/core.prisma +0 -163
- package/src/models/pets.prisma +0 -9
- package/src/routes/auth.ts +0 -74
- package/src/routes/index.ts +0 -10
- package/src/routes/pets.ts +0 -13
- package/src/routes/rbac.ts +0 -42
- package/storage/logs/.gitkeep +0 -0
- package/tsconfig.json +0 -30
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createRole = createRole;
|
|
4
|
+
exports.listRoles = listRoles;
|
|
5
|
+
exports.updateRole = updateRole;
|
|
6
|
+
exports.deleteRole = deleteRole;
|
|
7
|
+
exports.createPermission = createPermission;
|
|
8
|
+
exports.listPermissions = listPermissions;
|
|
9
|
+
exports.updatePermission = updatePermission;
|
|
10
|
+
exports.deletePermission = deletePermission;
|
|
11
|
+
exports.assignRoleToUser = assignRoleToUser;
|
|
12
|
+
exports.removeRoleFromUser = removeRoleFromUser;
|
|
13
|
+
exports.assignPermissionToRole = assignPermissionToRole;
|
|
14
|
+
exports.removePermissionFromRole = removePermissionFromRole;
|
|
15
|
+
exports.assignPermissionToUser = assignPermissionToUser;
|
|
16
|
+
exports.removePermissionFromUser = removePermissionFromUser;
|
|
17
|
+
const database_1 = require("../../lib/core/database");
|
|
18
|
+
const response_1 = require("../../lib/utils/response");
|
|
19
|
+
const validator_1 = require("../../lib/utils/validator");
|
|
20
|
+
const zod_1 = require("zod");
|
|
21
|
+
const serializer_1 = require("../../lib/core/serializer");
|
|
22
|
+
// --- Serializers ---
|
|
23
|
+
const roleSchema = {
|
|
24
|
+
type: "object",
|
|
25
|
+
properties: {
|
|
26
|
+
id: { type: "string" },
|
|
27
|
+
name: { type: "string" },
|
|
28
|
+
slug: { type: "string" },
|
|
29
|
+
description: { type: "string", nullable: true },
|
|
30
|
+
created_at: { type: "string", format: "date-time", nullable: true },
|
|
31
|
+
updated_at: { type: "string", format: "date-time", nullable: true },
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
const permissionSchema = {
|
|
35
|
+
type: "object",
|
|
36
|
+
properties: {
|
|
37
|
+
id: { type: "string" },
|
|
38
|
+
name: { type: "string" },
|
|
39
|
+
slug: { type: "string" },
|
|
40
|
+
description: { type: "string", nullable: true },
|
|
41
|
+
created_at: { type: "string", format: "date-time", nullable: true },
|
|
42
|
+
updated_at: { type: "string", format: "date-time", nullable: true },
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
const roleSerializer = (0, serializer_1.getSerializer)("role", (0, serializer_1.createResponseSchema)(roleSchema));
|
|
46
|
+
const roleListSerializer = (0, serializer_1.getSerializer)("role-list", (0, serializer_1.createResponseSchema)({ type: "array", items: roleSchema }));
|
|
47
|
+
const permissionSerializer = (0, serializer_1.getSerializer)("permission", (0, serializer_1.createResponseSchema)(permissionSchema));
|
|
48
|
+
const permissionListSerializer = (0, serializer_1.getSerializer)("permission-list", (0, serializer_1.createResponseSchema)({ type: "array", items: permissionSchema }));
|
|
49
|
+
const voidSerializer = (0, serializer_1.getSerializer)("void", (0, serializer_1.createResponseSchema)({ type: "null" }));
|
|
50
|
+
// --- Controllers ---
|
|
51
|
+
async function createRole(req, res) {
|
|
52
|
+
const validator = validator_1.Validator.make(req.body || {}, {
|
|
53
|
+
name: "required|string|min:1",
|
|
54
|
+
slug: "required|string|min:1|unique:roles,slug",
|
|
55
|
+
description: "string",
|
|
56
|
+
});
|
|
57
|
+
if (await validator.fails()) {
|
|
58
|
+
(0, response_1.sendError)(res, 422, "Validation error", validator.errors());
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const { name, slug, description } = await validator.validated();
|
|
62
|
+
// Manual unique check removed as it is handled by validator
|
|
63
|
+
const role = await database_1.prisma.roles.create({
|
|
64
|
+
data: {
|
|
65
|
+
name,
|
|
66
|
+
slug,
|
|
67
|
+
description: description || null,
|
|
68
|
+
created_at: new Date(),
|
|
69
|
+
updated_at: new Date(),
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
(0, response_1.sendFastSuccess)(res, 201, roleSerializer, {
|
|
73
|
+
status: "success",
|
|
74
|
+
message: "Role created",
|
|
75
|
+
data: { ...role, id: role.id.toString() },
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
async function listRoles(_req, res) {
|
|
79
|
+
const roles = await database_1.prisma.roles.findMany({
|
|
80
|
+
orderBy: { id: "asc" },
|
|
81
|
+
});
|
|
82
|
+
const serialized = roles.map((r) => ({ ...r, id: r.id.toString() }));
|
|
83
|
+
(0, response_1.sendFastSuccess)(res, 200, roleListSerializer, {
|
|
84
|
+
status: "success",
|
|
85
|
+
message: "Roles list",
|
|
86
|
+
data: serialized,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
async function updateRole(req, res) {
|
|
90
|
+
const { id } = req.params;
|
|
91
|
+
const roleId = BigInt(id);
|
|
92
|
+
const validator = validator_1.Validator.make(req.body || {}, {
|
|
93
|
+
name: "string",
|
|
94
|
+
slug: `string|unique:roles,slug,${id}`,
|
|
95
|
+
description: "string",
|
|
96
|
+
});
|
|
97
|
+
if (await validator.fails()) {
|
|
98
|
+
(0, response_1.sendError)(res, 422, "Validation error", validator.errors());
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const { name, slug, description } = await validator.validated();
|
|
102
|
+
const role = await database_1.prisma.roles.findUnique({ where: { id: roleId } });
|
|
103
|
+
if (!role) {
|
|
104
|
+
(0, response_1.sendError)(res, 404, "Role not found");
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
// Manual unique check removed as it is handled by validator
|
|
108
|
+
const updated = await database_1.prisma.roles.update({
|
|
109
|
+
where: { id: roleId },
|
|
110
|
+
data: {
|
|
111
|
+
name: name ?? role.name,
|
|
112
|
+
slug: slug ?? role.slug,
|
|
113
|
+
description: description ?? role.description,
|
|
114
|
+
updated_at: new Date(),
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
(0, response_1.sendFastSuccess)(res, 200, roleSerializer, {
|
|
118
|
+
status: "success",
|
|
119
|
+
message: "Role updated",
|
|
120
|
+
data: { ...updated, id: updated.id.toString() },
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
async function deleteRole(req, res) {
|
|
124
|
+
const { id } = req.params;
|
|
125
|
+
const roleId = BigInt(id);
|
|
126
|
+
const role = await database_1.prisma.roles.findUnique({ where: { id: roleId } });
|
|
127
|
+
if (!role) {
|
|
128
|
+
(0, response_1.sendError)(res, 404, "Role not found");
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
await database_1.prisma.role_permissions.deleteMany({ where: { role_id: roleId } });
|
|
132
|
+
await database_1.prisma.user_roles.deleteMany({ where: { role_id: roleId } });
|
|
133
|
+
await database_1.prisma.roles.delete({ where: { id: roleId } });
|
|
134
|
+
(0, response_1.sendFastSuccess)(res, 200, voidSerializer, {
|
|
135
|
+
status: "success",
|
|
136
|
+
message: "Role deleted",
|
|
137
|
+
data: null,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
async function createPermission(req, res) {
|
|
141
|
+
const validator = validator_1.Validator.make(req.body || {}, {
|
|
142
|
+
name: "required|string|min:1",
|
|
143
|
+
slug: "required|string|min:1|unique:permissions,slug",
|
|
144
|
+
description: "string",
|
|
145
|
+
});
|
|
146
|
+
if (await validator.fails()) {
|
|
147
|
+
(0, response_1.sendError)(res, 422, "Validation error", validator.errors());
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const { name, slug, description } = await validator.validated();
|
|
151
|
+
// Manual unique check removed as it is handled by validator
|
|
152
|
+
const permission = await database_1.prisma.permissions.create({
|
|
153
|
+
data: {
|
|
154
|
+
name,
|
|
155
|
+
slug,
|
|
156
|
+
description: description || null,
|
|
157
|
+
created_at: new Date(),
|
|
158
|
+
updated_at: new Date(),
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
(0, response_1.sendFastSuccess)(res, 201, permissionSerializer, {
|
|
162
|
+
status: "success",
|
|
163
|
+
message: "Permission created",
|
|
164
|
+
data: { ...permission, id: permission.id.toString() },
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
async function listPermissions(_req, res) {
|
|
168
|
+
const permissions = await database_1.prisma.permissions.findMany({
|
|
169
|
+
orderBy: { id: "asc" },
|
|
170
|
+
});
|
|
171
|
+
const serialized = permissions.map((p) => ({
|
|
172
|
+
...p,
|
|
173
|
+
id: p.id.toString(),
|
|
174
|
+
}));
|
|
175
|
+
(0, response_1.sendFastSuccess)(res, 200, permissionListSerializer, {
|
|
176
|
+
status: "success",
|
|
177
|
+
message: "Permissions list",
|
|
178
|
+
data: serialized,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
async function updatePermission(req, res) {
|
|
182
|
+
const { id } = req.params;
|
|
183
|
+
const permissionId = BigInt(id);
|
|
184
|
+
const validator = validator_1.Validator.make(req.body || {}, {
|
|
185
|
+
name: "string",
|
|
186
|
+
slug: `string|unique:permissions,slug,${id}`,
|
|
187
|
+
description: "string",
|
|
188
|
+
});
|
|
189
|
+
if (await validator.fails()) {
|
|
190
|
+
(0, response_1.sendError)(res, 422, "Validation error", validator.errors());
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const { name, slug, description } = await validator.validated();
|
|
194
|
+
const permission = await database_1.prisma.permissions.findUnique({
|
|
195
|
+
where: { id: permissionId },
|
|
196
|
+
});
|
|
197
|
+
if (!permission) {
|
|
198
|
+
(0, response_1.sendError)(res, 404, "Permission not found");
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
// Manual unique check removed as it is handled by validator
|
|
202
|
+
const updated = await database_1.prisma.permissions.update({
|
|
203
|
+
where: { id: permissionId },
|
|
204
|
+
data: {
|
|
205
|
+
name: name ?? permission.name,
|
|
206
|
+
slug: slug ?? permission.slug,
|
|
207
|
+
description: description ?? permission.description,
|
|
208
|
+
updated_at: new Date(),
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
(0, response_1.sendFastSuccess)(res, 200, permissionSerializer, {
|
|
212
|
+
status: "success",
|
|
213
|
+
message: "Permission updated",
|
|
214
|
+
data: { ...updated, id: updated.id.toString() },
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
async function deletePermission(req, res) {
|
|
218
|
+
const { id } = req.params;
|
|
219
|
+
const permissionId = BigInt(id);
|
|
220
|
+
const permission = await database_1.prisma.permissions.findUnique({
|
|
221
|
+
where: { id: permissionId },
|
|
222
|
+
});
|
|
223
|
+
if (!permission) {
|
|
224
|
+
(0, response_1.sendError)(res, 404, "Permission not found");
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
await database_1.prisma.role_permissions.deleteMany({
|
|
228
|
+
where: { permission_id: permissionId },
|
|
229
|
+
});
|
|
230
|
+
await database_1.prisma.user_permissions.deleteMany({
|
|
231
|
+
where: { permission_id: permissionId },
|
|
232
|
+
});
|
|
233
|
+
await database_1.prisma.permissions.delete({ where: { id: permissionId } });
|
|
234
|
+
(0, response_1.sendFastSuccess)(res, 200, voidSerializer, {
|
|
235
|
+
status: "success",
|
|
236
|
+
message: "Permission deleted",
|
|
237
|
+
data: null,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
async function assignRoleToUser(req, res) {
|
|
241
|
+
const validator = validator_1.Validator.make(req.body || {}, {
|
|
242
|
+
userId: zod_1.z.string().min(1, "userId wajib diisi"),
|
|
243
|
+
roleId: zod_1.z.string().min(1, "roleId wajib diisi"),
|
|
244
|
+
});
|
|
245
|
+
if (await validator.fails()) {
|
|
246
|
+
(0, response_1.sendError)(res, 422, "Validation error", validator.errors());
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
const { userId, roleId } = await validator.validated();
|
|
250
|
+
const user = await database_1.prisma.users.findUnique({
|
|
251
|
+
where: { id: BigInt(userId) },
|
|
252
|
+
});
|
|
253
|
+
if (!user) {
|
|
254
|
+
(0, response_1.sendError)(res, 404, "User not found");
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const role = await database_1.prisma.roles.findUnique({
|
|
258
|
+
where: { id: BigInt(roleId) },
|
|
259
|
+
});
|
|
260
|
+
if (!role) {
|
|
261
|
+
(0, response_1.sendError)(res, 404, "Role not found");
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
await database_1.prisma.user_roles.upsert({
|
|
265
|
+
where: {
|
|
266
|
+
user_id_role_id: {
|
|
267
|
+
user_id: BigInt(userId),
|
|
268
|
+
role_id: BigInt(roleId),
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
create: {
|
|
272
|
+
user_id: BigInt(userId),
|
|
273
|
+
role_id: BigInt(roleId),
|
|
274
|
+
created_at: new Date(),
|
|
275
|
+
},
|
|
276
|
+
update: {},
|
|
277
|
+
});
|
|
278
|
+
(0, response_1.sendFastSuccess)(res, 200, voidSerializer, {
|
|
279
|
+
status: "success",
|
|
280
|
+
message: "Role assigned to user",
|
|
281
|
+
data: null,
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
async function removeRoleFromUser(req, res) {
|
|
285
|
+
const validator = validator_1.Validator.make(req.body || {}, {
|
|
286
|
+
userId: zod_1.z.string().min(1, "userId wajib diisi"),
|
|
287
|
+
roleId: zod_1.z.string().min(1, "roleId wajib diisi"),
|
|
288
|
+
});
|
|
289
|
+
if (await validator.fails()) {
|
|
290
|
+
(0, response_1.sendError)(res, 422, "Validation error", validator.errors());
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
const { userId, roleId } = await validator.validated();
|
|
294
|
+
await database_1.prisma.user_roles.deleteMany({
|
|
295
|
+
where: {
|
|
296
|
+
user_id: BigInt(userId),
|
|
297
|
+
role_id: BigInt(roleId),
|
|
298
|
+
},
|
|
299
|
+
});
|
|
300
|
+
(0, response_1.sendFastSuccess)(res, 200, voidSerializer, {
|
|
301
|
+
status: "success",
|
|
302
|
+
message: "Role removed from user",
|
|
303
|
+
data: null,
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
async function assignPermissionToRole(req, res) {
|
|
307
|
+
const validator = validator_1.Validator.make(req.body || {}, {
|
|
308
|
+
roleId: zod_1.z.string().min(1, "roleId wajib diisi"),
|
|
309
|
+
permissionId: zod_1.z.string().min(1, "permissionId wajib diisi"),
|
|
310
|
+
});
|
|
311
|
+
if (await validator.fails()) {
|
|
312
|
+
(0, response_1.sendError)(res, 422, "Validation error", validator.errors());
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
const { roleId, permissionId } = await validator.validated();
|
|
316
|
+
const role = await database_1.prisma.roles.findUnique({
|
|
317
|
+
where: { id: BigInt(roleId) },
|
|
318
|
+
});
|
|
319
|
+
if (!role) {
|
|
320
|
+
(0, response_1.sendError)(res, 404, "Role not found");
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
const permission = await database_1.prisma.permissions.findUnique({
|
|
324
|
+
where: { id: BigInt(permissionId) },
|
|
325
|
+
});
|
|
326
|
+
if (!permission) {
|
|
327
|
+
(0, response_1.sendError)(res, 404, "Permission not found");
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
await database_1.prisma.role_permissions.upsert({
|
|
331
|
+
where: {
|
|
332
|
+
role_id_permission_id: {
|
|
333
|
+
role_id: BigInt(roleId),
|
|
334
|
+
permission_id: BigInt(permissionId),
|
|
335
|
+
},
|
|
336
|
+
},
|
|
337
|
+
create: {
|
|
338
|
+
role_id: BigInt(roleId),
|
|
339
|
+
permission_id: BigInt(permissionId),
|
|
340
|
+
created_at: new Date(),
|
|
341
|
+
},
|
|
342
|
+
update: {},
|
|
343
|
+
});
|
|
344
|
+
(0, response_1.sendFastSuccess)(res, 200, voidSerializer, {
|
|
345
|
+
status: "success",
|
|
346
|
+
message: "Permission assigned to role",
|
|
347
|
+
data: null,
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
async function removePermissionFromRole(req, res) {
|
|
351
|
+
const validator = validator_1.Validator.make(req.body || {}, {
|
|
352
|
+
roleId: zod_1.z.string().min(1, "roleId wajib diisi"),
|
|
353
|
+
permissionId: zod_1.z.string().min(1, "permissionId wajib diisi"),
|
|
354
|
+
});
|
|
355
|
+
if (await validator.fails()) {
|
|
356
|
+
(0, response_1.sendError)(res, 422, "Validation error", validator.errors());
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
const { roleId, permissionId } = await validator.validated();
|
|
360
|
+
await database_1.prisma.role_permissions.deleteMany({
|
|
361
|
+
where: {
|
|
362
|
+
role_id: BigInt(roleId),
|
|
363
|
+
permission_id: BigInt(permissionId),
|
|
364
|
+
},
|
|
365
|
+
});
|
|
366
|
+
(0, response_1.sendFastSuccess)(res, 200, voidSerializer, {
|
|
367
|
+
status: "success",
|
|
368
|
+
message: "Permission removed from role",
|
|
369
|
+
data: null,
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
async function assignPermissionToUser(req, res) {
|
|
373
|
+
const validator = validator_1.Validator.make(req.body || {}, {
|
|
374
|
+
userId: zod_1.z.string().min(1, "userId wajib diisi"),
|
|
375
|
+
permissionId: zod_1.z.string().min(1, "permissionId wajib diisi"),
|
|
376
|
+
});
|
|
377
|
+
if (await validator.fails()) {
|
|
378
|
+
(0, response_1.sendError)(res, 422, "Validation error", validator.errors());
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
const { userId, permissionId } = await validator.validated();
|
|
382
|
+
const user = await database_1.prisma.users.findUnique({
|
|
383
|
+
where: { id: BigInt(userId) },
|
|
384
|
+
});
|
|
385
|
+
if (!user) {
|
|
386
|
+
(0, response_1.sendError)(res, 404, "User not found");
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
const permission = await database_1.prisma.permissions.findUnique({
|
|
390
|
+
where: { id: BigInt(permissionId) },
|
|
391
|
+
});
|
|
392
|
+
if (!permission) {
|
|
393
|
+
(0, response_1.sendError)(res, 404, "Permission not found");
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
await database_1.prisma.user_permissions.upsert({
|
|
397
|
+
where: {
|
|
398
|
+
user_id_permission_id: {
|
|
399
|
+
user_id: BigInt(userId),
|
|
400
|
+
permission_id: BigInt(permissionId),
|
|
401
|
+
},
|
|
402
|
+
},
|
|
403
|
+
create: {
|
|
404
|
+
user_id: BigInt(userId),
|
|
405
|
+
permission_id: BigInt(permissionId),
|
|
406
|
+
created_at: new Date(),
|
|
407
|
+
},
|
|
408
|
+
update: {},
|
|
409
|
+
});
|
|
410
|
+
(0, response_1.sendFastSuccess)(res, 200, voidSerializer, {
|
|
411
|
+
status: "success",
|
|
412
|
+
message: "Permission assigned to user",
|
|
413
|
+
data: null,
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
async function removePermissionFromUser(req, res) {
|
|
417
|
+
const validator = validator_1.Validator.make(req.body || {}, {
|
|
418
|
+
userId: zod_1.z.string().min(1, "userId wajib diisi"),
|
|
419
|
+
permissionId: zod_1.z.string().min(1, "permissionId wajib diisi"),
|
|
420
|
+
});
|
|
421
|
+
if (await validator.fails()) {
|
|
422
|
+
(0, response_1.sendError)(res, 422, "Validation error", validator.errors());
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
const { userId, permissionId } = await validator.validated();
|
|
426
|
+
await database_1.prisma.user_permissions.deleteMany({
|
|
427
|
+
where: {
|
|
428
|
+
user_id: BigInt(userId),
|
|
429
|
+
permission_id: BigInt(permissionId),
|
|
430
|
+
},
|
|
431
|
+
});
|
|
432
|
+
(0, response_1.sendFastSuccess)(res, 200, voidSerializer, {
|
|
433
|
+
status: "success",
|
|
434
|
+
message: "Permission removed from user",
|
|
435
|
+
data: null,
|
|
436
|
+
});
|
|
437
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../../src/core/database.ts"],"names":[],"mappings":"AAOA,QAAA,IAAI,MAAM,EAAE,GAAG,CAAC;AAyBhB,OAAO,EAAE,MAAM,EAAE,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.prisma = void 0;
|
|
4
|
+
const { PrismaClient } = require("@prisma/client");
|
|
5
|
+
const adapter_pg_1 = require("@prisma/adapter-pg");
|
|
6
|
+
const adapter_mariadb_1 = require("@prisma/adapter-mariadb");
|
|
7
|
+
const url = process.env.DATABASE_URL || "";
|
|
8
|
+
const provider = (process.env.DATABASE_PROVIDER || "").toLowerCase();
|
|
9
|
+
let prisma;
|
|
10
|
+
if (provider === "postgresql" || url.startsWith("postgres")) {
|
|
11
|
+
const adapter = new adapter_pg_1.PrismaPg({ connectionString: url });
|
|
12
|
+
exports.prisma = prisma = new PrismaClient({ adapter });
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
if (provider === "mysql" || url.startsWith("mysql")) {
|
|
16
|
+
try {
|
|
17
|
+
const u = new URL(url);
|
|
18
|
+
const adapter = new adapter_mariadb_1.PrismaMariaDb({
|
|
19
|
+
host: u.hostname,
|
|
20
|
+
port: Number(u.port || "3306"),
|
|
21
|
+
user: decodeURIComponent(u.username),
|
|
22
|
+
password: decodeURIComponent(u.password),
|
|
23
|
+
database: u.pathname.replace("/", ""),
|
|
24
|
+
});
|
|
25
|
+
exports.prisma = prisma = new PrismaClient({ adapter });
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
exports.prisma = prisma = new PrismaClient({});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
exports.prisma = prisma = new PrismaClient({});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime.d.ts","sourceRoot":"","sources":["../../../src/core/realtime.ts"],"names":[],"mappings":"AAKA,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,MAAM,EAAE,MAAM,QAuBzD;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,QAGrE"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.initRealtime = initRealtime;
|
|
7
|
+
exports.notifyUser = notifyUser;
|
|
8
|
+
const socket_io_1 = require("socket.io");
|
|
9
|
+
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
10
|
+
let io = null;
|
|
11
|
+
function initRealtime(server) {
|
|
12
|
+
io = new socket_io_1.Server(server, {
|
|
13
|
+
cors: { origin: "*", methods: ["GET", "POST", "PUT", "DELETE"] },
|
|
14
|
+
});
|
|
15
|
+
io.on("connection", (socket) => {
|
|
16
|
+
const token = socket.handshake.query?.token ||
|
|
17
|
+
socket.handshake.headers["authorization"]
|
|
18
|
+
?.toString()
|
|
19
|
+
?.replace("Bearer ", "") ||
|
|
20
|
+
"";
|
|
21
|
+
const secret = process.env.JWT_SECRET;
|
|
22
|
+
if (secret && token) {
|
|
23
|
+
try {
|
|
24
|
+
const payload = jsonwebtoken_1.default.verify(token, secret);
|
|
25
|
+
const room = `user:${payload.userId}`;
|
|
26
|
+
socket.join(room);
|
|
27
|
+
}
|
|
28
|
+
catch { }
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function notifyUser(userId, event, payload) {
|
|
33
|
+
if (!io)
|
|
34
|
+
return;
|
|
35
|
+
io.to(`user:${userId}`).emit(event, payload);
|
|
36
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import Redis from "ioredis";
|
|
2
|
+
export declare function initRedis(): Promise<void>;
|
|
3
|
+
declare const redisProxy: Redis;
|
|
4
|
+
export declare function getCache(key: string): Promise<any>;
|
|
5
|
+
export declare function setCache(key: string, value: any, ttlSeconds?: number): Promise<void>;
|
|
6
|
+
export declare function delCache(key: string): Promise<void>;
|
|
7
|
+
export { redisProxy as redis };
|
|
8
|
+
//# sourceMappingURL=redis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../../src/core/redis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,SAAS,CAAC;AA4D5B,wBAAsB,SAAS,kBAoC9B;AAGD,QAAA,MAAM,UAAU,OAMd,CAAC;AAEH,wBAAsB,QAAQ,CAAC,GAAG,EAAE,MAAM,gBAOzC;AAED,wBAAsB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,UAAU,SAAK,iBAItE;AAED,wBAAsB,QAAQ,CAAC,GAAG,EAAE,MAAM,iBAIzC;AAGD,OAAO,EAAE,UAAU,IAAI,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.redis = void 0;
|
|
7
|
+
exports.initRedis = initRedis;
|
|
8
|
+
exports.getCache = getCache;
|
|
9
|
+
exports.setCache = setCache;
|
|
10
|
+
exports.delCache = delCache;
|
|
11
|
+
const ioredis_1 = __importDefault(require("ioredis"));
|
|
12
|
+
// @ts-ignore
|
|
13
|
+
const ioredis_mock_1 = __importDefault(require("ioredis-mock"));
|
|
14
|
+
const redisUrl = process.env.REDIS_URL || "redis://localhost:6379";
|
|
15
|
+
// Create a wrapper to handle connection attempts
|
|
16
|
+
let redis;
|
|
17
|
+
let isRedisConnected = false;
|
|
18
|
+
// If explicitly disabled via env
|
|
19
|
+
if (process.env.NO_REDIS === "true") {
|
|
20
|
+
console.log("Redis disabled via NO_REDIS, using in-memory mock.");
|
|
21
|
+
redis = new ioredis_mock_1.default();
|
|
22
|
+
isRedisConnected = true;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
// Try to connect to real Redis
|
|
26
|
+
redis = new ioredis_1.default(redisUrl, {
|
|
27
|
+
lazyConnect: true,
|
|
28
|
+
maxRetriesPerRequest: 1,
|
|
29
|
+
retryStrategy: (times) => {
|
|
30
|
+
// Retry 3 times then give up
|
|
31
|
+
if (times > 3)
|
|
32
|
+
return null;
|
|
33
|
+
return 200;
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
redis.on("ready", () => {
|
|
38
|
+
isRedisConnected = true;
|
|
39
|
+
// console.log("Redis connected!");
|
|
40
|
+
});
|
|
41
|
+
redis.on("error", (_err) => {
|
|
42
|
+
// If connection fails and we haven't switched to mock yet
|
|
43
|
+
if (!isRedisConnected && !(redis instanceof ioredis_mock_1.default)) {
|
|
44
|
+
// console.log("Redis connection failed, switching to in-memory mock...");
|
|
45
|
+
// Replace the global redis instance with mock
|
|
46
|
+
// Note: This is a runtime switch. Existing listeners might be lost if we don't handle carefully.
|
|
47
|
+
// However, for a simple fallback, we can just use the mock for future calls.
|
|
48
|
+
// Better approach: Since we exported 'redis' as a const (reference), we can't reassign it easily
|
|
49
|
+
// if other modules already imported it.
|
|
50
|
+
// BUT, ioredis instance itself is an EventEmitter.
|
|
51
|
+
// Strategy: We keep 'redis' as the main interface.
|
|
52
|
+
// If real redis fails, we just don't set isRedisConnected to true for the *real* one.
|
|
53
|
+
// But wait, the user wants 'bundle redis'.
|
|
54
|
+
// The best way is to detect failure during init and SWAP the implementation.
|
|
55
|
+
}
|
|
56
|
+
isRedisConnected = false;
|
|
57
|
+
});
|
|
58
|
+
// We need a way to seamlessly switch or just default to Mock if connect fails.
|
|
59
|
+
// Since 'redis' is exported immediately, we can't easily swap the object reference for importers.
|
|
60
|
+
// PROXY APPROACH:
|
|
61
|
+
// We export a Proxy that forwards to real redis OR mock redis.
|
|
62
|
+
const mockRedis = new ioredis_mock_1.default();
|
|
63
|
+
let activeRedis = redis; // Start with real redis attempt
|
|
64
|
+
// Custom init function to determine which one to use
|
|
65
|
+
async function initRedis() {
|
|
66
|
+
if (process.env.NO_REDIS === "true") {
|
|
67
|
+
activeRedis = mockRedis;
|
|
68
|
+
console.log("✅ Redis: Active (Source: Zero-Config Redis [NO_REDIS=true])");
|
|
69
|
+
if (process.env.NODE_ENV === "production") {
|
|
70
|
+
console.warn("⚠️ WARNING: Running in PRODUCTION with in-memory Redis mock. Data will be lost on restart and not shared between instances.");
|
|
71
|
+
}
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
await redis.connect();
|
|
76
|
+
activeRedis = redis; // Keep using real redis
|
|
77
|
+
isRedisConnected = true;
|
|
78
|
+
// Determine source label
|
|
79
|
+
const sourceLabel = process.env.REDIS_URL
|
|
80
|
+
? redisUrl
|
|
81
|
+
: "Zero-Config Redis (Localhost)";
|
|
82
|
+
console.log(`✅ Redis: Active (Source: ${sourceLabel})`);
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
// Connection failed, switch to mock
|
|
86
|
+
console.log(`⚠️ Redis: Connection failed to ${redisUrl}, switching to fallback (Source: Zero-Config Redis [Mock])`);
|
|
87
|
+
activeRedis = mockRedis;
|
|
88
|
+
isRedisConnected = true; // Mock is always "connected"
|
|
89
|
+
if (process.env.NODE_ENV === "production") {
|
|
90
|
+
console.warn("⚠️ WARNING: Redis connection failed in PRODUCTION. Switched to in-memory mock. Data will be lost on restart.");
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Proxy handler to forward all calls to activeRedis
|
|
95
|
+
const redisProxy = new Proxy({}, {
|
|
96
|
+
get: (_target, prop) => {
|
|
97
|
+
// If accessing a property on the proxy, forward it to activeRedis
|
|
98
|
+
const value = activeRedis[prop];
|
|
99
|
+
return value;
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
exports.redis = redisProxy;
|
|
103
|
+
async function getCache(key) {
|
|
104
|
+
try {
|
|
105
|
+
const v = await activeRedis.get(key);
|
|
106
|
+
return v ? JSON.parse(v) : null;
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async function setCache(key, value, ttlSeconds = 60) {
|
|
113
|
+
try {
|
|
114
|
+
await activeRedis.set(key, JSON.stringify(value), "EX", ttlSeconds);
|
|
115
|
+
}
|
|
116
|
+
catch { }
|
|
117
|
+
}
|
|
118
|
+
async function delCache(key) {
|
|
119
|
+
try {
|
|
120
|
+
await activeRedis.del(key);
|
|
121
|
+
}
|
|
122
|
+
catch { }
|
|
123
|
+
}
|