@vortenixinnovations/flagra-common-module 1.0.54 → 1.0.58

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.
@@ -1,4 +1 @@
1
- export * from "./logger/index.js";
2
- export * from "./error/index.js";
3
1
  export * from "./global/index.js";
4
- export * from "./validator.js";
@@ -1,4 +1 @@
1
- export * from "./logger/index.js";
2
- export * from "./error/index.js";
3
1
  export * from "./global/index.js";
4
- export * from "./validator.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vortenixinnovations/flagra-common-module",
3
- "version": "1.0.54",
3
+ "version": "1.0.58",
4
4
  "description": "common module of flagra",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",
@@ -22,7 +22,7 @@
22
22
  "scripts": {
23
23
  "clean": "del-cli ./build/*",
24
24
  "build": "npm run clean && tsc",
25
- "publish": "npm version patch && npm run build && npm publish"
25
+ "release": "npm version patch && npm run build && npm publish"
26
26
  },
27
27
  "dependencies": {
28
28
  "@sinclair/typebox": "^0.34.41",
@@ -33,7 +33,8 @@
33
33
  "dotenv": "^17.2.3",
34
34
  "express": "^5.1.0",
35
35
  "pino": "^10.0.0",
36
- "pino-http": "^11.0.0"
36
+ "pino-http": "^11.0.0",
37
+ "pino-pretty": "^13.0.0"
37
38
  },
