@eratu/common 1.0.15 → 1.0.16

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 (29) hide show
  1. package/build/errors/forbidden-error.d.ts +9 -0
  2. package/build/errors/forbidden-error.js +16 -0
  3. package/build/errors/not-authorized-error.d.ts +2 -2
  4. package/build/errors/not-authorized-error.js +3 -3
  5. package/build/errors/not-found-error.d.ts +3 -2
  6. package/build/errors/not-found-error.js +4 -3
  7. package/build/events/event-types/auth/author-deleted-event.d.ts +2 -1
  8. package/build/events/event-types/auth/author-signed-in-event.d.ts +2 -2
  9. package/build/events/event-types/auth/author-updated-event.d.ts +3 -1
  10. package/build/events/event-types/auth/{author-created-event.d.ts → author-verified-event.d.ts} +5 -3
  11. package/build/events/event-types/auth/reader-deleted-event.d.ts +2 -1
  12. package/build/events/event-types/auth/reader-signed-in-event.d.ts +2 -1
  13. package/build/events/event-types/auth/reader-updated-event.d.ts +3 -1
  14. package/build/events/event-types/auth/{reader-created-event.d.ts → reader-verified-event.d.ts} +5 -3
  15. package/build/events/subjects.d.ts +2 -2
  16. package/build/events/subjects.js +2 -2
  17. package/build/index.d.ts +11 -8
  18. package/build/index.js +15 -8
  19. package/build/middlewares/allow-roles.d.ts +3 -0
  20. package/build/middlewares/allow-roles.js +18 -0
  21. package/build/middlewares/current-user.d.ts +11 -0
  22. package/build/middlewares/current-user.js +59 -1
  23. package/build/middlewares/validation.d.ts +1 -1
  24. package/build/middlewares/validation.js +3 -3
  25. package/build/redis-wrapper.d.ts +20 -0
  26. package/build/redis-wrapper.js +77 -0
  27. package/package.json +4 -2
  28. /package/build/events/event-types/auth/{author-created-event.js → author-verified-event.js} +0 -0
  29. /package/build/events/event-types/auth/{reader-created-event.js → reader-verified-event.js} +0 -0
