nexus-backend 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,288 +1,349 @@
1
- # Nexus Backend
2
-
3
- A lightweight backend utility library for [Express.js](https://expressjs.com/) providing structured error classes, standardised API response helpers, and a plug-and-play error handling middleware.
4
-
5
- ---
6
-
7
- ## Table of Contents
8
-
9
- - [Installation](#installation)
10
- - [Quick Start](#quick-start)
11
- - [API Reference](#api-reference)
12
- - [Response Helpers](#response-helpers)
13
- - [Error Classes](#error-classes)
14
- - [Error Middleware](#error-middleware)
15
- - [Response Shape](#response-shape)
16
- - [TypeScript](#typescript)
17
- - [License](#license)
18
-
19
- ---
20
-
21
- ## Installation
22
-
23
- ```bash
24
- npm install nexus-backend
25
- ```
26
-
27
- Express is a peer dependency — make sure it is installed in your project:
28
-
29
- ```bash
30
- npm install express
31
- ```
32
-
33
- ---
34
-
35
- ## Quick Start
36
-
37
- ```ts
38
- import express from "express";
39
- import {
40
- successResponse,
41
- errorMiddleware,
42
- NotFoundError,
43
- ValidationError,
44
- } from "nexusjs";
45
-
46
- const app = express();
47
- app.use(express.json());
48
-
49
- // Example route
50
- app.get("/users/:id", async (req, res, next) => {
51
- try {
52
- const user = await getUserById(req.params.id);
53
-
54
- if (!user) {
55
- throw new NotFoundError("User not found");
56
- }
57
-
58
- res.json(successResponse(user, "User fetched successfully"));
59
- } catch (err) {
60
- next(err);
61
- }
62
- });
63
-
64
- // Register error middleware last
65
- app.use(errorMiddleware);
66
-
67
- app.listen(3000);
68
- ```
69
-
70
- ---
71
-
72
- ## API Reference
73
-
74
- ### Response Helpers
75
-
76
- #### `successResponse(data, message?)`
77
-
78
- Returns a structured success payload. Pass the result directly to `res.json()`.
79
-
80
- ```ts
81
- successResponse<T>(data: T, message?: string): SuccessResponse<T>
82
- ```
83
-
84
- **Example**
85
-
86
- ```ts
87
- res.status(200).json(
88
- successResponse({ id: 1, name: "Alice" }, "User fetched successfully")
89
- );
90
- ```
91
-
92
- ```json
93
- {
94
- "success": true,
95
- "message": "User fetched successfully",
96
- "data": { "id": 1, "name": "Alice" }
97
- }
98
- ```
99
-
100
- ---
101
-
102
- #### `errorResponse(message, errors?, stack?)`
103
-
104
- Returns a structured error payload. You will rarely call this directly — `errorMiddleware` calls it internally. Useful if you need to construct an error response manually.
105
-
106
- ```ts
107
- errorResponse(message: string, errors?: any, stack?: string): ErrorResponse
108
- ```
109
-
110
- **Example**
111
-
112
- ```ts
113
- res.status(400).json(
114
- errorResponse("Validation failed", { field: "email", issue: "Required" })
115
- );
116
- ```
117
-
118
- ```json
119
- {
120
- "success": false,
121
- "message": "Validation failed",
122
- "errors": { "field": "email", "issue": "Required" }
123
- }
124
- ```
125
-
126
- ---
127
-
128
- ### Error Classes
129
-
130
- All error classes extend the base `ApiError` class, which itself extends the native `Error`. Throw any of these inside a route and let `errorMiddleware` handle the rest.
131
-
132
- #### `ApiError`
133
-
134
- The base error class. Use this when none of the specific subclasses fit your use case.
135
-
136
- ```ts
137
- new ApiError(message: string, statusCode?: number, errors?: any, isOperational?: boolean)
138
- ```
139
-
140
- | Parameter | Type | Default | Description |
141
- |---|---|---|---|
142
- | `message` | `string` | — | Human-readable error message |
143
- | `statusCode` | `number` | `500` | HTTP status code |
144
- | `errors` | `any` | `undefined` | Additional error details or field errors |
145
- | `isOperational` | `boolean` | `true` | Marks the error as an expected operational error |
146
-
147
- ---
148
-
149
- #### `BadRequestError`
150
-
151
- **Status:** `400 Bad Request`
152
-
153
- Use when the client sends a malformed or invalid request.
154
-
155
- ```ts
156
- throw new BadRequestError("Invalid request body");
157
- ```
158
-
159
- ---
160
-
161
- #### `UnauthorizedError`
162
-
163
- **Status:** `401 Unauthorized`
164
-
165
- Use when authentication is missing or invalid.
166
-
167
- ```ts
168
- throw new UnauthorizedError("Invalid token");
169
- ```
170
-
171
- ---
172
-
173
- #### `ForbiddenError`
174
-
175
- **Status:** `403 Forbidden`
176
-
177
- Use when an authenticated user lacks permission to access a resource.
178
-
179
- ```ts
180
- throw new ForbiddenError("You do not have access to this resource");
181
- ```
182
-
183
- ---
184
-
185
- #### `NotFoundError`
186
-
187
- **Status:** `404 Not Found`
188
-
189
- Use when a requested resource does not exist.
190
-
191
- ```ts
192
- throw new NotFoundError("Post not found");
193
- ```
194
-
195
- ---
196
-
197
- #### `ValidationError`
198
-
199
- **Status:** `422 Unprocessable Entity`
200
-
201
- Use when request data fails validation. Pass field-level errors via the `errors` argument.
202
-
203
- ```ts
204
- throw new ValidationError("Validation failed", [
205
- { field: "email", message: "Must be a valid email address" },
206
- { field: "password", message: "Must be at least 8 characters" },
207
- ]);
208
- ```
209
-
210
- ---
211
-
212
- ### Error Middleware
213
-
214
- #### `errorMiddleware`
215
-
216
- An Express-compatible error handling middleware. It catches any error passed to `next(err)`, determines the appropriate HTTP status code and message, and sends a structured `ErrorResponse`.
217
-
218
- Register it **after all routes** and other middleware.
219
-
220
- ```ts
221
- import { errorMiddleware } from "nexusjs";
222
-
223
- app.use(errorMiddleware);
224
- ```
225
-
226
- **Behaviour**
227
-
228
- - If the error is an instance of `ApiError` (or any subclass), the middleware uses the error's own `statusCode` and `message`.
229
- - For all other unhandled errors, it falls back to `500 Internal Server Error`.
230
- - When `NODE_ENV` is set to `"development"`, the response includes a `stack` field with the full stack trace to aid debugging. The `stack` field is omitted in production.
231
-
232
- **Development response example**
233
-
234
- ```json
235
- {
236
- "success": false,
237
- "message": "User not found",
238
- "errors": null,
239
- "stack": "NotFoundError: User not found\n at ..."
240
- }
241
- ```
242
-
243
- ---
244
-
245
- ## Response Shape
246
-
247
- All responses follow a consistent structure.
248
-
249
- #### Success
250
-
251
- ```ts
252
- interface SuccessResponse<T> {
253
- success: true;
254
- message?: string;
255
- data: T;
256
- }
257
- ```
258
-
259
- #### Error
260
-
261
- ```ts
262
- interface ErrorResponse {
263
- success: false;
264
- message: string;
265
- errors?: any;
266
- stack?: string; // only present in development
267
- }
268
- ```
269
-
270
- ---
271
-
272
- ## TypeScript
273
-
274
- nexusjs is written in TypeScript and ships with type declarations out of the box. No `@types` package is needed.
275
-
276
- `SuccessResponse` and `ErrorResponse` are exported and can be used to type your own response wrappers or API clients:
277
-
278
- ```ts
279
- import type { SuccessResponse, ErrorResponse } from "nexusjs";
280
-
281
- type ApiResult<T> = SuccessResponse<T> | ErrorResponse;
282
- ```
283
-
284
- ---
285
-
286
- ## License
287
-
288
- MIT
1
+ # Nexus Backend
2
+
3
+ A lightweight backend utility library for [Express.js](https://expressjs.com/) providing structured error classes, standardised API response helpers, and a plug-and-play error handling middleware.
4
+
5
+ ---
6
+
7
+ ## Table of Contents
8
+
9
+ - [Installation](#installation)
10
+ - [Quick Start](#quick-start)
11
+ - [API Reference](#api-reference)
12
+ - [Response Helpers](#response-helpers)
13
+ - [Error Classes](#error-classes)
14
+ - [Error Middleware](#error-middleware)
15
+ - [Response Shape](#response-shape)
16
+ - [TypeScript](#typescript)
17
+ - [License](#license)
18
+
19
+ ---
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+
25
+ npm install express mongoose cors helmet morgan cookie-parser
26
+ ```
27
+
28
+ Express, mongoose, cors, helmet, morgan, and cookie-parser are peer dependencies — make sure they are installed in your project:
29
+
30
+ ```bash
31
+ npm install nexus-backend
32
+ ```
33
+
34
+ ---
35
+
36
+ ## Quick Start
37
+
38
+ ```ts
39
+ // src/config/mongoConfig.ts
40
+ import { type MongoConfig } from "nexus-backend";
41
+
42
+ const dbConfig: MongoConfig = {
43
+ subDomain: requiredEnv(process.env.DB_HOST, "DB_HOST"),
44
+ userName: requiredEnv(process.env.DB_USERNAME, "DB_USERNAME"),
45
+ password: requiredEnv(process.env.DB_PASSWORD, "DB_PASSWORD"),
46
+ cluster: requiredEnv(process.env.DB_CLUSTER, "DB_CLUSTER"),
47
+ dbName: requiredEnv(process.env.DB_NAME, "DB_NAME"),
48
+ };
49
+ export default dbConfig;
50
+ ```
51
+
52
+ ```ts
53
+ // src/server.ts
54
+ import express, { type Application, Request, Response } from "express";
55
+ import http from "http";
56
+ import {
57
+ successResponse,
58
+ errorMiddleware,
59
+ NotFoundError,
60
+ ValidationError,
61
+ } from "nexus-backend";
62
+ import cors from "cors";
63
+ import helmet from "helmet";
64
+ import morgan from "morgan";
65
+ import cookieParser from "cookie-parser";
66
+ import { Server } from "socket.io";
67
+
68
+ const app: Application = express();
69
+
70
+ if (process.env.NODE_ENV !== "production") {
71
+ app.use(morgan("dev"));
72
+ }
73
+ app.set("trust proxy", 1);
74
+ app.use(helmet());
75
+ app.use(
76
+ cors({
77
+ origin: process.env.FRONTEND_URL,
78
+ credentials: true,
79
+ }),
80
+ );
81
+
82
+ app.use(express.json({ limit: "500mb" })); // Adjust the limit as needed
83
+ app.use(express.urlencoded({ extended: true, limit: "500mb" })); // For parsing application/x-www-form-urlencoded
84
+ app.use(cookieParser());
85
+
86
+ // Example route
87
+ app.get("/users/:id", async (req: Request, res: Response) => {
88
+ const user = await getUserById(req.params.id);
89
+
90
+ if (!user) {
91
+ throw new NotFoundError("User not found");
92
+ }
93
+
94
+ res.json(successResponse(user, "User fetched successfully"));
95
+ });
96
+
97
+ // Register error middleware last
98
+ app.use(errorMiddleware);
99
+ const server = http.createServer(app);
100
+ export const io = new Server(server, {
101
+ cors: {
102
+ origin: process.env.FRONTEND_URL,
103
+ credentials: true,
104
+ },
105
+ });
106
+
107
+ export default server;
108
+ ```
109
+
110
+ ```ts
111
+ // src/index.ts
112
+ import "dotenv/config";
113
+ import { connectMongoDb } from "nexus-backend";
114
+ import dns from "dns";
115
+ import dbConfig from "./config/mongoConfig";
116
+ import server from "./server";
117
+ const PORT = process.env.PORT || 5000;
118
+ async () => {
119
+ dns.setServers(["1.1.1.1", "1.0.0.1"]);
120
+ const dbConnected = await connectMongoDb(dbConfig);
121
+ if (!dbConnected) {
122
+ console.error("Database connection failed. Exiting...");
123
+ process.exit(1);
124
+ }
125
+ server.listen(PORT, () => {
126
+ console.log(`Server running on ${PORT}`);
127
+ });
128
+ };
129
+ ```
130
+
131
+ ## API Reference
132
+
133
+ ### Response Helpers
134
+
135
+ #### `successResponse(data, message?)`
136
+
137
+ Returns a structured success payload. Pass the result directly to `res.json()`.
138
+
139
+ ```ts
140
+ successResponse<T>(data: T, message?: string): SuccessResponse<T>
141
+ ```
142
+
143
+ **Example**
144
+
145
+ ```ts
146
+ res
147
+ .status(200)
148
+ .json(successResponse({ id: 1, name: "Alice" }, "User fetched successfully"));
149
+ ```
150
+
151
+ ```json
152
+ {
153
+ "success": true,
154
+ "message": "User fetched successfully",
155
+ "data": { "id": 1, "name": "Alice" }
156
+ }
157
+ ```
158
+
159
+ ---
160
+
161
+ #### `errorResponse(message, errors?, stack?)`
162
+
163
+ Returns a structured error payload. You will rarely call this directly — `errorMiddleware` calls it internally. Useful if you need to construct an error response manually.
164
+
165
+ ```ts
166
+ errorResponse(message: string, errors?: any, stack?: string): ErrorResponse
167
+ ```
168
+
169
+ **Example**
170
+
171
+ ```ts
172
+ res
173
+ .status(400)
174
+ .json(
175
+ errorResponse("Validation failed", { field: "email", issue: "Required" }),
176
+ );
177
+ ```
178
+
179
+ ```json
180
+ {
181
+ "success": false,
182
+ "message": "Validation failed",
183
+ "errors": { "field": "email", "issue": "Required" }
184
+ }
185
+ ```
186
+
187
+ ---
188
+
189
+ ### Error Classes
190
+
191
+ All error classes extend the base `ApiError` class, which itself extends the native `Error`. Throw any of these inside a route and let `errorMiddleware` handle the rest.
192
+
193
+ #### `ApiError`
194
+
195
+ The base error class. Use this when none of the specific subclasses fit your use case.
196
+
197
+ ```ts
198
+ new ApiError(message: string, statusCode?: number, errors?: any, isOperational?: boolean)
199
+ ```
200
+
201
+ | Parameter | Type | Default | Description |
202
+ | --------------- | --------- | ----------- | ------------------------------------------------ |
203
+ | `message` | `string` | — | Human-readable error message |
204
+ | `statusCode` | `number` | `500` | HTTP status code |
205
+ | `errors` | `any` | `undefined` | Additional error details or field errors |
206
+ | `isOperational` | `boolean` | `true` | Marks the error as an expected operational error |
207
+
208
+ ---
209
+
210
+ #### `BadRequestError`
211
+
212
+ **Status:** `400 Bad Request`
213
+
214
+ Use when the client sends a malformed or invalid request.
215
+
216
+ ```ts
217
+ throw new BadRequestError("Invalid request body");
218
+ ```
219
+
220
+ ---
221
+
222
+ #### `UnauthorizedError`
223
+
224
+ **Status:** `401 Unauthorized`
225
+
226
+ Use when authentication is missing or invalid.
227
+
228
+ ```ts
229
+ throw new UnauthorizedError("Invalid token");
230
+ ```
231
+
232
+ ---
233
+
234
+ #### `ForbiddenError`
235
+
236
+ **Status:** `403 Forbidden`
237
+
238
+ Use when an authenticated user lacks permission to access a resource.
239
+
240
+ ```ts
241
+ throw new ForbiddenError("You do not have access to this resource");
242
+ ```
243
+
244
+ ---
245
+
246
+ #### `NotFoundError`
247
+
248
+ **Status:** `404 Not Found`
249
+
250
+ Use when a requested resource does not exist.
251
+
252
+ ```ts
253
+ throw new NotFoundError("Post not found");
254
+ ```
255
+
256
+ ---
257
+
258
+ #### `ValidationError`
259
+
260
+ **Status:** `422 Unprocessable Entity`
261
+
262
+ Use when request data fails validation. Pass field-level errors via the `errors` argument.
263
+
264
+ ```ts
265
+ throw new ValidationError("Validation failed", [
266
+ { field: "email", message: "Must be a valid email address" },
267
+ { field: "password", message: "Must be at least 8 characters" },
268
+ ]);
269
+ ```
270
+
271
+ ---
272
+
273
+ ### Error Middleware
274
+
275
+ #### `errorMiddleware`
276
+
277
+ An Express-compatible error handling middleware. It catches any error passed to `next(err)`, determines the appropriate HTTP status code and message, and sends a structured `ErrorResponse`.
278
+
279
+ Register it **after all routes** and other middleware.
280
+
281
+ ```ts
282
+ import { errorMiddleware } from "nexusjs";
283
+
284
+ app.use(errorMiddleware);
285
+ ```
286
+
287
+ **Behaviour**
288
+
289
+ - If the error is an instance of `ApiError` (or any subclass), the middleware uses the error's own `statusCode` and `message`.
290
+ - For all other unhandled errors, it falls back to `500 Internal Server Error`.
291
+ - When `NODE_ENV` is set to `"development"`, the response includes a `stack` field with the full stack trace to aid debugging. The `stack` field is omitted in production.
292
+
293
+ **Development response example**
294
+
295
+ ```json
296
+ {
297
+ "success": false,
298
+ "message": "User not found",
299
+ "errors": null,
300
+ "stack": "NotFoundError: User not found\n at ..."
301
+ }
302
+ ```
303
+
304
+ ---
305
+
306
+ ## Response Shape
307
+
308
+ All responses follow a consistent structure.
309
+
310
+ #### Success
311
+
312
+ ```ts
313
+ interface SuccessResponse<T> {
314
+ success: true;
315
+ message?: string;
316
+ data: T;
317
+ }
318
+ ```
319
+
320
+ #### Error
321
+
322
+ ```ts
323
+ interface ErrorResponse {
324
+ success: false;
325
+ message: string;
326
+ errors?: any;
327
+ stack?: string; // only present in development
328
+ }
329
+ ```
330
+
331
+ ---
332
+
333
+ ## TypeScript
334
+
335
+ nexusjs is written in TypeScript and ships with type declarations out of the box. No `@types` package is needed.
336
+
337
+ `SuccessResponse` and `ErrorResponse` are exported and can be used to type your own response wrappers or API clients:
338
+
339
+ ```ts
340
+ import type { SuccessResponse, ErrorResponse } from "nexusjs";
341
+
342
+ type ApiResult<T> = SuccessResponse<T> | ErrorResponse;
343
+ ```
344
+
345
+ ---
346
+
347
+ ## License
348
+
349
+ MIT
package/dist/index.d.mts CHANGED
@@ -16,6 +16,18 @@ declare const successResponse: <T>(data: T, message?: string) => SuccessResponse
16
16
 
17
17
  declare const errorResponse: (message: string, errors?: any, stack?: string) => ErrorResponse;
18
18
 
19
+ declare const requiredEnv: (value: string | undefined, key: string) => string;
20
+
21
+ interface MongoConfig {
22
+ subDomain: string;
23
+ userName: string;
24
+ password: string;
25
+ cluster: string;
26
+ dbName: string;
27
+ }
28
+
29
+ declare const connectMongoDb: (config: MongoConfig) => Promise<boolean>;
30
+
19
31
  declare class ApiError extends Error {
20
32
  statusCode: number;
21
33
  isOperational: boolean;
@@ -43,6 +55,9 @@ declare class ValidationError extends ApiError {
43
55
  constructor(message?: string, errors?: any);
44
56
  }
45
57
 
46
- declare const errorHandler: (err: any, req: Request, res: Response, next: NextFunction) => Response<any, Record<string, any>>;
58
+ declare const errorHandler: [
59
+ (req: Request, res: Response, next: NextFunction) => void,
60
+ (err: any, req: Request, res: Response, next: NextFunction) => void
61
+ ];
47
62
 
48
- export { ApiError, BadRequestError, type ErrorResponse, ForbiddenError, NotFoundError, type SuccessResponse, UnauthorizedError, ValidationError, errorHandler as errorMiddleware, errorResponse, successResponse };
63
+ export { ApiError, BadRequestError, type ErrorResponse, ForbiddenError, type MongoConfig, NotFoundError, type SuccessResponse, UnauthorizedError, ValidationError, connectMongoDb, errorHandler as errorMiddleware, errorResponse, requiredEnv, successResponse };
package/dist/index.d.ts CHANGED
@@ -16,6 +16,18 @@ declare const successResponse: <T>(data: T, message?: string) => SuccessResponse
16
16
 
17
17
  declare const errorResponse: (message: string, errors?: any, stack?: string) => ErrorResponse;
18
18
 
19
+ declare const requiredEnv: (value: string | undefined, key: string) => string;
20
+
21
+ interface MongoConfig {
22
+ subDomain: string;
23
+ userName: string;
24
+ password: string;
25
+ cluster: string;
26
+ dbName: string;
27
+ }
28
+
29
+ declare const connectMongoDb: (config: MongoConfig) => Promise<boolean>;
30
+
19
31
  declare class ApiError extends Error {
20
32
  statusCode: number;
21
33
  isOperational: boolean;
@@ -43,6 +55,9 @@ declare class ValidationError extends ApiError {
43
55
  constructor(message?: string, errors?: any);
44
56
  }
45
57
 
46
- declare const errorHandler: (err: any, req: Request, res: Response, next: NextFunction) => Response<any, Record<string, any>>;
58
+ declare const errorHandler: [
59
+ (req: Request, res: Response, next: NextFunction) => void,
60
+ (err: any, req: Request, res: Response, next: NextFunction) => void
61
+ ];
47
62
 
48
- export { ApiError, BadRequestError, type ErrorResponse, ForbiddenError, NotFoundError, type SuccessResponse, UnauthorizedError, ValidationError, errorHandler as errorMiddleware, errorResponse, successResponse };
63
+ export { ApiError, BadRequestError, type ErrorResponse, ForbiddenError, type MongoConfig, NotFoundError, type SuccessResponse, UnauthorizedError, ValidationError, connectMongoDb, errorHandler as errorMiddleware, errorResponse, requiredEnv, successResponse };
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
@@ -26,8 +36,10 @@ __export(index_exports, {
26
36
  NotFoundError: () => NotFoundError,
27
37
  UnauthorizedError: () => UnauthorizedError,
28
38
  ValidationError: () => ValidationError,
39
+ connectMongoDb: () => connectMongoDb,
29
40
  errorMiddleware: () => errorHandler_default,
30
41
  errorResponse: () => errorResponse,
42
+ requiredEnv: () => requiredEnv,
31
43
  successResponse: () => successResponse
32
44
  });
33
45
  module.exports = __toCommonJS(index_exports);
@@ -47,6 +59,39 @@ var errorResponse = (message, errors, stack) => ({
47
59
  stack
48
60
  });
49
61
 
62
+ // src/utils/envManager.ts
63
+ var requiredEnv = (value, key) => {
64
+ if (!value) {
65
+ throw new Error(`Missing required environment variable: ${key}`);
66
+ }
67
+ return value;
68
+ };
69
+
70
+ // src/config/mongoConfig.ts
71
+ var import_mongoose = __toESM(require("mongoose"));
72
+ var connectMongoDb = async (config) => {
73
+ const { subDomain, userName, password, cluster, dbName } = config;
74
+ const srvURL = `mongodb+srv://${userName}:${password}@${cluster.toLowerCase()}.${subDomain}.mongodb.net/${dbName}?retryWrites=true&w=majority&appName=${cluster.toLowerCase()}`;
75
+ 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}`;
76
+ try {
77
+ console.log("Trying primary +srv connection...");
78
+ await import_mongoose.default.connect(srvURL);
79
+ console.log("Connected to MongoDB Atlas via +srv URL");
80
+ return true;
81
+ } catch (err) {
82
+ console.warn("+srv connection failed:", err.message);
83
+ console.log("Trying fallback standard connection...");
84
+ try {
85
+ await import_mongoose.default.connect(fallbackURL);
86
+ console.log("Connected to MongoDB Atlas via fallback URL");
87
+ return true;
88
+ } catch (fallbackErr) {
89
+ console.error("Fallback connection failed:", fallbackErr.message);
90
+ return false;
91
+ }
92
+ }
93
+ };
94
+
50
95
  // src/errors/ApiError.ts
51
96
  var ApiError = class extends Error {
52
97
  constructor(message, statusCode = 500, errors, isOperational = true) {
@@ -94,7 +139,10 @@ var ValidationError = class extends ApiError {
94
139
  };
95
140
 
96
141
  // src/handlers/errorHandler.ts
97
- var errorHandler = (err, req, res, next) => {
142
+ var routeNotFoundHandler = (req, _, next) => {
143
+ next(new ApiError(`Route ${req.originalUrl} not found`, 404));
144
+ };
145
+ var globalErrorHandler = (err, req, res, next) => {
98
146
  console.error("Error:", err);
99
147
  let statusCode = 500;
100
148
  let message = "Internal Server Error";
@@ -108,14 +156,9 @@ var errorHandler = (err, req, res, next) => {
108
156
  if (process.env.NODE_ENV === "development") {
109
157
  stack = err.stack;
110
158
  }
111
- return res.status(statusCode).json(
112
- errorResponse(
113
- message,
114
- errors,
115
- stack
116
- )
117
- );
159
+ return res.status(statusCode).json(errorResponse(message, errors, stack));
118
160
  };
161
+ var errorHandler = [routeNotFoundHandler, globalErrorHandler];
119
162
  var errorHandler_default = errorHandler;
120
163
  // Annotate the CommonJS export names for ESM import in node:
121
164
  0 && (module.exports = {
@@ -125,8 +168,10 @@ var errorHandler_default = errorHandler;
125
168
  NotFoundError,
126
169
  UnauthorizedError,
127
170
  ValidationError,
171
+ connectMongoDb,
128
172
  errorMiddleware,
129
173
  errorResponse,
174
+ requiredEnv,
130
175
  successResponse
131
176
  });
132
177
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/responses/successResponse.ts","../src/responses/errorResponse.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\";\r\nexport { errorResponse } from \"./responses/errorResponse\";\r\n\r\nexport { default as ApiError } from \"./errors/ApiError\";\r\nexport { default as BadRequestError } from \"./errors/BadRequestError\";\r\nexport { default as UnauthorizedError } from \"./errors/UnauthorisedError\";\r\nexport { default as ForbiddenError } from \"./errors/ForbiddenError\";\r\nexport { default as NotFoundError } from \"./errors/NotFoundError\";\r\nexport { default as ValidationError } from \"./errors/ValidationError\";\r\n\r\nexport { default as errorMiddleware } from \"./handlers/errorHandler\";\r\n\r\nexport type {\r\n SuccessResponse,\r\n ErrorResponse,\r\n} from \"./types/response.types\";","import { SuccessResponse } from \"../types/response.types\";\r\n\r\nexport const successResponse = <T>(\r\n data: T,\r\n message?: string\r\n): SuccessResponse<T> => ({\r\n success: true,\r\n data,\r\n message,\r\n});","import { ErrorResponse } from \"../types/response.types\";\r\n\r\nexport const errorResponse = (\r\n message: string,\r\n errors?: any,\r\n stack?: string\r\n): ErrorResponse => ({\r\n success: false,\r\n message,\r\n errors,\r\n stack,\r\n});","export default class ApiError extends Error {\r\n statusCode: number;\r\n isOperational: boolean;\r\n errors?: any;\r\n\r\n constructor(\r\n message: string,\r\n statusCode = 500,\r\n errors?: any,\r\n isOperational = true\r\n ) {\r\n super(message);\r\n\r\n this.statusCode = statusCode;\r\n this.errors = errors;\r\n this.isOperational = isOperational;\r\n\r\n Error.captureStackTrace(this, this.constructor);\r\n }\r\n}","import ApiError from \"./ApiError\";\r\n\r\nexport default class BadRequestError extends ApiError {\r\n constructor(message = \"Bad Request\", errors?: any) {\r\n super(message, 400, errors);\r\n }\r\n}","import ApiError from \"./ApiError\";\r\n\r\nexport default class UnauthorizedError extends ApiError {\r\n constructor(message = \"Unauthorized\", errors?: any) {\r\n super(message, 401, errors);\r\n }\r\n}","import ApiError from \"./ApiError\";\r\n\r\nexport default class ForbiddenError extends ApiError {\r\n constructor(message = \"Forbidden\", errors?: any) {\r\n super(message, 403, errors);\r\n }\r\n}","import ApiError from \"./ApiError\";\r\n\r\nexport default class NotFoundError extends ApiError {\r\n constructor(message = \"Resource Not Found\", errors?: any) {\r\n super(message, 404, errors);\r\n }\r\n}","import ApiError from \"./ApiError\";\r\n\r\nexport default class ValidationError extends ApiError {\r\n constructor(message = \"Validation Failed\", errors?: any) {\r\n super(message, 422, errors);\r\n }\r\n}","import { Request, Response, NextFunction } from \"express\";\r\n\r\nimport ApiError from \"../errors/ApiError\";\r\nimport { errorResponse } from \"../responses/errorResponse\";\r\n\r\nconst errorHandler = (\r\n err: any,\r\n req: Request,\r\n res: Response,\r\n next: NextFunction\r\n) => {\r\n\r\n console.error(\"Error:\", err);\r\n\r\n let statusCode = 500;\r\n let message = \"Internal Server Error\";\r\n let errors = undefined;\r\n let stack = undefined;\r\n\r\n // Custom application errors\r\n if (err instanceof ApiError) {\r\n statusCode = err.statusCode;\r\n message = err.message;\r\n errors = err.errors;\r\n }\r\n\r\n // Development stack trace\r\n if (process.env.NODE_ENV === \"development\") {\r\n stack = err.stack;\r\n }\r\n\r\n return res.status(statusCode).json(\r\n errorResponse(\r\n message,\r\n errors,\r\n stack\r\n )\r\n );\r\n};\r\n\r\nexport default errorHandler;"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEO,IAAM,kBAAkB,CAC7B,MACA,aACwB;AAAA,EACxB,SAAS;AAAA,EACT;AAAA,EACA;AACF;;;ACPO,IAAM,gBAAgB,CAC3B,SACA,QACA,WACmB;AAAA,EACnB,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AACF;;;ACXA,IAAqB,WAArB,cAAsC,MAAM;AAAA,EAK1C,YACE,SACA,aAAa,KACb,QACA,gBAAgB,MAChB;AACA,UAAM,OAAO;AAEb,SAAK,aAAa;AAClB,SAAK,SAAS;AACd,SAAK,gBAAgB;AAErB,UAAM,kBAAkB,MAAM,KAAK,WAAW;AAAA,EAChD;AACF;;;ACjBA,IAAqB,kBAArB,cAA6C,SAAS;AAAA,EACpD,YAAY,UAAU,eAAe,QAAc;AACjD,UAAM,SAAS,KAAK,MAAM;AAAA,EAC5B;AACF;;;ACJA,IAAqB,oBAArB,cAA+C,SAAS;AAAA,EACtD,YAAY,UAAU,gBAAgB,QAAc;AAClD,UAAM,SAAS,KAAK,MAAM;AAAA,EAC5B;AACF;;;ACJA,IAAqB,iBAArB,cAA4C,SAAS;AAAA,EACnD,YAAY,UAAU,aAAa,QAAc;AAC/C,UAAM,SAAS,KAAK,MAAM;AAAA,EAC5B;AACF;;;ACJA,IAAqB,gBAArB,cAA2C,SAAS;AAAA,EAClD,YAAY,UAAU,sBAAsB,QAAc;AACxD,UAAM,SAAS,KAAK,MAAM;AAAA,EAC5B;AACF;;;ACJA,IAAqB,kBAArB,cAA6C,SAAS;AAAA,EACpD,YAAY,UAAU,qBAAqB,QAAc;AACvD,UAAM,SAAS,KAAK,MAAM;AAAA,EAC5B;AACF;;;ACDA,IAAM,eAAe,CACnB,KACA,KACA,KACA,SACG;AAEH,UAAQ,MAAM,UAAU,GAAG;AAE3B,MAAI,aAAa;AACjB,MAAI,UAAU;AACd,MAAI,SAAS;AACb,MAAI,QAAQ;AAGZ,MAAI,eAAe,UAAU;AAC3B,iBAAa,IAAI;AACjB,cAAU,IAAI;AACd,aAAS,IAAI;AAAA,EACf;AAGA,MAAI,QAAQ,IAAI,aAAa,eAAe;AAC1C,YAAQ,IAAI;AAAA,EACd;AAEA,SAAO,IAAI,OAAO,UAAU,EAAE;AAAA,IAC5B;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,uBAAQ;","names":[]}
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"]}
package/dist/index.mjs CHANGED
@@ -13,6 +13,39 @@ var errorResponse = (message, errors, stack) => ({
13
13
  stack
14
14
  });
15
15
 
16
+ // src/utils/envManager.ts
17
+ var requiredEnv = (value, key) => {
18
+ if (!value) {
19
+ throw new Error(`Missing required environment variable: ${key}`);
20
+ }
21
+ return value;
22
+ };
23
+
24
+ // src/config/mongoConfig.ts
25
+ import mongoose from "mongoose";
26
+ var connectMongoDb = async (config) => {
27
+ const { subDomain, userName, password, cluster, dbName } = config;
28
+ const srvURL = `mongodb+srv://${userName}:${password}@${cluster.toLowerCase()}.${subDomain}.mongodb.net/${dbName}?retryWrites=true&w=majority&appName=${cluster.toLowerCase()}`;
29
+ 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}`;
30
+ try {
31
+ console.log("Trying primary +srv connection...");
32
+ await mongoose.connect(srvURL);
33
+ console.log("Connected to MongoDB Atlas via +srv URL");
34
+ return true;
35
+ } catch (err) {
36
+ console.warn("+srv connection failed:", err.message);
37
+ console.log("Trying fallback standard connection...");
38
+ try {
39
+ await mongoose.connect(fallbackURL);
40
+ console.log("Connected to MongoDB Atlas via fallback URL");
41
+ return true;
42
+ } catch (fallbackErr) {
43
+ console.error("Fallback connection failed:", fallbackErr.message);
44
+ return false;
45
+ }
46
+ }
47
+ };
48
+
16
49
  // src/errors/ApiError.ts
17
50
  var ApiError = class extends Error {
18
51
  constructor(message, statusCode = 500, errors, isOperational = true) {
@@ -60,7 +93,10 @@ var ValidationError = class extends ApiError {
60
93
  };
61
94
 
62
95
  // src/handlers/errorHandler.ts
63
- var errorHandler = (err, req, res, next) => {
96
+ var routeNotFoundHandler = (req, _, next) => {
97
+ next(new ApiError(`Route ${req.originalUrl} not found`, 404));
98
+ };
99
+ var globalErrorHandler = (err, req, res, next) => {
64
100
  console.error("Error:", err);
65
101
  let statusCode = 500;
66
102
  let message = "Internal Server Error";
@@ -74,14 +110,9 @@ var errorHandler = (err, req, res, next) => {
74
110
  if (process.env.NODE_ENV === "development") {
75
111
  stack = err.stack;
76
112
  }
77
- return res.status(statusCode).json(
78
- errorResponse(
79
- message,
80
- errors,
81
- stack
82
- )
83
- );
113
+ return res.status(statusCode).json(errorResponse(message, errors, stack));
84
114
  };
115
+ var errorHandler = [routeNotFoundHandler, globalErrorHandler];
85
116
  var errorHandler_default = errorHandler;
86
117
  export {
87
118
  ApiError,
@@ -90,8 +121,10 @@ export {
90
121
  NotFoundError,
91
122
  UnauthorizedError,
92
123
  ValidationError,
124
+ connectMongoDb,
93
125
  errorHandler_default as errorMiddleware,
94
126
  errorResponse,
127
+ requiredEnv,
95
128
  successResponse
96
129
  };
97
130
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/responses/successResponse.ts","../src/responses/errorResponse.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\";\r\n\r\nexport const successResponse = <T>(\r\n data: T,\r\n message?: string\r\n): SuccessResponse<T> => ({\r\n success: true,\r\n data,\r\n message,\r\n});","import { ErrorResponse } from \"../types/response.types\";\r\n\r\nexport const errorResponse = (\r\n message: string,\r\n errors?: any,\r\n stack?: string\r\n): ErrorResponse => ({\r\n success: false,\r\n message,\r\n errors,\r\n stack,\r\n});","export default class ApiError extends Error {\r\n statusCode: number;\r\n isOperational: boolean;\r\n errors?: any;\r\n\r\n constructor(\r\n message: string,\r\n statusCode = 500,\r\n errors?: any,\r\n isOperational = true\r\n ) {\r\n super(message);\r\n\r\n this.statusCode = statusCode;\r\n this.errors = errors;\r\n this.isOperational = isOperational;\r\n\r\n Error.captureStackTrace(this, this.constructor);\r\n }\r\n}","import ApiError from \"./ApiError\";\r\n\r\nexport default class BadRequestError extends ApiError {\r\n constructor(message = \"Bad Request\", errors?: any) {\r\n super(message, 400, errors);\r\n }\r\n}","import ApiError from \"./ApiError\";\r\n\r\nexport default class UnauthorizedError extends ApiError {\r\n constructor(message = \"Unauthorized\", errors?: any) {\r\n super(message, 401, errors);\r\n }\r\n}","import ApiError from \"./ApiError\";\r\n\r\nexport default class ForbiddenError extends ApiError {\r\n constructor(message = \"Forbidden\", errors?: any) {\r\n super(message, 403, errors);\r\n }\r\n}","import ApiError from \"./ApiError\";\r\n\r\nexport default class NotFoundError extends ApiError {\r\n constructor(message = \"Resource Not Found\", errors?: any) {\r\n super(message, 404, errors);\r\n }\r\n}","import ApiError from \"./ApiError\";\r\n\r\nexport default class ValidationError extends ApiError {\r\n constructor(message = \"Validation Failed\", errors?: any) {\r\n super(message, 422, errors);\r\n }\r\n}","import { Request, Response, NextFunction } from \"express\";\r\n\r\nimport ApiError from \"../errors/ApiError\";\r\nimport { errorResponse } from \"../responses/errorResponse\";\r\n\r\nconst errorHandler = (\r\n err: any,\r\n req: Request,\r\n res: Response,\r\n next: NextFunction\r\n) => {\r\n\r\n console.error(\"Error:\", err);\r\n\r\n let statusCode = 500;\r\n let message = \"Internal Server Error\";\r\n let errors = undefined;\r\n let stack = undefined;\r\n\r\n // Custom application errors\r\n if (err instanceof ApiError) {\r\n statusCode = err.statusCode;\r\n message = err.message;\r\n errors = err.errors;\r\n }\r\n\r\n // Development stack trace\r\n if (process.env.NODE_ENV === \"development\") {\r\n stack = err.stack;\r\n }\r\n\r\n return res.status(statusCode).json(\r\n errorResponse(\r\n message,\r\n errors,\r\n stack\r\n )\r\n );\r\n};\r\n\r\nexport default errorHandler;"],"mappings":";AAEO,IAAM,kBAAkB,CAC7B,MACA,aACwB;AAAA,EACxB,SAAS;AAAA,EACT;AAAA,EACA;AACF;;;ACPO,IAAM,gBAAgB,CAC3B,SACA,QACA,WACmB;AAAA,EACnB,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AACF;;;ACXA,IAAqB,WAArB,cAAsC,MAAM;AAAA,EAK1C,YACE,SACA,aAAa,KACb,QACA,gBAAgB,MAChB;AACA,UAAM,OAAO;AAEb,SAAK,aAAa;AAClB,SAAK,SAAS;AACd,SAAK,gBAAgB;AAErB,UAAM,kBAAkB,MAAM,KAAK,WAAW;AAAA,EAChD;AACF;;;ACjBA,IAAqB,kBAArB,cAA6C,SAAS;AAAA,EACpD,YAAY,UAAU,eAAe,QAAc;AACjD,UAAM,SAAS,KAAK,MAAM;AAAA,EAC5B;AACF;;;ACJA,IAAqB,oBAArB,cAA+C,SAAS;AAAA,EACtD,YAAY,UAAU,gBAAgB,QAAc;AAClD,UAAM,SAAS,KAAK,MAAM;AAAA,EAC5B;AACF;;;ACJA,IAAqB,iBAArB,cAA4C,SAAS;AAAA,EACnD,YAAY,UAAU,aAAa,QAAc;AAC/C,UAAM,SAAS,KAAK,MAAM;AAAA,EAC5B;AACF;;;ACJA,IAAqB,gBAArB,cAA2C,SAAS;AAAA,EAClD,YAAY,UAAU,sBAAsB,QAAc;AACxD,UAAM,SAAS,KAAK,MAAM;AAAA,EAC5B;AACF;;;ACJA,IAAqB,kBAArB,cAA6C,SAAS;AAAA,EACpD,YAAY,UAAU,qBAAqB,QAAc;AACvD,UAAM,SAAS,KAAK,MAAM;AAAA,EAC5B;AACF;;;ACDA,IAAM,eAAe,CACnB,KACA,KACA,KACA,SACG;AAEH,UAAQ,MAAM,UAAU,GAAG;AAE3B,MAAI,aAAa;AACjB,MAAI,UAAU;AACd,MAAI,SAAS;AACb,MAAI,QAAQ;AAGZ,MAAI,eAAe,UAAU;AAC3B,iBAAa,IAAI;AACjB,cAAU,IAAI;AACd,aAAS,IAAI;AAAA,EACf;AAGA,MAAI,QAAQ,IAAI,aAAa,eAAe;AAC1C,YAAQ,IAAI;AAAA,EACd;AAEA,SAAO,IAAI,OAAO,UAAU,EAAE;AAAA,IAC5B;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,uBAAQ;","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"],"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":";AAEO,IAAM,kBAAkB,CAC7B,MACA,aACwB;AAAA,EACxB,SAAS;AAAA,EACT;AAAA,EACA;AACF;;;ACPO,IAAM,gBAAgB,CAC3B,SACA,QACA,WACmB;AAAA,EACnB,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AACF;;;ACXO,IAAM,cAAc,CAAC,OAA2B,QAAwB;AAC7E,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,0CAA0C,GAAG,EAAE;AAAA,EACjE;AACA,SAAO;AACT;;;ACLA,OAAO,cAAc;AAId,IAAM,iBAAiB,OAAO,WAAwB;AAC3D,QAAM,EAAE,WAAW,UAAU,UAAU,SAAS,OAAO,IAAI;AAE3D,QAAM,SAAS,iBAAiB,QAAQ,IAAI,QAAQ,IAAI,QAAQ,YAAY,CAAC,IAAI,SAAS,gBAAgB,MAAM,wCAAwC,QAAQ,YAAY,CAAC;AAE7K,QAAM,cAAc,aAAa,QAAQ,IAAI,QAAQ,2BAA2B,SAAS,6CAA6C,SAAS,6CAA6C,SAAS,sBAAsB,MAAM,sEAAsE,OAAO;AAC9S,MAAI;AACF,YAAQ,IAAI,mCAAmC;AAC/C,UAAM,SAAS,QAAQ,MAAM;AAC7B,YAAQ,IAAI,yCAAyC;AACrD,WAAO;AAAA,EACT,SAAS,KAAU;AACjB,YAAQ,KAAK,2BAA2B,IAAI,OAAO;AACnD,YAAQ,IAAI,wCAAwC;AACpD,QAAI;AACF,YAAM,SAAS,QAAQ,WAAW;AAClC,cAAQ,IAAI,6CAA6C;AACzD,aAAO;AAAA,IACT,SAAS,aAAkB;AACzB,cAAQ,MAAM,+BAA+B,YAAY,OAAO;AAChE,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AC3BA,IAAqB,WAArB,cAAsC,MAAM;AAAA,EAK1C,YACE,SACA,aAAa,KACb,QACA,gBAAgB,MAChB;AACA,UAAM,OAAO;AAEb,SAAK,aAAa;AAClB,SAAK,SAAS;AACd,SAAK,gBAAgB;AAErB,UAAM,kBAAkB,MAAM,KAAK,WAAW;AAAA,EAChD;AACF;;;ACjBA,IAAqB,kBAArB,cAA6C,SAAS;AAAA,EACpD,YAAY,UAAU,eAAe,QAAc;AACjD,UAAM,SAAS,KAAK,MAAM;AAAA,EAC5B;AACF;;;ACJA,IAAqB,oBAArB,cAA+C,SAAS;AAAA,EACtD,YAAY,UAAU,gBAAgB,QAAc;AAClD,UAAM,SAAS,KAAK,MAAM;AAAA,EAC5B;AACF;;;ACJA,IAAqB,iBAArB,cAA4C,SAAS;AAAA,EACnD,YAAY,UAAU,aAAa,QAAc;AAC/C,UAAM,SAAS,KAAK,MAAM;AAAA,EAC5B;AACF;;;ACJA,IAAqB,gBAArB,cAA2C,SAAS;AAAA,EAClD,YAAY,UAAU,sBAAsB,QAAc;AACxD,UAAM,SAAS,KAAK,MAAM;AAAA,EAC5B;AACF;;;ACJA,IAAqB,kBAArB,cAA6C,SAAS;AAAA,EACpD,YAAY,UAAU,qBAAqB,QAAc;AACvD,UAAM,SAAS,KAAK,MAAM;AAAA,EAC5B;AACF;;;ACDA,IAAM,uBAAuB,CAAC,KAAc,GAAa,SAAuB;AAC9E,OAAK,IAAI,SAAS,SAAS,IAAI,WAAW,cAAc,GAAG,CAAC;AAC9D;AAEA,IAAM,qBAAqB,CAAC,KAAU,KAAc,KAAe,SAAuB;AACxF,UAAQ,MAAM,UAAU,GAAG;AAC3B,MAAI,aAAa;AACjB,MAAI,UAAU;AACd,MAAI,SAAS;AACb,MAAI,QAAQ;AAEZ,MAAI,eAAe,UAAU;AAC3B,iBAAa,IAAI;AACjB,cAAU,IAAI;AACd,aAAS,IAAI;AAAA,EACf;AAEA,MAAI,QAAQ,IAAI,aAAa,eAAe;AAC1C,YAAQ,IAAI;AAAA,EACd;AAEA,SAAO,IAAI,OAAO,UAAU,EAAE,KAAK,cAAc,SAAS,QAAQ,KAAK,CAAC;AAC1E;AAGA,IAAM,eAGF,CAAC,sBAAsB,kBAAkB;AAE7C,IAAO,uBAAQ;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexus-backend",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Backend utility library for Express.js",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -12,11 +12,20 @@
12
12
  "build": "tsup"
13
13
  },
14
14
  "peerDependencies": {
15
- "express": "^5.0.6"
15
+ "cookie-parser": "^1.4.7",
16
+ "cors": "^2.8.6",
17
+ "dotenv": "^17.4.2",
18
+ "express": "^5.0.6",
19
+ "helmet": "^8.1.0",
20
+ "mongoose": "^9.6.2",
21
+ "morgan": "^1.10.1",
22
+ "socket.io": "^4.8.3"
16
23
  },
17
24
  "devDependencies": {
25
+ "@types/cookie-parser": "^1.4.10",
26
+ "@types/cors": "^2.8.19",
18
27
  "@types/express": "^5.0.6",
19
28
  "tsup": "^8.5.1",
20
29
  "typescript": "^5.8.3"
21
30
  }
22
- }
31
+ }