@masonprotsman/common 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/build/errors/bad-request-error.js +20 -0
- package/build/errors/custom-error.js +14 -0
- package/build/errors/database-connection-error.js +20 -0
- package/build/errors/not-authorized-error.js +19 -0
- package/build/errors/not-found-error.js +19 -0
- package/build/errors/request-validation-error.js +28 -0
- package/build/index.js +26 -0
- package/build/middlewares/current-user.js +27 -0
- package/build/middlewares/error-handler.js +16 -0
- package/build/middlewares/require-auth.js +16 -0
- package/build/middlewares/validate-request.js +19 -0
- package/package.json +31 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BadRequestError = void 0;
|
|
4
|
+
const custom_error_1 = require("./custom-error");
|
|
5
|
+
// Error thrown for general bad requests (e.g., email already in use)
|
|
6
|
+
// Returns 400 Bad Request status with custom message
|
|
7
|
+
class BadRequestError extends custom_error_1.CustomError {
|
|
8
|
+
constructor(message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.message = message;
|
|
11
|
+
this.statusCode = 400;
|
|
12
|
+
// Set prototype for proper instanceof checks with TypeScript
|
|
13
|
+
Object.setPrototypeOf(this, BadRequestError.prototype);
|
|
14
|
+
}
|
|
15
|
+
// Return error in standardized format for API response
|
|
16
|
+
serializeErrors() {
|
|
17
|
+
return [{ message: this.message }];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.BadRequestError = BadRequestError;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CustomError = void 0;
|
|
4
|
+
// Abstract base class for all custom errors in the application
|
|
5
|
+
// Ensures consistent error structure and response format
|
|
6
|
+
class CustomError extends Error {
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(message);
|
|
9
|
+
// Set prototype explicitly because we're extending a built-in class
|
|
10
|
+
// This ensures instanceof checks work correctly with TypeScript
|
|
11
|
+
Object.setPrototypeOf(this, CustomError.prototype);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.CustomError = CustomError;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DatabaseConnectionError = void 0;
|
|
4
|
+
const custom_error_1 = require("./custom-error");
|
|
5
|
+
// Error thrown when database connection fails
|
|
6
|
+
// Returns 500 Internal Server Error status
|
|
7
|
+
class DatabaseConnectionError extends custom_error_1.CustomError {
|
|
8
|
+
constructor() {
|
|
9
|
+
super('Error connecting to database');
|
|
10
|
+
this.statusCode = 500;
|
|
11
|
+
this.reason = 'Error connecting to database';
|
|
12
|
+
// Set prototype for proper instanceof checks with TypeScript
|
|
13
|
+
Object.setPrototypeOf(this, DatabaseConnectionError.prototype);
|
|
14
|
+
}
|
|
15
|
+
// Return error in standardized format for API response
|
|
16
|
+
serializeErrors() {
|
|
17
|
+
return [{ message: this.reason }];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.DatabaseConnectionError = DatabaseConnectionError;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NotAuthorizedError = void 0;
|
|
4
|
+
const custom_error_1 = require("./custom-error");
|
|
5
|
+
// Error thrown when user is not authenticated or lacks proper credentials
|
|
6
|
+
// Returns 401 Unauthorized status
|
|
7
|
+
class NotAuthorizedError extends custom_error_1.CustomError {
|
|
8
|
+
constructor() {
|
|
9
|
+
super('Not authorized');
|
|
10
|
+
this.statusCode = 401;
|
|
11
|
+
// Set prototype for proper instanceof checks with TypeScript
|
|
12
|
+
Object.setPrototypeOf(this, NotAuthorizedError.prototype);
|
|
13
|
+
}
|
|
14
|
+
// Return error in standardized format for API response
|
|
15
|
+
serializeErrors() {
|
|
16
|
+
return [{ message: 'Not authorized' }];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.NotAuthorizedError = NotAuthorizedError;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NotFoundError = void 0;
|
|
4
|
+
const custom_error_1 = require("./custom-error");
|
|
5
|
+
// Error thrown when a requested route doesn't exist
|
|
6
|
+
// Returns 404 Not Found status
|
|
7
|
+
class NotFoundError extends custom_error_1.CustomError {
|
|
8
|
+
constructor() {
|
|
9
|
+
super('Route not found');
|
|
10
|
+
this.statusCode = 404;
|
|
11
|
+
// Set prototype for proper instanceof checks with TypeScript
|
|
12
|
+
Object.setPrototypeOf(this, NotFoundError.prototype);
|
|
13
|
+
}
|
|
14
|
+
// Return error in standardized format for API response
|
|
15
|
+
serializeErrors() {
|
|
16
|
+
return [{ message: 'Not Found' }];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.NotFoundError = NotFoundError;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RequestValidationError = void 0;
|
|
4
|
+
const custom_error_1 = require("./custom-error");
|
|
5
|
+
// Error thrown when request validation fails (invalid input data)
|
|
6
|
+
// Returns 400 Bad Request status
|
|
7
|
+
class RequestValidationError extends custom_error_1.CustomError {
|
|
8
|
+
constructor(errors) {
|
|
9
|
+
super('Invalid request parameters');
|
|
10
|
+
this.errors = errors;
|
|
11
|
+
this.statusCode = 400;
|
|
12
|
+
// Set prototype for proper instanceof checks with TypeScript
|
|
13
|
+
Object.setPrototypeOf(this, RequestValidationError.prototype);
|
|
14
|
+
}
|
|
15
|
+
// Transform validation errors into standardized format
|
|
16
|
+
// Includes field name when available for client-side field highlighting
|
|
17
|
+
serializeErrors() {
|
|
18
|
+
return this.errors.map((err) => {
|
|
19
|
+
// For field-level validation errors, include the field path
|
|
20
|
+
if (err.type === 'field') {
|
|
21
|
+
return { message: err.msg, field: err.path };
|
|
22
|
+
}
|
|
23
|
+
// For general validation errors, return just the message
|
|
24
|
+
return { message: err.msg };
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.RequestValidationError = RequestValidationError;
|
package/build/index.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./errors/bad-request-error"), exports);
|
|
18
|
+
__exportStar(require("./errors/custom-error"), exports);
|
|
19
|
+
__exportStar(require("./errors/database-connection-error"), exports);
|
|
20
|
+
__exportStar(require("./errors/not-authorized-error"), exports);
|
|
21
|
+
__exportStar(require("./errors/not-found-error"), exports);
|
|
22
|
+
__exportStar(require("./errors/request-validation-error"), exports);
|
|
23
|
+
__exportStar(require("./middlewares/current-user"), exports);
|
|
24
|
+
__exportStar(require("./middlewares/error-handler"), exports);
|
|
25
|
+
__exportStar(require("./middlewares/require-auth"), exports);
|
|
26
|
+
__exportStar(require("./middlewares/validate-request"), exports);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.currentUser = void 0;
|
|
7
|
+
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
8
|
+
// Middleware that extracts user info from JWT and attaches it to req.currentUser
|
|
9
|
+
// Does not require authentication - just sets currentUser if valid JWT exists
|
|
10
|
+
const currentUser = (req, res, next) => {
|
|
11
|
+
var _a;
|
|
12
|
+
// If no JWT in session, continue without setting currentUser
|
|
13
|
+
if (!((_a = req.session) === null || _a === void 0 ? void 0 : _a.jwt)) {
|
|
14
|
+
return next();
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
// Verify and decode the JWT token
|
|
18
|
+
const payload = jsonwebtoken_1.default.verify(req.session.jwt, process.env.JWT_KEY);
|
|
19
|
+
// Attach user payload to request for use in route handlers
|
|
20
|
+
req.currentUser = payload;
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
// JWT invalid or expired - silently continue without setting currentUser
|
|
24
|
+
}
|
|
25
|
+
next();
|
|
26
|
+
};
|
|
27
|
+
exports.currentUser = currentUser;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.errorHandler = void 0;
|
|
4
|
+
const custom_error_1 = require("../errors/custom-error");
|
|
5
|
+
// Global error handling middleware
|
|
6
|
+
// Catches all errors thrown in async route handlers (via express-async-errors)
|
|
7
|
+
// and formats them into consistent API responses
|
|
8
|
+
const errorHandler = (err, req, res, next) => {
|
|
9
|
+
// If error is one of our custom errors, use its status code and serialization
|
|
10
|
+
if (err instanceof custom_error_1.CustomError) {
|
|
11
|
+
return res.status(err.statusCode).send({ errors: err.serializeErrors() });
|
|
12
|
+
}
|
|
13
|
+
// For unexpected errors, return 400 with the error message
|
|
14
|
+
res.status(400).send({ message: err.message });
|
|
15
|
+
};
|
|
16
|
+
exports.errorHandler = errorHandler;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.requireAuth = void 0;
|
|
4
|
+
const not_authorized_error_1 = require("../errors/not-authorized-error");
|
|
5
|
+
// Middleware that requires user to be authenticated
|
|
6
|
+
// Must be used after currentUser middleware
|
|
7
|
+
// Throws 401 error if user is not logged in
|
|
8
|
+
const requireAuth = (req, res, next) => {
|
|
9
|
+
// If currentUser is not set, user is not authenticated
|
|
10
|
+
if (!req.currentUser) {
|
|
11
|
+
throw new not_authorized_error_1.NotAuthorizedError();
|
|
12
|
+
}
|
|
13
|
+
// User is authenticated - continue to route handler
|
|
14
|
+
next();
|
|
15
|
+
};
|
|
16
|
+
exports.requireAuth = requireAuth;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateRequest = void 0;
|
|
4
|
+
const express_validator_1 = require("express-validator");
|
|
5
|
+
const request_validation_error_1 = require("../errors/request-validation-error");
|
|
6
|
+
// Middleware that checks for validation errors from express-validator
|
|
7
|
+
// Used after validation rules are applied to request body/params
|
|
8
|
+
// Throws RequestValidationError if any validation rules failed
|
|
9
|
+
const validateRequest = (req, res, next) => {
|
|
10
|
+
// Extract validation errors from the request
|
|
11
|
+
const errors = (0, express_validator_1.validationResult)(req);
|
|
12
|
+
// If there are validation errors, throw custom error
|
|
13
|
+
if (!errors.isEmpty()) {
|
|
14
|
+
throw new request_validation_error_1.RequestValidationError(errors.array());
|
|
15
|
+
}
|
|
16
|
+
// No errors - continue to next middleware
|
|
17
|
+
next();
|
|
18
|
+
};
|
|
19
|
+
exports.validateRequest = validateRequest;
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@masonprotsman/common",
|
|
3
|
+
"version": "1.0.4",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "./build/index.js",
|
|
6
|
+
"types": "./build/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"build/**/*"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"clean": "del ./build/*",
|
|
12
|
+
"build": "npm run clean && tsc",
|
|
13
|
+
"pub": "git add . && git commit -m \"Updates\" && npm version patch && npm run build && npm publish --access public"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [],
|
|
16
|
+
"author": "",
|
|
17
|
+
"license": "ISC",
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"del-cli": "^5.1.0",
|
|
20
|
+
"typescript": "^5.6.2"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@types/cookie-session": "^2.0.49",
|
|
24
|
+
"@types/express": "^5.0.0",
|
|
25
|
+
"@types/jsonwebtoken": "^9.0.7",
|
|
26
|
+
"cookie-session": "^2.1.0",
|
|
27
|
+
"express": "^4.21.0",
|
|
28
|
+
"express-validator": "^7.2.0",
|
|
29
|
+
"jsonwebtoken": "^9.0.2"
|
|
30
|
+
}
|
|
31
|
+
}
|