@@ -0,0 +1,9 @@
1
+ import { CustomError } from "./custom-error";
2
+ export declare class ForbiddenError extends CustomError {
3
+ message: string;
4
+ statusCode: number;
5
+ constructor(message?: string);
6
+ serializeErrors(): {
7
+ message: string;
8
+ }[];
9
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ForbiddenError = void 0;
4
+ const custom_error_1 = require("./custom-error");
5
+ class ForbiddenError extends custom_error_1.CustomError {
6
+ constructor(message = "Forbidden") {
7
+ super(message);
8
+ this.message = message;
9
+ this.statusCode = 403;
10
+ Object.setPrototypeOf(this, ForbiddenError.prototype);
11
+ }
12
+ serializeErrors() {
13
+ return [{ message: this.message }];
14
+ }
15
+ }
16
+ exports.ForbiddenError = ForbiddenError;
@@ -1,7 +1,7 @@
1
- import { CustomError } from './custom-error';
1
+ import { CustomError } from "./custom-error";
2
2
  export declare class NotAuthorizedError extends CustomError {
3
3
  statusCode: number;
4
- constructor();
4
+ constructor(message?: string);
5
5
  serializeErrors(): {
6
6
  message: string;
7
7
  }[];
@@ -3,13 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NotAuthorizedError = void 0;
4
4
  const custom_error_1 = require("./custom-error");
5
5
  class NotAuthorizedError extends custom_error_1.CustomError {
6
- constructor() {
7
- super('Not Authorized');
6
+ constructor(message = "Not Authorized") {
7
+ super(message);
8
8
  this.statusCode = 401;
9
9
  Object.setPrototypeOf(this, NotAuthorizedError.prototype);
10
10
  }
11
11
  serializeErrors() {
12
- return [{ message: 'Not authorized' }];
12
+ return [{ message: this.message }];
13
13
  }
14
14
  }
15
15
  exports.NotAuthorizedError = NotAuthorizedError;
@@ -1,7 +1,8 @@
1
- import { CustomError } from './custom-error';
1
+ import { CustomError } from "./custom-error";
2
2
  export declare class NotFoundError extends CustomError {
3
+ message: string;
3
4
  statusCode: number;
4
- constructor();
5
+ constructor(message?: string);
5
6
  serializeErrors(): {
6
7
  message: string;
7
8
  }[];
@@ -3,13 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NotFoundError = void 0;
4
4
  const custom_error_1 = require("./custom-error");
5
5
  class NotFoundError extends custom_error_1.CustomError {
6
- constructor() {
7
- super('Route not found');
6
+ constructor(message = "Not Found") {
7
+ super("Route not found");
8
+ this.message = message;
8
9
  this.statusCode = 404;
9
10
  Object.setPrototypeOf(this, NotFoundError.prototype);
10
11
  }
11
12
  serializeErrors() {
12
- return [{ message: 'Not Found' }];
13
+ return [{ message: this.message }];
13
14
  }
14
15
  }
15
16
  exports.NotFoundError = NotFoundError;
@@ -2,9 +2,10 @@ import { Streams } from "../../streams";
2
2
  import { Subjects } from "../../subjects";
3
3
  export interface AuthorDeletedEvent {
4
4
  subject: Subjects.AuthorDeleted;
5
- stream: Streams.AuthorServiceStream;
5
+ stream: Streams.AuthServiceStream;
6
6
  data: {
7
7
  id: string;
8
8
  version: number;
9
+ authorVersion: number;
9
10
  };
10
11
  }
@@ -6,7 +6,7 @@ export interface AuthorSignedInEvent {
6
6
  data: {
7
7
  userId: string;
8
8
  email: string;
9
- sessionId: string;
10
- signedInAt: string;
9
+ version: number;
10
+ authorVersion: number;
11
11
  };
12
12
  }
@@ -2,11 +2,13 @@ import { Streams } from "../../streams";
2
2
  import { Subjects } from "../../subjects";
3
3
  export interface AuthorUpdatedEvent {
4
4
  subject: Subjects.AuthorUpdated;
5
- stream: Streams.AuthorServiceStream;
5
+ stream: Streams.AuthServiceStream;
6
6
  data: {
7
7
  id: string;
8
8
  firstName: string;
9
9
  lastName: string;
10
10
  email: string;
11
+ version: number;
12
+ authorVersion: number;
11
13
  };
12
14
  }
@@ -1,12 +1,14 @@
1
1
  import { Streams } from "../../streams";
2
2
  import { Subjects } from "../../subjects";
3
- export interface AuthorCreatedEvent {
4
- subject: Subjects.AuthorCreated;
5
- stream: Streams.AuthorServiceStream;
3
+ export interface AuthorVerifiedEvent {
4
+ subject: Subjects.AuthorVerified;
5
+ stream: Streams.AuthServiceStream;
6
6
  data: {
7
7
  id: string;
8
8
  firstName: string;
9
9
  lastName: string;
10
10
  email: string;
11
+ version: number;
12
+ authorVersion: number;
11
13
  };
12
14
  }
@@ -2,9 +2,10 @@ import { Streams } from "../../streams";
2
2
  import { Subjects } from "../../subjects";
3
3
  export interface ReaderDeletedEvent {
4
4
  subject: Subjects.ReaderDeleted;
5
- stream: Streams.ReaderServiceStream;
5
+ stream: Streams.AuthServiceStream;
6
6
  data: {
7
7
  id: string;
8
8
  version: number;
9
+ readerVersion: number;
9
10
  };
10
11
  }
@@ -6,7 +6,8 @@ export interface ReaderSignedInEvent {
6
6
  data: {
7
7
  userId: string;
8
8
  email: string;
9
- sessionId: string;
10
9
  signedInAt: string;
10
+ version: number;
11
+ readerVersion: number;
11
12
  };
12
13
  }
@@ -2,11 +2,13 @@ import { Streams } from "../../streams";
2
2
  import { Subjects } from "../../subjects";
3
3
  export interface ReaderUpdatedEvent {
4
4
  subject: Subjects.ReaderUpdated;
5
- stream: Streams.ReaderServiceStream;
5
+ stream: Streams.AuthServiceStream;
6
6
  data: {
7
7
  id: string;
8
8
  firstName: string;
9
9
  lastName: string;
10
10
  email: string;
11
+ version: number;
12
+ readerVersion: number;
11
13
  };
12
14
  }
@@ -1,12 +1,14 @@
1
1
  import { Streams } from "../../streams";
2
2
  import { Subjects } from "../../subjects";
3
- export interface ReaderCreatedEvent {
4
- subject: Subjects.ReaderCreated;
5
- stream: Streams.ReaderServiceStream;
3
+ export interface ReaderVerifiedEvent {
4
+ subject: Subjects.ReaderVerified;
5
+ stream: Streams.AuthServiceStream;
6
6
  data: {
7
7
  id: string;
8
8
  firstName: string;
9
9
  lastName: string;
10
10
  email: string;
11
+ version: number;
12
+ readerVersion: number;
11
13
  };
12
14
  }
@@ -1,16 +1,16 @@
1
1
  export declare enum Subjects {
2
- AuthorCreated = "author:created",
3
2
  AuthorUpdated = "author:updated",
4
3
  AuthorDeleted = "author:deleted",
5
4
  AuthorSignedUp = "author:signed-up",
6
5
  AuthorSignedIn = "author:signed-in",
7
6
  AuthorSignedOut = "author:signed-out",
7
+ AuthorVerified = "author:verified",
8
8
  ReaderSignedUp = "reader:signed-up",
9
9
  ReaderSignedIn = "reader:signed-in",
10
10
  ReaderSignedOut = "reader:signed-out",
11
- ReaderCreated = "reader:created",
12
11
  ReaderUpdated = "reader:updated",
13
12
  ReaderDeleted = "reader:deleted",
13
+ ReaderVerified = "reader:verified",
14
14
  BookCreated = "book:created",
15
15
  BookUpdated = "book:updated",
16
16
  BookDeleted = "book:deleted",
@@ -4,19 +4,19 @@ exports.Subjects = void 0;
4
4
  var Subjects;
5
5
  (function (Subjects) {
6
6
  // Authors related event subjects
7
- Subjects["AuthorCreated"] = "author:created";
8
7
  Subjects["AuthorUpdated"] = "author:updated";
9
8
  Subjects["AuthorDeleted"] = "author:deleted";
10
9
  Subjects["AuthorSignedUp"] = "author:signed-up";
11
10
  Subjects["AuthorSignedIn"] = "author:signed-in";
12
11
  Subjects["AuthorSignedOut"] = "author:signed-out";
12
+ Subjects["AuthorVerified"] = "author:verified";
13
13
  // Readers related event subjects
14
14
  Subjects["ReaderSignedUp"] = "reader:signed-up";
15
15
  Subjects["ReaderSignedIn"] = "reader:signed-in";
16
16
  Subjects["ReaderSignedOut"] = "reader:signed-out";
17
- Subjects["ReaderCreated"] = "reader:created";
18
17
  Subjects["ReaderUpdated"] = "reader:updated";
19
18
  Subjects["ReaderDeleted"] = "reader:deleted";
19
+ Subjects["ReaderVerified"] = "reader:verified";
20
20
  // Books related event subjects
21
21
  Subjects["BookCreated"] = "book:created";
22
22
  Subjects["BookUpdated"] = "book:updated";
package/build/index.d.ts CHANGED
@@ -4,29 +4,32 @@ export * from "./errors/database-connection-error";
4
4
  export * from "./errors/not-authorized-error";
5
5
  export * from "./errors/not-found-error";
6
6
  export * from "./errors/request-validation-error";
7
+ export * from "./errors/forbidden-error";
7
8
  export * from "./middlewares/current-user";
8
- export * from "./middlewares/error-handler";
9
9
  export * from "./middlewares/require-auth";
10
10
  export * from "./middlewares/validation";
11
+ export * from "./middlewares/error-handler";
12
+ export * from "./middlewares/allow-roles";
11
13
  export * from "./enum/roles";
12
14
  export * from "./events/listeners/base-listener";
13
15
  export * from "./events/publishers/base-publisher";
14
16
  export * from "./events/event-types/books/book-created-event";
15
17
  export * from "./events/event-types/books/book-updated-event";
16
18
  export * from "./events/event-types/books/book-deleted-event";
17
- export * from "./events/event-types/auth/reader-created-event";
18
- export * from "./events/event-types/auth/reader-updated-event";
19
- export * from "./events/event-types/auth/reader-deleted-event";
20
- export * from "./events/event-types/auth/author-created-event";
21
19
  export * from "./events/event-types/auth/author-updated-event";
22
20
  export * from "./events/event-types/auth/author-deleted-event";
23
- export * from "./events/event-types/auth/reader-signed-up-event";
24
- export * from "./events/event-types/auth/reader-signed-in-event";
25
- export * from "./events/event-types/auth/reader-signed-out-event";
21
+ export * from "./events/event-types/auth/author-verified-event";
26
22
  export * from "./events/event-types/auth/author-signed-up-event";
27
23
  export * from "./events/event-types/auth/author-signed-in-event";
28
24
  export * from "./events/event-types/auth/author-signed-out-event";
25
+ export * from "./events/event-types/auth/reader-updated-event";
26
+ export * from "./events/event-types/auth/reader-deleted-event";
27
+ export * from "./events/event-types/auth/reader-signed-up-event";
28
+ export * from "./events/event-types/auth/reader-signed-in-event";
29
+ export * from "./events/event-types/auth/reader-signed-out-event";
30
+ export * from "./events/event-types/auth/reader-verified-event";
29
31
  export * from "./events/event-types/orders/order-created-event";
30
32
  export * from "./events/subjects";
31
33
  export * from "./events/streams";
32
34
  export * from "./nats-wrapper";
35
+ export * from "./redis-wrapper";
package/build/index.js CHANGED
@@ -14,16 +14,20 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ // Errors
17
18
  __exportStar(require("./errors/bad-request-error"), exports);
18
19
  __exportStar(require("./errors/custom-error"), exports);
19
20
  __exportStar(require("./errors/database-connection-error"), exports);
20
21
  __exportStar(require("./errors/not-authorized-error"), exports);
21
22
  __exportStar(require("./errors/not-found-error"), exports);
22
23
  __exportStar(require("./errors/request-validation-error"), exports);
24
+ __exportStar(require("./errors/forbidden-error"), exports);
25
+ // Middlewares
23
26
  __exportStar(require("./middlewares/current-user"), exports);
24
- __exportStar(require("./middlewares/error-handler"), exports);
25
27
  __exportStar(require("./middlewares/require-auth"), exports);
26
28
  __exportStar(require("./middlewares/validation"), exports);
29
+ __exportStar(require("./middlewares/error-handler"), exports);
30
+ __exportStar(require("./middlewares/allow-roles"), exports);
27
31
  // Enums
28
32
  __exportStar(require("./enum/roles"), exports);
29
33
  __exportStar(require("./events/listeners/base-listener"), exports);
@@ -31,19 +35,22 @@ __exportStar(require("./events/publishers/base-publisher"), exports);
31
35
  __exportStar(require("./events/event-types/books/book-created-event"), exports);
32
36
  __exportStar(require("./events/event-types/books/book-updated-event"), exports);
33
37
  __exportStar(require("./events/event-types/books/book-deleted-event"), exports);
34
- __exportStar(require("./events/event-types/auth/reader-created-event"), exports);
35
- __exportStar(require("./events/event-types/auth/reader-updated-event"), exports);
36
- __exportStar(require("./events/event-types/auth/reader-deleted-event"), exports);
37
- __exportStar(require("./events/event-types/auth/author-created-event"), exports);
38
+ // Author events
38
39
  __exportStar(require("./events/event-types/auth/author-updated-event"), exports);
39
40
  __exportStar(require("./events/event-types/auth/author-deleted-event"), exports);
40
- __exportStar(require("./events/event-types/auth/reader-signed-up-event"), exports);
41
- __exportStar(require("./events/event-types/auth/reader-signed-in-event"), exports);
42
- __exportStar(require("./events/event-types/auth/reader-signed-out-event"), exports);
41
+ __exportStar(require("./events/event-types/auth/author-verified-event"), exports);
43
42
  __exportStar(require("./events/event-types/auth/author-signed-up-event"), exports);
44
43
  __exportStar(require("./events/event-types/auth/author-signed-in-event"), exports);
45
44
  __exportStar(require("./events/event-types/auth/author-signed-out-event"), exports);
45
+ // Reader events
46
+ __exportStar(require("./events/event-types/auth/reader-updated-event"), exports);
47
+ __exportStar(require("./events/event-types/auth/reader-deleted-event"), exports);
48
+ __exportStar(require("./events/event-types/auth/reader-signed-up-event"), exports);
49
+ __exportStar(require("./events/event-types/auth/reader-signed-in-event"), exports);
50
+ __exportStar(require("./events/event-types/auth/reader-signed-out-event"), exports);
51
+ __exportStar(require("./events/event-types/auth/reader-verified-event"), exports);
46
52
  __exportStar(require("./events/event-types/orders/order-created-event"), exports);
47
53
  __exportStar(require("./events/subjects"), exports);
48
54
  __exportStar(require("./events/streams"), exports);
49
55
  __exportStar(require("./nats-wrapper"), exports);
56
+ __exportStar(require("./redis-wrapper"), exports);
@@ -0,0 +1,3 @@
1
+ import { UserRoles } from "../enum/roles";
2
+ import { Request, Response, NextFunction } from "express";
3
+ export declare const allowRoles: (roles: UserRoles[]) => (req: Request, res: Response, next: NextFunction) => void;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.allowRoles = void 0;
4
+ const not_authorized_error_1 = require("../errors/not-authorized-error");
5
+ const forbidden_error_1 = require("../errors/forbidden-error");
6
+ const allowRoles = (roles) => {
7
+ return (req, res, next) => {
8
+ const currentUser = req.currentUser;
9
+ if (!currentUser) {
10
+ throw new not_authorized_error_1.NotAuthorizedError();
11
+ }
12
+ if (!roles.includes(currentUser.role)) {
13
+ throw new forbidden_error_1.ForbiddenError();
14
+ }
15
+ return next();
16
+ };
17
+ };
18
+ exports.allowRoles = allowRoles;
@@ -1,5 +1,7 @@
1
1
  import { Request, Response, NextFunction } from "express";
2
2
  import { UserRoles } from "../enum/roles";
3
+ import { RedisWrapper } from "../redis-wrapper";
4
+ import NodeCache from "node-cache";
3
5
  export interface UserJwtPayload {
4
6
  id: string;
5
7
  email: string;
@@ -26,4 +28,13 @@ declare global {
26
28
  }
27
29
  }
28
30
  }
31
+ export declare class CurrentUserMiddleware {
32
+ private readonly redisClient;
33
+ private readonly localCache;
34
+ constructor(params?: {
35
+ redisClient?: RedisWrapper;
36
+ localCache?: NodeCache;
37
+ });
38
+ getMiddleware(): (req: Request, res: Response, next: NextFunction) => Promise<void>;
39
+ }
29
40
  export declare const currentUser: (req: Request, res: Response, next: NextFunction) => void;
@@ -1,10 +1,68 @@
1
1
  "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
2
11
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
13
  };
5
14
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.currentUser = void 0;
15
+ exports.currentUser = exports.CurrentUserMiddleware = void 0;
7
16
  const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
17
+ class CurrentUserMiddleware {
18
+ constructor(params) {
19
+ this.localCache = (params === null || params === void 0 ? void 0 : params.localCache) || null;
20
+ this.redisClient = (params === null || params === void 0 ? void 0 : params.redisClient) || null;
21
+ }
22
+ getMiddleware() {
23
+ return (req, res, next) => __awaiter(this, void 0, void 0, function* () {
24
+ var _a, _b, _c, _d;
25
+ try {
26
+ const token = (_a = req.headers["authorization"]) === null || _a === void 0 ? void 0 : _a.split(" ")[1];
27
+ if (!token) {
28
+ return next();
29
+ }
30
+ const payload = jsonwebtoken_1.default.verify(token, process.env.JWT_KEY);
31
+ const userData = {
32
+ id: payload.sub,
33
+ email: payload.email,
34
+ firstName: payload.firstName,
35
+ lastName: payload.lastName,
36
+ role: payload.role,
37
+ };
38
+ // If JWT has jti claim — it’s important for revocation
39
+ const jti = payload.jti;
40
+ if (!jti) {
41
+ return next();
42
+ }
43
+ // Check local cache first (fast)
44
+ if ((_b = this.localCache) === null || _b === void 0 ? void 0 : _b.get(jti)) {
45
+ return next();
46
+ }
47
+ // Then check Redis
48
+ const redisResult = yield ((_c = this.redisClient) === null || _c === void 0 ? void 0 : _c.get(`revoked:${jti}`));
49
+ if (redisResult) {
50
+ // store in local cache to reduce redis lookups
51
+ (_d = this.localCache) === null || _d === void 0 ? void 0 : _d.set(jti, true, 60 * 5); // cache for 5 min
52
+ return next();
53
+ }
54
+ // All good — attach user
55
+ req.currentUser = userData;
56
+ next();
57
+ }
58
+ catch (err) {
59
+ console.error("Auth error:", err);
60
+ return next();
61
+ }
62
+ });
63
+ }
64
+ }
65
+ exports.CurrentUserMiddleware = CurrentUserMiddleware;
8
66
  const currentUser = (req, res, next) => {
9
67
  var _a;
10
68
  const token = (_a = req.headers["authorization"]) === null || _a === void 0 ? void 0 : _a.split(" ")[1];
@@ -1,3 +1,3 @@
1
1
  import { Request, Response, NextFunction } from 'express';
2
2
  import { ClassConstructor } from 'class-transformer';
3
- export declare function validationMiddleware<T extends object>(type: ClassConstructor<T>, skipMissingProperties?: boolean): (req: Request, res: Response, next: NextFunction) => Promise<Response<any, Record<string, any>> | undefined>;
3
+ export declare function validationMiddleware<T extends object>(type: ClassConstructor<T>, field?: 'body' | 'query' | 'params', skipMissingProperties?: boolean): (req: Request, res: Response, next: NextFunction) => Promise<Response<any, Record<string, any>> | undefined>;
@@ -12,11 +12,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.validationMiddleware = validationMiddleware;
13
13
  const class_transformer_1 = require("class-transformer");
14
14
  const class_validator_1 = require("class-validator");
15
- function validationMiddleware(type, skipMissingProperties = false) {
15
+ function validationMiddleware(type, field = 'body', skipMissingProperties = false) {
16
16
  return (req, res, next) => __awaiter(this, void 0, void 0, function* () {
17
17
  try {
18
18
  // Transform plain object to class instance
19
- const dto = (0, class_transformer_1.plainToClass)(type, req.body);
19
+ const dto = (0, class_transformer_1.plainToClass)(type, req[field]);
20
20
  // Validate the DTO
21
21
  const errors = yield (0, class_validator_1.validate)(dto, {
22
22
  skipMissingProperties,
@@ -43,7 +43,7 @@ function validationMiddleware(type, skipMissingProperties = false) {
43
43
  });
44
44
  }
45
45
  // Attach the validated and transformed DTO to the request
46
- req.body = dto;
46
+ req.body = (0, class_transformer_1.instanceToPlain)(dto, { exposeUnsetFields: false });
47
47
  next();
48
48
  }
49
49
  catch (error) {
@@ -0,0 +1,20 @@
1
+ import { Redis } from "ioredis";
2
+ declare class RedisWrapper {
3
+ private _client;
4
+ private host;
5
+ private port;
6
+ private username;
7
+ private password;
8
+ constructor(params?: {
9
+ host?: string;
10
+ port?: number;
11
+ username?: string;
12
+ password?: string;
13
+ });
14
+ connect(): Promise<void>;
15
+ disconnect(): Promise<void>;
16
+ set(key: string, value: string, expireInSeconds: number): Promise<void>;
17
+ get(key: string): Promise<string | null>;
18
+ get client(): Redis;
19
+ }
20
+ export { RedisWrapper };
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.RedisWrapper = void 0;
13
+ const ioredis_1 = require("ioredis");
14
+ class RedisWrapper {
15
+ constructor(params) {
16
+ this._client = null;
17
+ this.host = (params === null || params === void 0 ? void 0 : params.host) || "localhost";
18
+ this.port = (params === null || params === void 0 ? void 0 : params.port) || 6379;
19
+ this.username = (params === null || params === void 0 ? void 0 : params.username) || "";
20
+ this.password = (params === null || params === void 0 ? void 0 : params.password) || "";
21
+ }
22
+ connect() {
23
+ return __awaiter(this, void 0, void 0, function* () {
24
+ try {
25
+ this._client = new ioredis_1.Redis({
26
+ host: this.host,
27
+ port: this.port,
28
+ username: this.username,
29
+ password: this.password,
30
+ lazyConnect: true,
31
+ });
32
+ yield this._client.connect();
33
+ console.log("✅ Connected to Redis");
34
+ return;
35
+ }
36
+ catch (e) {
37
+ console.error("❌ Error connecting to Redis:", e.message);
38
+ }
39
+ console.log("❌ Failed to connect to Redis");
40
+ });
41
+ }
42
+ disconnect() {
43
+ return __awaiter(this, void 0, void 0, function* () {
44
+ try {
45
+ if (this._client) {
46
+ yield this._client.quit();
47
+ }
48
+ }
49
+ catch (e) {
50
+ console.error("❌ Error disconnecting from Redis:", e.message);
51
+ }
52
+ });
53
+ }
54
+ set(key, value, expireInSeconds) {
55
+ return __awaiter(this, void 0, void 0, function* () {
56
+ if (!this._client) {
57
+ throw new Error("Redis not connected");
58
+ }
59
+ yield this._client.set(key, value, "EX", expireInSeconds);
60
+ });
61
+ }
62
+ get(key) {
63
+ return __awaiter(this, void 0, void 0, function* () {
64
+ if (!this._client) {
65
+ throw new Error("Redis not connected");
66
+ }
67
+ return yield this._client.get(key);
68
+ });
69
+ }
70
+ get client() {
71
+ if (!this._client) {
72
+ throw new Error("Cannot access Redis client before connecting");
73
+ }
74
+ return this._client;
75
+ }
76
+ }
77
+ exports.RedisWrapper = RedisWrapper;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eratu/common",
3
- "version": "1.0.15",
3
+ "version": "1.0.16",
4
4
  "description": "A package for shared code across microservices",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",
@@ -28,7 +28,9 @@
28
28
  "cookie-session": "^2.1.0",
29
29
  "express": "^4.21.2",
30
30
  "express-validator": "^7.2.1",
31
+ "ioredis": "^5.8.2",
31
32
  "jsonwebtoken": "^9.0.2",
32
- "nats": "^2.29.3"
33
+ "nats": "^2.29.3",
34
+ "node-cache": "^5.1.2"
33
35
  }
34
36
  }