nexus-backend 1.0.2 → 1.0.4
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/dist/index.d.mts +32 -1
- package/dist/index.d.ts +32 -1
- package/dist/index.js +116 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +113 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
import NodeCache from 'node-cache';
|
|
2
3
|
|
|
3
4
|
interface SuccessResponse<T = any> {
|
|
4
5
|
success: true;
|
|
@@ -60,4 +61,34 @@ declare const errorHandler: [
|
|
|
60
61
|
(err: any, req: Request, res: Response, next: NextFunction) => void
|
|
61
62
|
];
|
|
62
63
|
|
|
63
|
-
|
|
64
|
+
type CacheValue = unknown;
|
|
65
|
+
type ComputeFn<T> = () => Promise<T> | T;
|
|
66
|
+
declare class Cache extends NodeCache {
|
|
67
|
+
private namespaces;
|
|
68
|
+
private tagMap;
|
|
69
|
+
constructor(options?: NodeCache.Options);
|
|
70
|
+
private getKey;
|
|
71
|
+
private removeKeyFromTags;
|
|
72
|
+
setItem(key: string, value: CacheValue, ttl?: number, namespace?: string, tags?: string[]): void;
|
|
73
|
+
getItem<T = unknown>(key: string, namespace?: string): T | undefined;
|
|
74
|
+
getOrSetItem<T>(key: string, computeFn: ComputeFn<T>, ttl?: number, namespace?: string, tags?: string[]): Promise<T>;
|
|
75
|
+
deleteItem(key: string, namespace?: string): number;
|
|
76
|
+
clearNamespace(namespace?: string): void;
|
|
77
|
+
/**
|
|
78
|
+
* Delete all keys associated with a tag
|
|
79
|
+
*/
|
|
80
|
+
clearTag(tag: string): void;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
declare const cacheMemory: Cache;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Generates a random numeric string of given length.
|
|
87
|
+
* Uses crypto for better randomness (production safe).
|
|
88
|
+
*
|
|
89
|
+
* @param digit - Length of the random number
|
|
90
|
+
* @returns string
|
|
91
|
+
*/
|
|
92
|
+
declare function random(digit: number): string;
|
|
93
|
+
|
|
94
|
+
export { ApiError, BadRequestError, Cache, type ErrorResponse, ForbiddenError, type MongoConfig, NotFoundError, type SuccessResponse, UnauthorizedError, ValidationError, cacheMemory, connectMongoDb, errorHandler as errorMiddleware, errorResponse, random, requiredEnv, successResponse };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
import NodeCache from 'node-cache';
|
|
2
3
|
|
|
3
4
|
interface SuccessResponse<T = any> {
|
|
4
5
|
success: true;
|
|
@@ -60,4 +61,34 @@ declare const errorHandler: [
|
|
|
60
61
|
(err: any, req: Request, res: Response, next: NextFunction) => void
|
|
61
62
|
];
|
|
62
63
|
|
|
63
|
-
|
|
64
|
+
type CacheValue = unknown;
|
|
65
|
+
type ComputeFn<T> = () => Promise<T> | T;
|
|
66
|
+
declare class Cache extends NodeCache {
|
|
67
|
+
private namespaces;
|
|
68
|
+
private tagMap;
|
|
69
|
+
constructor(options?: NodeCache.Options);
|
|
70
|
+
private getKey;
|
|
71
|
+
private removeKeyFromTags;
|
|
72
|
+
setItem(key: string, value: CacheValue, ttl?: number, namespace?: string, tags?: string[]): void;
|
|
73
|
+
getItem<T = unknown>(key: string, namespace?: string): T | undefined;
|
|
74
|
+
getOrSetItem<T>(key: string, computeFn: ComputeFn<T>, ttl?: number, namespace?: string, tags?: string[]): Promise<T>;
|
|
75
|
+
deleteItem(key: string, namespace?: string): number;
|
|
76
|
+
clearNamespace(namespace?: string): void;
|
|
77
|
+
/**
|
|
78
|
+
* Delete all keys associated with a tag
|
|
79
|
+
*/
|
|
80
|
+
clearTag(tag: string): void;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
declare const cacheMemory: Cache;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Generates a random numeric string of given length.
|
|
87
|
+
* Uses crypto for better randomness (production safe).
|
|
88
|
+
*
|
|
89
|
+
* @param digit - Length of the random number
|
|
90
|
+
* @returns string
|
|
91
|
+
*/
|
|
92
|
+
declare function random(digit: number): string;
|
|
93
|
+
|
|
94
|
+
export { ApiError, BadRequestError, Cache, type ErrorResponse, ForbiddenError, type MongoConfig, NotFoundError, type SuccessResponse, UnauthorizedError, ValidationError, cacheMemory, connectMongoDb, errorHandler as errorMiddleware, errorResponse, random, requiredEnv, successResponse };
|
package/dist/index.js
CHANGED
|
@@ -32,13 +32,16 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
ApiError: () => ApiError,
|
|
34
34
|
BadRequestError: () => BadRequestError,
|
|
35
|
+
Cache: () => Cache,
|
|
35
36
|
ForbiddenError: () => ForbiddenError,
|
|
36
37
|
NotFoundError: () => NotFoundError,
|
|
37
38
|
UnauthorizedError: () => UnauthorizedError,
|
|
38
39
|
ValidationError: () => ValidationError,
|
|
40
|
+
cacheMemory: () => cacheMemory_default,
|
|
39
41
|
connectMongoDb: () => connectMongoDb,
|
|
40
42
|
errorMiddleware: () => errorHandler_default,
|
|
41
43
|
errorResponse: () => errorResponse,
|
|
44
|
+
random: () => random,
|
|
42
45
|
requiredEnv: () => requiredEnv,
|
|
43
46
|
successResponse: () => successResponse
|
|
44
47
|
});
|
|
@@ -160,17 +163,130 @@ var globalErrorHandler = (err, req, res, next) => {
|
|
|
160
163
|
};
|
|
161
164
|
var errorHandler = [routeNotFoundHandler, globalErrorHandler];
|
|
162
165
|
var errorHandler_default = errorHandler;
|
|
166
|
+
|
|
167
|
+
// src/utils/cache.ts
|
|
168
|
+
var import_node_cache = __toESM(require("node-cache"));
|
|
169
|
+
var Cache = class extends import_node_cache.default {
|
|
170
|
+
constructor(options = {}) {
|
|
171
|
+
const defaults = {
|
|
172
|
+
stdTTL: 60,
|
|
173
|
+
checkperiod: 120
|
|
174
|
+
};
|
|
175
|
+
super({ ...defaults, ...options });
|
|
176
|
+
this.namespaces = /* @__PURE__ */ new Set();
|
|
177
|
+
this.tagMap = /* @__PURE__ */ new Map();
|
|
178
|
+
this.on("expired", (key, value) => {
|
|
179
|
+
console.log(`[Cache] Key expired: ${key} ->`, value);
|
|
180
|
+
this.removeKeyFromTags(key);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
getKey(key, namespace) {
|
|
184
|
+
return namespace ? `${namespace}:${key}` : key;
|
|
185
|
+
}
|
|
186
|
+
removeKeyFromTags(key) {
|
|
187
|
+
for (const [tag, keys] of this.tagMap.entries()) {
|
|
188
|
+
if (keys.has(key)) {
|
|
189
|
+
keys.delete(key);
|
|
190
|
+
if (keys.size === 0) {
|
|
191
|
+
this.tagMap.delete(tag);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
setItem(key, value, ttl = 60, namespace, tags = []) {
|
|
197
|
+
const fullKey = this.getKey(key, namespace);
|
|
198
|
+
if (namespace) {
|
|
199
|
+
this.namespaces.add(namespace);
|
|
200
|
+
}
|
|
201
|
+
const storedValue = typeof value === "string" ? value : JSON.stringify(value);
|
|
202
|
+
this.set(fullKey, storedValue, ttl);
|
|
203
|
+
for (const tag of tags) {
|
|
204
|
+
if (!this.tagMap.has(tag)) {
|
|
205
|
+
this.tagMap.set(tag, /* @__PURE__ */ new Set());
|
|
206
|
+
}
|
|
207
|
+
this.tagMap.get(tag).add(fullKey);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
getItem(key, namespace) {
|
|
211
|
+
const fullKey = this.getKey(key, namespace);
|
|
212
|
+
const value = this.get(fullKey);
|
|
213
|
+
if (value === void 0) return void 0;
|
|
214
|
+
try {
|
|
215
|
+
return JSON.parse(value);
|
|
216
|
+
} catch {
|
|
217
|
+
return value;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
async getOrSetItem(key, computeFn, ttl, namespace, tags = []) {
|
|
221
|
+
let value = this.getItem(key, namespace);
|
|
222
|
+
if (value === void 0) {
|
|
223
|
+
value = await computeFn();
|
|
224
|
+
this.setItem(key, value, ttl, namespace, tags);
|
|
225
|
+
}
|
|
226
|
+
return value;
|
|
227
|
+
}
|
|
228
|
+
deleteItem(key, namespace) {
|
|
229
|
+
const fullKey = this.getKey(key, namespace);
|
|
230
|
+
this.removeKeyFromTags(fullKey);
|
|
231
|
+
return this.del(fullKey);
|
|
232
|
+
}
|
|
233
|
+
clearNamespace(namespace) {
|
|
234
|
+
if (!namespace) {
|
|
235
|
+
this.flushAll();
|
|
236
|
+
this.tagMap.clear();
|
|
237
|
+
console.log("[Cache] All keys cleared");
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
for (const key of this.keys()) {
|
|
241
|
+
if (key.startsWith(`${namespace}:`)) {
|
|
242
|
+
this.deleteItem(key);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
console.log(`[Cache] Namespace "${namespace}" cleared`);
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Delete all keys associated with a tag
|
|
249
|
+
*/
|
|
250
|
+
clearTag(tag) {
|
|
251
|
+
const keys = this.tagMap.get(tag);
|
|
252
|
+
if (!keys) return;
|
|
253
|
+
for (const key of keys) {
|
|
254
|
+
this.del(key);
|
|
255
|
+
}
|
|
256
|
+
this.tagMap.delete(tag);
|
|
257
|
+
console.log(`[Cache] All keys with tag "${tag}" cleared`);
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
// src/utils/cacheMemory.ts
|
|
262
|
+
var cacheMemory = new Cache();
|
|
263
|
+
var cacheMemory_default = cacheMemory;
|
|
264
|
+
|
|
265
|
+
// src/utils/randomNum.ts
|
|
266
|
+
var import_crypto = __toESM(require("crypto"));
|
|
267
|
+
function random(digit) {
|
|
268
|
+
if (!Number.isInteger(digit) || digit <= 0) {
|
|
269
|
+
throw new Error("Digit must be a positive integer");
|
|
270
|
+
}
|
|
271
|
+
const min = 10 ** (digit - 1);
|
|
272
|
+
const max = 10 ** digit - 1;
|
|
273
|
+
const randomNumber = import_crypto.default.randomInt(min, max + 1);
|
|
274
|
+
return randomNumber.toString();
|
|
275
|
+
}
|
|
163
276
|
// Annotate the CommonJS export names for ESM import in node:
|
|
164
277
|
0 && (module.exports = {
|
|
165
278
|
ApiError,
|
|
166
279
|
BadRequestError,
|
|
280
|
+
Cache,
|
|
167
281
|
ForbiddenError,
|
|
168
282
|
NotFoundError,
|
|
169
283
|
UnauthorizedError,
|
|
170
284
|
ValidationError,
|
|
285
|
+
cacheMemory,
|
|
171
286
|
connectMongoDb,
|
|
172
287
|
errorMiddleware,
|
|
173
288
|
errorResponse,
|
|
289
|
+
random,
|
|
174
290
|
requiredEnv,
|
|
175
291
|
successResponse
|
|
176
292
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/responses/successResponse.ts","../src/responses/errorResponse.ts","../src/utils/envManager.ts","../src/config/mongoConfig.ts","../src/errors/ApiError.ts","../src/errors/BadRequestError.ts","../src/errors/UnauthorisedError.ts","../src/errors/ForbiddenError.ts","../src/errors/NotFoundError.ts","../src/errors/ValidationError.ts","../src/handlers/errorHandler.ts"],"sourcesContent":["export { successResponse } from \"./responses/successResponse\";\nexport { errorResponse } from \"./responses/errorResponse\";\nexport { requiredEnv } from \"./utils/envManager\";\nexport { connectMongoDb } from \"./config/mongoConfig\";\nexport { default as ApiError } from \"./errors/ApiError\";\nexport { default as BadRequestError } from \"./errors/BadRequestError\";\nexport { default as UnauthorizedError } from \"./errors/UnauthorisedError\";\nexport { default as ForbiddenError } from \"./errors/ForbiddenError\";\nexport { default as NotFoundError } from \"./errors/NotFoundError\";\nexport { default as ValidationError } from \"./errors/ValidationError\";\nexport { default as errorMiddleware } from \"./handlers/errorHandler\";\n\nexport type { SuccessResponse, ErrorResponse } from \"./types/response.types\";\nexport { type MongoConfig } from \"./types/mongoConfig.types\";","import { SuccessResponse } from \"../types/response.types\";\n\nexport const successResponse = <T>(\n data: T,\n message?: string\n): SuccessResponse<T> => ({\n success: true,\n data,\n message,\n});","import { ErrorResponse } from \"../types/response.types\";\n\nexport const errorResponse = (\n message: string,\n errors?: any,\n stack?: string\n): ErrorResponse => ({\n success: false,\n message,\n errors,\n stack,\n});","export const requiredEnv = (value: string | undefined, key: string): string => {\n if (!value) {\n throw new Error(`Missing required environment variable: ${key}`);\n }\n return value;\n};","import mongoose from \"mongoose\";\n\nimport type { MongoConfig } from \"../types/mongoConfig.types\";\n\nexport const connectMongoDb = async (config: MongoConfig) => {\n const { subDomain, userName, password, cluster, dbName } = config;\n // Primary +srv URL\n const srvURL = `mongodb+srv://${userName}:${password}@${cluster.toLowerCase()}.${subDomain}.mongodb.net/${dbName}?retryWrites=true&w=majority&appName=${cluster.toLowerCase()}`;\n // Fallback standard mongodb:// URL (you need to adjust hostnames from Atlas)\n const fallbackURL = `mongodb://${userName}:${password}@ac-hkntio7-shard-00-00.${subDomain}.mongodb.net:27017,ac-hkntio7-shard-00-01.${subDomain}.mongodb.net:27017,ac-hkntio7-shard-00-02.${subDomain}.mongodb.net:27017/${dbName}?ssl=true&replicaSet=atlas-cji6jk-shard-0&authSource=admin&appName=${cluster}`;\n try {\n console.log(\"Trying primary +srv connection...\");\n await mongoose.connect(srvURL);\n console.log(\"Connected to MongoDB Atlas via +srv URL\");\n return true;\n } catch (err: any) {\n console.warn(\"+srv connection failed:\", err.message);\n console.log(\"Trying fallback standard connection...\");\n try {\n await mongoose.connect(fallbackURL);\n console.log(\"Connected to MongoDB Atlas via fallback URL\");\n return true;\n } catch (fallbackErr: any) {\n console.error(\"Fallback connection failed:\", fallbackErr.message);\n return false;\n }\n }\n};","export default class ApiError extends Error {\n statusCode: number;\n isOperational: boolean;\n errors?: any;\n\n constructor(\n message: string,\n statusCode = 500,\n errors?: any,\n isOperational = true\n ) {\n super(message);\n\n this.statusCode = statusCode;\n this.errors = errors;\n this.isOperational = isOperational;\n\n Error.captureStackTrace(this, this.constructor);\n }\n}","import ApiError from \"./ApiError\";\n\nexport default class BadRequestError extends ApiError {\n constructor(message = \"Bad Request\", errors?: any) {\n super(message, 400, errors);\n }\n}","import ApiError from \"./ApiError\";\n\nexport default class UnauthorizedError extends ApiError {\n constructor(message = \"Unauthorized\", errors?: any) {\n super(message, 401, errors);\n }\n}","import ApiError from \"./ApiError\";\n\nexport default class ForbiddenError extends ApiError {\n constructor(message = \"Forbidden\", errors?: any) {\n super(message, 403, errors);\n }\n}","import ApiError from \"./ApiError\";\n\nexport default class NotFoundError extends ApiError {\n constructor(message = \"Resource Not Found\", errors?: any) {\n super(message, 404, errors);\n }\n}","import ApiError from \"./ApiError\";\n\nexport default class ValidationError extends ApiError {\n constructor(message = \"Validation Failed\", errors?: any) {\n super(message, 422, errors);\n }\n}","// errorHandler.ts\nimport { Request, Response, NextFunction } from \"express\";\nimport ApiError from \"../errors/ApiError\";\nimport { errorResponse } from \"../responses/errorResponse\";\n\nconst routeNotFoundHandler = (req: Request, _: Response, next: NextFunction) => {\n next(new ApiError(`Route ${req.originalUrl} not found`, 404));\n};\n\nconst globalErrorHandler = (err: any, req: Request, res: Response, next: NextFunction) => {\n console.error(\"Error:\", err);\n let statusCode = 500;\n let message = \"Internal Server Error\";\n let errors = undefined;\n let stack = undefined;\n\n if (err instanceof ApiError) {\n statusCode = err.statusCode;\n message = err.message;\n errors = err.errors;\n }\n\n if (process.env.NODE_ENV === \"development\") {\n stack = err.stack;\n }\n\n return res.status(statusCode).json(errorResponse(message, errors, stack));\n};\n\n// Export as a tuple with explicit types so spread works correctly\nconst errorHandler: [\n (req: Request, res: Response, next: NextFunction) => void,\n (err: any, req: Request, res: Response, next: NextFunction) => void\n] = [routeNotFoundHandler, globalErrorHandler];\n\nexport default errorHandler;"],"mappings":"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","names":["mongoose"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/responses/successResponse.ts","../src/responses/errorResponse.ts","../src/utils/envManager.ts","../src/config/mongoConfig.ts","../src/errors/ApiError.ts","../src/errors/BadRequestError.ts","../src/errors/UnauthorisedError.ts","../src/errors/ForbiddenError.ts","../src/errors/NotFoundError.ts","../src/errors/ValidationError.ts","../src/handlers/errorHandler.ts","../src/utils/cache.ts","../src/utils/cacheMemory.ts","../src/utils/randomNum.ts"],"sourcesContent":["export { successResponse } from \"./responses/successResponse\";\nexport { errorResponse } from \"./responses/errorResponse\";\nexport { requiredEnv } from \"./utils/envManager\";\nexport { connectMongoDb } from \"./config/mongoConfig\";\nexport { default as ApiError } from \"./errors/ApiError\";\nexport { default as BadRequestError } from \"./errors/BadRequestError\";\nexport { default as UnauthorizedError } from \"./errors/UnauthorisedError\";\nexport { default as ForbiddenError } from \"./errors/ForbiddenError\";\nexport { default as NotFoundError } from \"./errors/NotFoundError\";\nexport { default as ValidationError } from \"./errors/ValidationError\";\nexport { default as errorMiddleware } from \"./handlers/errorHandler\";\nexport { Cache } from \"./utils/cache\";\nexport { default as cacheMemory } from \"./utils/cacheMemory\";\nexport {default as random} from \"./utils/randomNum\";\nexport type { SuccessResponse, ErrorResponse } from \"./types/response.types\";\nexport { type MongoConfig } from \"./types/mongoConfig.types\";\n","import { SuccessResponse } from \"../types/response.types\";\n\nexport const successResponse = <T>(\n data: T,\n message?: string\n): SuccessResponse<T> => ({\n success: true,\n data,\n message,\n});","import { ErrorResponse } from \"../types/response.types\";\n\nexport const errorResponse = (\n message: string,\n errors?: any,\n stack?: string\n): ErrorResponse => ({\n success: false,\n message,\n errors,\n stack,\n});","export const requiredEnv = (value: string | undefined, key: string): string => {\n if (!value) {\n throw new Error(`Missing required environment variable: ${key}`);\n }\n return value;\n};","import mongoose from \"mongoose\";\n\nimport type { MongoConfig } from \"../types/mongoConfig.types\";\n\nexport const connectMongoDb = async (config: MongoConfig) => {\n const { subDomain, userName, password, cluster, dbName } = config;\n // Primary +srv URL\n const srvURL = `mongodb+srv://${userName}:${password}@${cluster.toLowerCase()}.${subDomain}.mongodb.net/${dbName}?retryWrites=true&w=majority&appName=${cluster.toLowerCase()}`;\n // Fallback standard mongodb:// URL (you need to adjust hostnames from Atlas)\n const fallbackURL = `mongodb://${userName}:${password}@ac-hkntio7-shard-00-00.${subDomain}.mongodb.net:27017,ac-hkntio7-shard-00-01.${subDomain}.mongodb.net:27017,ac-hkntio7-shard-00-02.${subDomain}.mongodb.net:27017/${dbName}?ssl=true&replicaSet=atlas-cji6jk-shard-0&authSource=admin&appName=${cluster}`;\n try {\n console.log(\"Trying primary +srv connection...\");\n await mongoose.connect(srvURL);\n console.log(\"Connected to MongoDB Atlas via +srv URL\");\n return true;\n } catch (err: any) {\n console.warn(\"+srv connection failed:\", err.message);\n console.log(\"Trying fallback standard connection...\");\n try {\n await mongoose.connect(fallbackURL);\n console.log(\"Connected to MongoDB Atlas via fallback URL\");\n return true;\n } catch (fallbackErr: any) {\n console.error(\"Fallback connection failed:\", fallbackErr.message);\n return false;\n }\n }\n};","export default class ApiError extends Error {\n statusCode: number;\n isOperational: boolean;\n errors?: any;\n\n constructor(\n message: string,\n statusCode = 500,\n errors?: any,\n isOperational = true\n ) {\n super(message);\n\n this.statusCode = statusCode;\n this.errors = errors;\n this.isOperational = isOperational;\n\n Error.captureStackTrace(this, this.constructor);\n }\n}","import ApiError from \"./ApiError\";\n\nexport default class BadRequestError extends ApiError {\n constructor(message = \"Bad Request\", errors?: any) {\n super(message, 400, errors);\n }\n}","import ApiError from \"./ApiError\";\n\nexport default class UnauthorizedError extends ApiError {\n constructor(message = \"Unauthorized\", errors?: any) {\n super(message, 401, errors);\n }\n}","import ApiError from \"./ApiError\";\n\nexport default class ForbiddenError extends ApiError {\n constructor(message = \"Forbidden\", errors?: any) {\n super(message, 403, errors);\n }\n}","import ApiError from \"./ApiError\";\n\nexport default class NotFoundError extends ApiError {\n constructor(message = \"Resource Not Found\", errors?: any) {\n super(message, 404, errors);\n }\n}","import ApiError from \"./ApiError\";\n\nexport default class ValidationError extends ApiError {\n constructor(message = \"Validation Failed\", errors?: any) {\n super(message, 422, errors);\n }\n}","// errorHandler.ts\nimport { Request, Response, NextFunction } from \"express\";\nimport ApiError from \"../errors/ApiError\";\nimport { errorResponse } from \"../responses/errorResponse\";\n\nconst routeNotFoundHandler = (req: Request, _: Response, next: NextFunction) => {\n next(new ApiError(`Route ${req.originalUrl} not found`, 404));\n};\n\nconst globalErrorHandler = (err: any, req: Request, res: Response, next: NextFunction) => {\n console.error(\"Error:\", err);\n let statusCode = 500;\n let message = \"Internal Server Error\";\n let errors = undefined;\n let stack = undefined;\n\n if (err instanceof ApiError) {\n statusCode = err.statusCode;\n message = err.message;\n errors = err.errors;\n }\n\n if (process.env.NODE_ENV === \"development\") {\n stack = err.stack;\n }\n\n return res.status(statusCode).json(errorResponse(message, errors, stack));\n};\n\n// Export as a tuple with explicit types so spread works correctly\nconst errorHandler: [\n (req: Request, res: Response, next: NextFunction) => void,\n (err: any, req: Request, res: Response, next: NextFunction) => void\n] = [routeNotFoundHandler, globalErrorHandler];\n\nexport default errorHandler;","import NodeCache from \"node-cache\";\n\ntype CacheValue = unknown;\ntype ComputeFn<T> = () => Promise<T> | T;\n\nexport class Cache extends NodeCache {\n private namespaces: Set<string>;\n private tagMap: Map<string, Set<string>>;\n\n constructor(options: NodeCache.Options = {}) {\n const defaults: NodeCache.Options = {\n stdTTL: 60,\n checkperiod: 120,\n };\n\n super({ ...defaults, ...options });\n\n this.namespaces = new Set<string>();\n this.tagMap = new Map<string, Set<string>>();\n\n this.on(\"expired\", (key: string, value: unknown) => {\n console.log(`[Cache] Key expired: ${key} ->`, value);\n this.removeKeyFromTags(key);\n });\n }\n\n private getKey(key: string, namespace?: string): string {\n return namespace ? `${namespace}:${key}` : key;\n }\n\n private removeKeyFromTags(key: string): void {\n for (const [tag, keys] of this.tagMap.entries()) {\n if (keys.has(key)) {\n keys.delete(key);\n if (keys.size === 0) {\n this.tagMap.delete(tag);\n }\n }\n }\n }\n\n setItem(\n key: string,\n value: CacheValue,\n ttl: number =60,\n namespace?: string,\n tags: string[] = []\n ): void {\n const fullKey = this.getKey(key, namespace);\n\n if (namespace) {\n this.namespaces.add(namespace);\n }\n\n const storedValue =\n typeof value === \"string\" ? value : JSON.stringify(value);\n\n this.set(fullKey, storedValue, ttl);\n\n for (const tag of tags) {\n if (!this.tagMap.has(tag)) {\n this.tagMap.set(tag, new Set<string>());\n }\n this.tagMap.get(tag)!.add(fullKey);\n }\n }\n\n getItem<T = unknown>(key: string, namespace?: string): T | undefined {\n const fullKey = this.getKey(key, namespace);\n const value = this.get(fullKey);\n\n if (value === undefined) return undefined;\n\n try {\n return JSON.parse(value as string) as T;\n } catch {\n return value as T;\n }\n }\n\n async getOrSetItem<T>(\n key: string,\n computeFn: ComputeFn<T>,\n ttl?: number,\n namespace?: string,\n tags: string[] = []\n ): Promise<T> {\n let value = this.getItem<T>(key, namespace);\n\n if (value === undefined) {\n value = await computeFn();\n this.setItem(key, value, ttl, namespace, tags);\n }\n\n return value;\n }\n\n deleteItem(key: string, namespace?: string): number {\n const fullKey = this.getKey(key, namespace);\n this.removeKeyFromTags(fullKey);\n return this.del(fullKey);\n }\n\n clearNamespace(namespace?: string): void {\n if (!namespace) {\n this.flushAll();\n this.tagMap.clear();\n console.log(\"[Cache] All keys cleared\");\n return;\n }\n\n for (const key of this.keys()) {\n if (key.startsWith(`${namespace}:`)) {\n this.deleteItem(key);\n }\n }\n\n console.log(`[Cache] Namespace \"${namespace}\" cleared`);\n }\n\n /**\n * Delete all keys associated with a tag\n */\n clearTag(tag: string): void {\n const keys = this.tagMap.get(tag);\n if (!keys) return;\n\n for (const key of keys) {\n this.del(key);\n }\n\n this.tagMap.delete(tag);\n console.log(`[Cache] All keys with tag \"${tag}\" cleared`);\n }\n}\n","import { Cache } from \"./cache\";\n\nconst cacheMemory = new Cache();\n\nexport default cacheMemory;\n","// src/utils/randomNum.ts\n\nimport crypto from \"crypto\";\n\n/**\n * Generates a random numeric string of given length.\n * Uses crypto for better randomness (production safe).\n *\n * @param digit - Length of the random number\n * @returns string\n */\nexport default function random(digit: number): string {\n if (!Number.isInteger(digit) || digit <= 0) {\n throw new Error(\"Digit must be a positive integer\");\n }\n\n const min = 10 ** (digit - 1);\n const max = 10 ** digit - 1;\n\n const randomNumber = crypto.randomInt(min, max + 1);\n\n return randomNumber.toString();\n}\n"],"mappings":"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","names":["mongoose","NodeCache","crypto"]}
|
package/dist/index.mjs
CHANGED
|
@@ -114,16 +114,129 @@ var globalErrorHandler = (err, req, res, next) => {
|
|
|
114
114
|
};
|
|
115
115
|
var errorHandler = [routeNotFoundHandler, globalErrorHandler];
|
|
116
116
|
var errorHandler_default = errorHandler;
|
|
117
|
+
|
|
118
|
+
// src/utils/cache.ts
|
|
119
|
+
import NodeCache from "node-cache";
|
|
120
|
+
var Cache = class extends NodeCache {
|
|
121
|
+
constructor(options = {}) {
|
|
122
|
+
const defaults = {
|
|
123
|
+
stdTTL: 60,
|
|
124
|
+
checkperiod: 120
|
|
125
|
+
};
|
|
126
|
+
super({ ...defaults, ...options });
|
|
127
|
+
this.namespaces = /* @__PURE__ */ new Set();
|
|
128
|
+
this.tagMap = /* @__PURE__ */ new Map();
|
|
129
|
+
this.on("expired", (key, value) => {
|
|
130
|
+
console.log(`[Cache] Key expired: ${key} ->`, value);
|
|
131
|
+
this.removeKeyFromTags(key);
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
getKey(key, namespace) {
|
|
135
|
+
return namespace ? `${namespace}:${key}` : key;
|
|
136
|
+
}
|
|
137
|
+
removeKeyFromTags(key) {
|
|
138
|
+
for (const [tag, keys] of this.tagMap.entries()) {
|
|
139
|
+
if (keys.has(key)) {
|
|
140
|
+
keys.delete(key);
|
|
141
|
+
if (keys.size === 0) {
|
|
142
|
+
this.tagMap.delete(tag);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
setItem(key, value, ttl = 60, namespace, tags = []) {
|
|
148
|
+
const fullKey = this.getKey(key, namespace);
|
|
149
|
+
if (namespace) {
|
|
150
|
+
this.namespaces.add(namespace);
|
|
151
|
+
}
|
|
152
|
+
const storedValue = typeof value === "string" ? value : JSON.stringify(value);
|
|
153
|
+
this.set(fullKey, storedValue, ttl);
|
|
154
|
+
for (const tag of tags) {
|
|
155
|
+
if (!this.tagMap.has(tag)) {
|
|
156
|
+
this.tagMap.set(tag, /* @__PURE__ */ new Set());
|
|
157
|
+
}
|
|
158
|
+
this.tagMap.get(tag).add(fullKey);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
getItem(key, namespace) {
|
|
162
|
+
const fullKey = this.getKey(key, namespace);
|
|
163
|
+
const value = this.get(fullKey);
|
|
164
|
+
if (value === void 0) return void 0;
|
|
165
|
+
try {
|
|
166
|
+
return JSON.parse(value);
|
|
167
|
+
} catch {
|
|
168
|
+
return value;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
async getOrSetItem(key, computeFn, ttl, namespace, tags = []) {
|
|
172
|
+
let value = this.getItem(key, namespace);
|
|
173
|
+
if (value === void 0) {
|
|
174
|
+
value = await computeFn();
|
|
175
|
+
this.setItem(key, value, ttl, namespace, tags);
|
|
176
|
+
}
|
|
177
|
+
return value;
|
|
178
|
+
}
|
|
179
|
+
deleteItem(key, namespace) {
|
|
180
|
+
const fullKey = this.getKey(key, namespace);
|
|
181
|
+
this.removeKeyFromTags(fullKey);
|
|
182
|
+
return this.del(fullKey);
|
|
183
|
+
}
|
|
184
|
+
clearNamespace(namespace) {
|
|
185
|
+
if (!namespace) {
|
|
186
|
+
this.flushAll();
|
|
187
|
+
this.tagMap.clear();
|
|
188
|
+
console.log("[Cache] All keys cleared");
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
for (const key of this.keys()) {
|
|
192
|
+
if (key.startsWith(`${namespace}:`)) {
|
|
193
|
+
this.deleteItem(key);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
console.log(`[Cache] Namespace "${namespace}" cleared`);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Delete all keys associated with a tag
|
|
200
|
+
*/
|
|
201
|
+
clearTag(tag) {
|
|
202
|
+
const keys = this.tagMap.get(tag);
|
|
203
|
+
if (!keys) return;
|
|
204
|
+
for (const key of keys) {
|
|
205
|
+
this.del(key);
|
|
206
|
+
}
|
|
207
|
+
this.tagMap.delete(tag);
|
|
208
|
+
console.log(`[Cache] All keys with tag "${tag}" cleared`);
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
// src/utils/cacheMemory.ts
|
|
213
|
+
var cacheMemory = new Cache();
|
|
214
|
+
var cacheMemory_default = cacheMemory;
|
|
215
|
+
|
|
216
|
+
// src/utils/randomNum.ts
|
|
217
|
+
import crypto from "crypto";
|
|
218
|
+
function random(digit) {
|
|
219
|
+
if (!Number.isInteger(digit) || digit <= 0) {
|
|
220
|
+
throw new Error("Digit must be a positive integer");
|
|
221
|
+
}
|
|
222
|
+
const min = 10 ** (digit - 1);
|
|
223
|
+
const max = 10 ** digit - 1;
|
|
224
|
+
const randomNumber = crypto.randomInt(min, max + 1);
|
|
225
|
+
return randomNumber.toString();
|
|
226
|
+
}
|
|
117
227
|
export {
|
|
118
228
|
ApiError,
|
|
119
229
|
BadRequestError,
|
|
230
|
+
Cache,
|
|
120
231
|
ForbiddenError,
|
|
121
232
|
NotFoundError,
|
|
122
233
|
UnauthorizedError,
|
|
123
234
|
ValidationError,
|
|
235
|
+
cacheMemory_default as cacheMemory,
|
|
124
236
|
connectMongoDb,
|
|
125
237
|
errorHandler_default as errorMiddleware,
|
|
126
238
|
errorResponse,
|
|
239
|
+
random,
|
|
127
240
|
requiredEnv,
|
|
128
241
|
successResponse
|
|
129
242
|
};
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/responses/successResponse.ts","../src/responses/errorResponse.ts","../src/utils/envManager.ts","../src/config/mongoConfig.ts","../src/errors/ApiError.ts","../src/errors/BadRequestError.ts","../src/errors/UnauthorisedError.ts","../src/errors/ForbiddenError.ts","../src/errors/NotFoundError.ts","../src/errors/ValidationError.ts","../src/handlers/errorHandler.ts"],"sourcesContent":["import { SuccessResponse } from \"../types/response.types\";\n\nexport const successResponse = <T>(\n data: T,\n message?: string\n): SuccessResponse<T> => ({\n success: true,\n data,\n message,\n});","import { ErrorResponse } from \"../types/response.types\";\n\nexport const errorResponse = (\n message: string,\n errors?: any,\n stack?: string\n): ErrorResponse => ({\n success: false,\n message,\n errors,\n stack,\n});","export const requiredEnv = (value: string | undefined, key: string): string => {\n if (!value) {\n throw new Error(`Missing required environment variable: ${key}`);\n }\n return value;\n};","import mongoose from \"mongoose\";\n\nimport type { MongoConfig } from \"../types/mongoConfig.types\";\n\nexport const connectMongoDb = async (config: MongoConfig) => {\n const { subDomain, userName, password, cluster, dbName } = config;\n // Primary +srv URL\n const srvURL = `mongodb+srv://${userName}:${password}@${cluster.toLowerCase()}.${subDomain}.mongodb.net/${dbName}?retryWrites=true&w=majority&appName=${cluster.toLowerCase()}`;\n // Fallback standard mongodb:// URL (you need to adjust hostnames from Atlas)\n const fallbackURL = `mongodb://${userName}:${password}@ac-hkntio7-shard-00-00.${subDomain}.mongodb.net:27017,ac-hkntio7-shard-00-01.${subDomain}.mongodb.net:27017,ac-hkntio7-shard-00-02.${subDomain}.mongodb.net:27017/${dbName}?ssl=true&replicaSet=atlas-cji6jk-shard-0&authSource=admin&appName=${cluster}`;\n try {\n console.log(\"Trying primary +srv connection...\");\n await mongoose.connect(srvURL);\n console.log(\"Connected to MongoDB Atlas via +srv URL\");\n return true;\n } catch (err: any) {\n console.warn(\"+srv connection failed:\", err.message);\n console.log(\"Trying fallback standard connection...\");\n try {\n await mongoose.connect(fallbackURL);\n console.log(\"Connected to MongoDB Atlas via fallback URL\");\n return true;\n } catch (fallbackErr: any) {\n console.error(\"Fallback connection failed:\", fallbackErr.message);\n return false;\n }\n }\n};","export default class ApiError extends Error {\n statusCode: number;\n isOperational: boolean;\n errors?: any;\n\n constructor(\n message: string,\n statusCode = 500,\n errors?: any,\n isOperational = true\n ) {\n super(message);\n\n this.statusCode = statusCode;\n this.errors = errors;\n this.isOperational = isOperational;\n\n Error.captureStackTrace(this, this.constructor);\n }\n}","import ApiError from \"./ApiError\";\n\nexport default class BadRequestError extends ApiError {\n constructor(message = \"Bad Request\", errors?: any) {\n super(message, 400, errors);\n }\n}","import ApiError from \"./ApiError\";\n\nexport default class UnauthorizedError extends ApiError {\n constructor(message = \"Unauthorized\", errors?: any) {\n super(message, 401, errors);\n }\n}","import ApiError from \"./ApiError\";\n\nexport default class ForbiddenError extends ApiError {\n constructor(message = \"Forbidden\", errors?: any) {\n super(message, 403, errors);\n }\n}","import ApiError from \"./ApiError\";\n\nexport default class NotFoundError extends ApiError {\n constructor(message = \"Resource Not Found\", errors?: any) {\n super(message, 404, errors);\n }\n}","import ApiError from \"./ApiError\";\n\nexport default class ValidationError extends ApiError {\n constructor(message = \"Validation Failed\", errors?: any) {\n super(message, 422, errors);\n }\n}","// errorHandler.ts\nimport { Request, Response, NextFunction } from \"express\";\nimport ApiError from \"../errors/ApiError\";\nimport { errorResponse } from \"../responses/errorResponse\";\n\nconst routeNotFoundHandler = (req: Request, _: Response, next: NextFunction) => {\n next(new ApiError(`Route ${req.originalUrl} not found`, 404));\n};\n\nconst globalErrorHandler = (err: any, req: Request, res: Response, next: NextFunction) => {\n console.error(\"Error:\", err);\n let statusCode = 500;\n let message = \"Internal Server Error\";\n let errors = undefined;\n let stack = undefined;\n\n if (err instanceof ApiError) {\n statusCode = err.statusCode;\n message = err.message;\n errors = err.errors;\n }\n\n if (process.env.NODE_ENV === \"development\") {\n stack = err.stack;\n }\n\n return res.status(statusCode).json(errorResponse(message, errors, stack));\n};\n\n// Export as a tuple with explicit types so spread works correctly\nconst errorHandler: [\n (req: Request, res: Response, next: NextFunction) => void,\n (err: any, req: Request, res: Response, next: NextFunction) => void\n] = [routeNotFoundHandler, globalErrorHandler];\n\nexport default errorHandler;"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/responses/successResponse.ts","../src/responses/errorResponse.ts","../src/utils/envManager.ts","../src/config/mongoConfig.ts","../src/errors/ApiError.ts","../src/errors/BadRequestError.ts","../src/errors/UnauthorisedError.ts","../src/errors/ForbiddenError.ts","../src/errors/NotFoundError.ts","../src/errors/ValidationError.ts","../src/handlers/errorHandler.ts","../src/utils/cache.ts","../src/utils/cacheMemory.ts","../src/utils/randomNum.ts"],"sourcesContent":["import { SuccessResponse } from \"../types/response.types\";\n\nexport const successResponse = <T>(\n data: T,\n message?: string\n): SuccessResponse<T> => ({\n success: true,\n data,\n message,\n});","import { ErrorResponse } from \"../types/response.types\";\n\nexport const errorResponse = (\n message: string,\n errors?: any,\n stack?: string\n): ErrorResponse => ({\n success: false,\n message,\n errors,\n stack,\n});","export const requiredEnv = (value: string | undefined, key: string): string => {\n if (!value) {\n throw new Error(`Missing required environment variable: ${key}`);\n }\n return value;\n};","import mongoose from \"mongoose\";\n\nimport type { MongoConfig } from \"../types/mongoConfig.types\";\n\nexport const connectMongoDb = async (config: MongoConfig) => {\n const { subDomain, userName, password, cluster, dbName } = config;\n // Primary +srv URL\n const srvURL = `mongodb+srv://${userName}:${password}@${cluster.toLowerCase()}.${subDomain}.mongodb.net/${dbName}?retryWrites=true&w=majority&appName=${cluster.toLowerCase()}`;\n // Fallback standard mongodb:// URL (you need to adjust hostnames from Atlas)\n const fallbackURL = `mongodb://${userName}:${password}@ac-hkntio7-shard-00-00.${subDomain}.mongodb.net:27017,ac-hkntio7-shard-00-01.${subDomain}.mongodb.net:27017,ac-hkntio7-shard-00-02.${subDomain}.mongodb.net:27017/${dbName}?ssl=true&replicaSet=atlas-cji6jk-shard-0&authSource=admin&appName=${cluster}`;\n try {\n console.log(\"Trying primary +srv connection...\");\n await mongoose.connect(srvURL);\n console.log(\"Connected to MongoDB Atlas via +srv URL\");\n return true;\n } catch (err: any) {\n console.warn(\"+srv connection failed:\", err.message);\n console.log(\"Trying fallback standard connection...\");\n try {\n await mongoose.connect(fallbackURL);\n console.log(\"Connected to MongoDB Atlas via fallback URL\");\n return true;\n } catch (fallbackErr: any) {\n console.error(\"Fallback connection failed:\", fallbackErr.message);\n return false;\n }\n }\n};","export default class ApiError extends Error {\n statusCode: number;\n isOperational: boolean;\n errors?: any;\n\n constructor(\n message: string,\n statusCode = 500,\n errors?: any,\n isOperational = true\n ) {\n super(message);\n\n this.statusCode = statusCode;\n this.errors = errors;\n this.isOperational = isOperational;\n\n Error.captureStackTrace(this, this.constructor);\n }\n}","import ApiError from \"./ApiError\";\n\nexport default class BadRequestError extends ApiError {\n constructor(message = \"Bad Request\", errors?: any) {\n super(message, 400, errors);\n }\n}","import ApiError from \"./ApiError\";\n\nexport default class UnauthorizedError extends ApiError {\n constructor(message = \"Unauthorized\", errors?: any) {\n super(message, 401, errors);\n }\n}","import ApiError from \"./ApiError\";\n\nexport default class ForbiddenError extends ApiError {\n constructor(message = \"Forbidden\", errors?: any) {\n super(message, 403, errors);\n }\n}","import ApiError from \"./ApiError\";\n\nexport default class NotFoundError extends ApiError {\n constructor(message = \"Resource Not Found\", errors?: any) {\n super(message, 404, errors);\n }\n}","import ApiError from \"./ApiError\";\n\nexport default class ValidationError extends ApiError {\n constructor(message = \"Validation Failed\", errors?: any) {\n super(message, 422, errors);\n }\n}","// errorHandler.ts\nimport { Request, Response, NextFunction } from \"express\";\nimport ApiError from \"../errors/ApiError\";\nimport { errorResponse } from \"../responses/errorResponse\";\n\nconst routeNotFoundHandler = (req: Request, _: Response, next: NextFunction) => {\n next(new ApiError(`Route ${req.originalUrl} not found`, 404));\n};\n\nconst globalErrorHandler = (err: any, req: Request, res: Response, next: NextFunction) => {\n console.error(\"Error:\", err);\n let statusCode = 500;\n let message = \"Internal Server Error\";\n let errors = undefined;\n let stack = undefined;\n\n if (err instanceof ApiError) {\n statusCode = err.statusCode;\n message = err.message;\n errors = err.errors;\n }\n\n if (process.env.NODE_ENV === \"development\") {\n stack = err.stack;\n }\n\n return res.status(statusCode).json(errorResponse(message, errors, stack));\n};\n\n// Export as a tuple with explicit types so spread works correctly\nconst errorHandler: [\n (req: Request, res: Response, next: NextFunction) => void,\n (err: any, req: Request, res: Response, next: NextFunction) => void\n] = [routeNotFoundHandler, globalErrorHandler];\n\nexport default errorHandler;","import NodeCache from \"node-cache\";\n\ntype CacheValue = unknown;\ntype ComputeFn<T> = () => Promise<T> | T;\n\nexport class Cache extends NodeCache {\n private namespaces: Set<string>;\n private tagMap: Map<string, Set<string>>;\n\n constructor(options: NodeCache.Options = {}) {\n const defaults: NodeCache.Options = {\n stdTTL: 60,\n checkperiod: 120,\n };\n\n super({ ...defaults, ...options });\n\n this.namespaces = new Set<string>();\n this.tagMap = new Map<string, Set<string>>();\n\n this.on(\"expired\", (key: string, value: unknown) => {\n console.log(`[Cache] Key expired: ${key} ->`, value);\n this.removeKeyFromTags(key);\n });\n }\n\n private getKey(key: string, namespace?: string): string {\n return namespace ? `${namespace}:${key}` : key;\n }\n\n private removeKeyFromTags(key: string): void {\n for (const [tag, keys] of this.tagMap.entries()) {\n if (keys.has(key)) {\n keys.delete(key);\n if (keys.size === 0) {\n this.tagMap.delete(tag);\n }\n }\n }\n }\n\n setItem(\n key: string,\n value: CacheValue,\n ttl: number =60,\n namespace?: string,\n tags: string[] = []\n ): void {\n const fullKey = this.getKey(key, namespace);\n\n if (namespace) {\n this.namespaces.add(namespace);\n }\n\n const storedValue =\n typeof value === \"string\" ? value : JSON.stringify(value);\n\n this.set(fullKey, storedValue, ttl);\n\n for (const tag of tags) {\n if (!this.tagMap.has(tag)) {\n this.tagMap.set(tag, new Set<string>());\n }\n this.tagMap.get(tag)!.add(fullKey);\n }\n }\n\n getItem<T = unknown>(key: string, namespace?: string): T | undefined {\n const fullKey = this.getKey(key, namespace);\n const value = this.get(fullKey);\n\n if (value === undefined) return undefined;\n\n try {\n return JSON.parse(value as string) as T;\n } catch {\n return value as T;\n }\n }\n\n async getOrSetItem<T>(\n key: string,\n computeFn: ComputeFn<T>,\n ttl?: number,\n namespace?: string,\n tags: string[] = []\n ): Promise<T> {\n let value = this.getItem<T>(key, namespace);\n\n if (value === undefined) {\n value = await computeFn();\n this.setItem(key, value, ttl, namespace, tags);\n }\n\n return value;\n }\n\n deleteItem(key: string, namespace?: string): number {\n const fullKey = this.getKey(key, namespace);\n this.removeKeyFromTags(fullKey);\n return this.del(fullKey);\n }\n\n clearNamespace(namespace?: string): void {\n if (!namespace) {\n this.flushAll();\n this.tagMap.clear();\n console.log(\"[Cache] All keys cleared\");\n return;\n }\n\n for (const key of this.keys()) {\n if (key.startsWith(`${namespace}:`)) {\n this.deleteItem(key);\n }\n }\n\n console.log(`[Cache] Namespace \"${namespace}\" cleared`);\n }\n\n /**\n * Delete all keys associated with a tag\n */\n clearTag(tag: string): void {\n const keys = this.tagMap.get(tag);\n if (!keys) return;\n\n for (const key of keys) {\n this.del(key);\n }\n\n this.tagMap.delete(tag);\n console.log(`[Cache] All keys with tag \"${tag}\" cleared`);\n }\n}\n","import { Cache } from \"./cache\";\n\nconst cacheMemory = new Cache();\n\nexport default cacheMemory;\n","// src/utils/randomNum.ts\n\nimport crypto from \"crypto\";\n\n/**\n * Generates a random numeric string of given length.\n * Uses crypto for better randomness (production safe).\n *\n * @param digit - Length of the random number\n * @returns string\n */\nexport default function random(digit: number): string {\n if (!Number.isInteger(digit) || digit <= 0) {\n throw new Error(\"Digit must be a positive integer\");\n }\n\n const min = 10 ** (digit - 1);\n const max = 10 ** digit - 1;\n\n const randomNumber = crypto.randomInt(min, max + 1);\n\n return randomNumber.toString();\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexus-backend",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Backend utility library for Express.js",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"helmet": "^8.1.0",
|
|
20
20
|
"mongoose": "^9.6.2",
|
|
21
21
|
"morgan": "^1.10.1",
|
|
22
|
-
"socket.io": "^4.8.3"
|
|
22
|
+
"socket.io": "^4.8.3",
|
|
23
|
+
"node-cache": "5.1.2"
|
|
23
24
|
},
|
|
24
25
|
"devDependencies": {
|
|
25
26
|
"@types/cookie-parser": "^1.4.10",
|