38
39
  "devDependencies": {
39
40
  "@types/express": "^5.0.3",
@@ -1,19 +0,0 @@
1
- declare class BaseError extends Error {
2
- readonly name: string;
3
- readonly status: number;
4
- readonly message: string;
5
- constructor(name: string, status: number, description: string);
6
- }
7
- export declare class APIError extends BaseError {
8
- constructor(description?: string);
9
- }
10
- export declare class ValidationError extends BaseError {
11
- constructor(description?: string);
12
- }
13
- export declare class AuthorizeError extends BaseError {
14
- constructor(description?: string);
15
- }
16
- export declare class NotFoundError extends BaseError {
17
- constructor(description?: string);
18
- }
19
- export {};
@@ -1,38 +0,0 @@
1
- import { STATUS_CODES } from "./status-codes.js";
2
- class BaseError extends Error {
3
- name;
4
- status;
5
- message;
6
- constructor(name, status, description) {
7
- super(description);
8
- this.name = name;
9
- this.status = status;
10
- this.message = description;
11
- Object.setPrototypeOf(this, new.target.prototype);
12
- Error.captureStackTrace(this);
13
- }
14
- }
15
- // 500 Internal Error
16
- export class APIError extends BaseError {
17
- constructor(description = "api error") {
18
- super("api internal server error", STATUS_CODES.INTERNAL_ERROR, description);
19
- }
20
- }
21
- // 400 Validation Error
22
- export class ValidationError extends BaseError {
23
- constructor(description = "bad request") {
24
- super("bad request", STATUS_CODES.BAD_REQUEST, description);
25
- }
26
- }
27
- // 403 Authorize error
28
- export class AuthorizeError extends BaseError {
29
- constructor(description = "access denied") {
30
- super("access denied", STATUS_CODES.UN_AUTHORISED, description);
31
- }
32
- }
33
- // 404 Not Found
34
- export class NotFoundError extends BaseError {
35
- constructor(description = "not found") {
36
- super(description, STATUS_CODES.NOT_FOUND, description);
37
- }
38
- }
@@ -1,3 +0,0 @@
1
- import type { Request, Response, NextFunction } from "express";
2
- export declare const HandleErrorWithLogger: (error: any, req: Request, res: Response, next: NextFunction) => void;
3
- export declare const HandleUnCaughtException: (error: Error) => Promise<never>;
@@ -1,33 +0,0 @@
1
- import { AuthorizeError, NotFoundError, ValidationError } from "./errors.js";
2
- import { logger } from "../logger/index.js";
3
- export const HandleErrorWithLogger = (error, req, res, next) => {
4
- let reportError = true;
5
- let status = 500;
6
- let data = error.message;
7
- // convert express-jwt UnauthorizedError to your AuthorizeError
8
- if (error.name === "UnauthorizedError") {
9
- error = new AuthorizeError(error.message);
10
- }
11
- // skip known errors
12
- [NotFoundError, ValidationError, AuthorizeError].forEach((typeOfError) => {
13
- if (error instanceof typeOfError) {
14
- reportError = false;
15
- status = error.status || 400;
16
- data = error.message;
17
- }
18
- });
19
- if (reportError) {
20
- logger.error(error);
21
- }
22
- else {
23
- // future use third party error reporting tools
24
- logger.warn(error);
25
- }
26
- res.status(status).json({ error: data });
27
- };
28
- export const HandleUnCaughtException = async (error) => {
29
- // error report / monitoring tools
30
- logger.error(error);
31
- // recover
32
- process.exit(1);
33
- };
@@ -1,3 +0,0 @@
1
- export * from "./errors.js";
2
- export * from "./status-codes.js";
3
- export * from "./handler.js";
@@ -1,3 +0,0 @@
1
- export * from "./errors.js";
2
- export * from "./status-codes.js";
3
- export * from "./handler.js";
@@ -1,7 +0,0 @@
1
- export declare const STATUS_CODES: {
2
- OK: number;
3
- BAD_REQUEST: number;
4
- UN_AUTHORISED: number;
5
- NOT_FOUND: number;
6
- INTERNAL_ERROR: number;
7
- };
@@ -1,7 +0,0 @@
1
- export const STATUS_CODES = {
2
- OK: 200,
3
- BAD_REQUEST: 400,
4
- UN_AUTHORISED: 403,
5
- NOT_FOUND: 404,
6
- INTERNAL_ERROR: 500,
7
- };
@@ -1 +0,0 @@
1
- export declare const ValidateError: (input: any) => Promise<Record<string, any> | false>;
@@ -1,14 +0,0 @@
1
- import { validate } from "class-validator";
2
- export const ValidateError = async (input) => {
3
- const error = await validate(input, {
4
- ValidationError: { target: true, property: true },
5
- });
6
- if (error.length) {
7
- return error.map((err) => ({
8
- field: err.property,
9
- message: (err.constraints && Object.values(err.constraints)[0]) ||
10
- "please provide input for this field",
11
- }));
12
- }
13
- return false;
14
- };
@@ -1,3 +0,0 @@
1
- import pino from "pino";
2
- export declare const logger: pino.Logger<never, boolean>;
3
- export declare const httpLogger: import("pino-http").HttpLogger<import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, never>;
@@ -1,39 +0,0 @@
1
- import pino from "pino";
2
- import { pinoHttp } from "pino-http";
3
- import fs from "fs";
4
- import path from "path";
5
- import { fileURLToPath } from 'url';
6
- import dotenv from "dotenv";
7
- dotenv.config();
8
- const isProd = process.env.APP_ENV == "production";
9
- const __filename = fileURLToPath(import.meta.url);
10
- const __dirname = path.dirname(__filename);
11
- // Ensure logs directory exists
12
- const logDir = path.resolve(__dirname, "../logs");
13
- if (isProd && !fs.existsSync(logDir)) {
14
- fs.mkdirSync(logDir, { recursive: true });
15
- }
16
- const destination = isProd
17
- ? pino.destination({ dest: path.join(logDir, "app.log"), sync: false }) // non-blocking file write
18
- : undefined;
19
- export const logger = pino({
20
- level: "info",
21
- timestamp: () => `,"time":"${new Date().toISOString()}"`,
22
- ...(isProd
23
- ? {} // No transport for production — raw JSON
24
- : {
25
- transport: {
26
- target: "pino-pretty",
27
- options: {
28
- colorize: true,
29
- translateTime: "SYS:standard",
30
- ignore: "pid,hostname",
31
- },
32
- },
33
- }),
34
- }, destination // Only used in production
35
- );
36
- // HTTP request logger for Express
37
- export const httpLogger = pinoHttp({
38
- logger,
39
- });
@@ -1,9 +0,0 @@
1
- import type { Static, TSchema } from "@sinclair/typebox";
2
- export declare function sanitizeStrings<T>(input: T): T;
3
- export declare function ValidateRequest<T extends TSchema>(data: unknown, schema: T): {
4
- valid: true;
5
- data: Static<T>;
6
- } | {
7
- valid: false;
8
- error: string;
9
- };
@@ -1,43 +0,0 @@
1
- import Ajv from "ajv";
2
- import ajvErrors from "ajv-errors";
3
- import addFormats from "ajv-formats";
4
- const ajv = new Ajv({ allErrors: true, strict: false, coerceTypes: true });
5
- ajvErrors(ajv);
6
- addFormats(ajv);
7
- export function sanitizeStrings(input) {
8
- if (input === null || input === undefined) {
9
- return input;
10
- }
11
- if (typeof input === "string") {
12
- return input.trim();
13
- }
14
- // Handle arrays recursively
15
- if (Array.isArray(input)) {
16
- return input.map((item) => sanitizeStrings(item));
17
- }
18
- // Handle objects recursively
19
- if (typeof input === "object") {
20
- const result = {};
21
- for (const key in input) {
22
- if (Object.prototype.hasOwnProperty.call(input, key)) {
23
- result[key] = sanitizeStrings(input[key]);
24
- }
25
- }
26
- return result;
27
- }
28
- // Return non-string primitive values as-is
29
- return input;
30
- }
31
- // Generic validator function using TypeBox schemas
32
- export function ValidateRequest(data, schema) {
33
- const sanitizedData = sanitizeStrings(data);
34
- const validate = ajv.compile(schema);
35
- const isValid = validate(sanitizedData);
36
- if (isValid)
37
- return { valid: true, data: sanitizedData };
38
- const errorMessages = validate.errors?.map((e) => e.message).filter(Boolean);
39
- return {
40
- valid: false,
41
- error: errorMessages?.[0] || "Validation failed",
42
- };
43
- }