{
  "slug": "validate-objectid",
  "runtimes": {
    "node": {
      "frameworks": {
        "express": {
          "dependencies": {
            "runtime": [
              "mongoose"
            ],
            "dev": []
          },
          "env": [],
          "architectures": {
            "mvc": {
              "files": [
                {
                  "type": "file",
                  "path": "src/utils/api-error.ts",
                  "content": "import { STATUS_CODES, StatusCode } from \"../constants/status-codes\";\r\n\r\nexport class ApiError extends Error {\r\n  public readonly statusCode: StatusCode;\r\n  public readonly isOperational: boolean;\r\n  public readonly errors?: unknown;\r\n\r\n  constructor(\r\n    statusCode: StatusCode,\r\n    message: string,\r\n    errors?: unknown,\r\n    isOperational = true\r\n  ) {\r\n    super(message);\r\n    this.name = \"ApiError\";\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\r\n  static badRequest(message = \"Bad Request\", errors?: unknown) {\r\n    return new ApiError(STATUS_CODES.BAD_REQUEST, message, errors);\r\n  }\r\n\r\n  static unauthorized(message = \"Unauthorized\") {\r\n    return new ApiError(STATUS_CODES.UNAUTHORIZED, message);\r\n  }\r\n\r\n  static forbidden(message = \"Forbidden\") {\r\n    return new ApiError(STATUS_CODES.FORBIDDEN, message);\r\n  }\r\n\r\n  static notFound(message = \"Not Found\") {\r\n    return new ApiError(STATUS_CODES.NOT_FOUND, message);\r\n  }\r\n\r\n  static conflict(message = \"Conflict\") {\r\n    return new ApiError(STATUS_CODES.CONFLICT, message);\r\n  }\r\n\r\n  static server(message = \"Internal Server Error\") {\r\n    return new ApiError(STATUS_CODES.INTERNAL_SERVER_ERROR, message);\r\n  }\r\n}\r\n\r\n/*\r\n  ? Usage:\r\n  * throw new ApiError(404, \"Not found\");\r\n  * throw ApiError.badRequest(\"Bad request\");\r\n */\r\n"
                },
                {
                  "type": "file",
                  "path": "src/middlewares/validate-id.ts",
                  "content": "import { isValidObjectId } from \"mongoose\";\r\nimport { ApiError } from \"../utils/api-error\";\r\nimport { NextFunction, Request, Response } from \"express\";\r\n\r\nexport const validateObjectId = (paramName: string = \"id\") => {\r\n  return (req: Request, res: Response, next: NextFunction) => {\r\n    const value =\r\n      req?.params[paramName] || req?.body[paramName] || req?.query[paramName];\r\n    if (!value) {\r\n      throw ApiError.badRequest(`${paramName} is required`);\r\n    }\r\n\r\n    if (!isValidObjectId(value)) {\r\n      throw ApiError.badRequest(`Invalid ${paramName}`);\r\n    }\r\n\r\n    next();\r\n  };\r\n};\r\n"
                },
                {
                  "type": "file",
                  "path": "src/constants/status-codes.ts",
                  "content": "export const STATUS_CODES = {\r\n  // 2xx Success\r\n  OK: 200,\r\n  CREATED: 201,\r\n  ACCEPTED: 202,\r\n  NO_CONTENT: 204,\r\n\r\n  // 3xx Redirection\r\n  MOVED_PERMANENTLY: 301,\r\n  FOUND: 302,\r\n  NOT_MODIFIED: 304,\r\n\r\n  // 4xx Client Errors\r\n  BAD_REQUEST: 400,\r\n  UNAUTHORIZED: 401,\r\n  FORBIDDEN: 403,\r\n  NOT_FOUND: 404,\r\n  CONFLICT: 409,\r\n  UNPROCESSABLE_ENTITY: 422,\r\n  TOO_MANY_REQUESTS: 429,\r\n\r\n  // 5xx Server Errors\r\n  INTERNAL_SERVER_ERROR: 500,\r\n  NOT_IMPLEMENTED: 501,\r\n  BAD_GATEWAY: 502,\r\n  SERVICE_UNAVAILABLE: 503,\r\n  GATEWAY_TIMEOUT: 504\r\n} as const;\r\n\r\nexport type StatusCode = (typeof STATUS_CODES)[keyof typeof STATUS_CODES];\r\n"
                }
              ]
            },
            "feature": {
              "files": [
                {
                  "type": "file",
                  "path": "src/shared/middlewares/validate-id.ts",
                  "content": "import { isValidObjectId } from \"mongoose\";\r\nimport { ApiError } from \"../errors/api-error\";\r\nimport { NextFunction, Request, Response } from \"express\";\r\n\r\nexport const validateObjectId = (paramName: string = \"id\") => {\r\n  return (req: Request, res: Response, next: NextFunction) => {\r\n    const value =\r\n      req?.params[paramName] || req?.body[paramName] || req?.query[paramName];\r\n    if (!value) {\r\n      throw ApiError.badRequest(`${paramName} is required`);\r\n    }\r\n\r\n    if (!isValidObjectId(value)) {\r\n      throw ApiError.badRequest(`Invalid ${paramName}`);\r\n    }\r\n\r\n    next();\r\n  };\r\n};\r\n"
                },
                {
                  "type": "file",
                  "path": "src/shared/errors/api-error.ts",
                  "content": "import { STATUS_CODES, StatusCode } from \"../constants/status-codes\";\r\n\r\nexport class ApiError extends Error {\r\n  public readonly statusCode: StatusCode;\r\n  public readonly isOperational: boolean;\r\n  public readonly errors?: unknown;\r\n\r\n  constructor(\r\n    statusCode: StatusCode,\r\n    message: string,\r\n    errors?: unknown,\r\n    isOperational = true\r\n  ) {\r\n    super(message);\r\n    this.name = \"ApiError\";\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\r\n  static badRequest(message = \"Bad Request\", errors?: unknown) {\r\n    return new ApiError(STATUS_CODES.BAD_REQUEST, message, errors);\r\n  }\r\n\r\n  static unauthorized(message = \"Unauthorized\") {\r\n    return new ApiError(STATUS_CODES.UNAUTHORIZED, message);\r\n  }\r\n\r\n  static forbidden(message = \"Forbidden\") {\r\n    return new ApiError(STATUS_CODES.FORBIDDEN, message);\r\n  }\r\n\r\n  static notFound(message = \"Not Found\") {\r\n    return new ApiError(STATUS_CODES.NOT_FOUND, message);\r\n  }\r\n\r\n  static conflict(message = \"Conflict\") {\r\n    return new ApiError(STATUS_CODES.CONFLICT, message);\r\n  }\r\n\r\n  static server(message = \"Internal Server Error\") {\r\n    return new ApiError(STATUS_CODES.INTERNAL_SERVER_ERROR, message);\r\n  }\r\n}\r\n\r\n/*\r\n  ? Usage:\r\n  * throw new ApiError(404, \"Not found\");\r\n  * throw ApiError.badRequest(\"Bad request\");\r\n */\r\n"
                },
                {
                  "type": "file",
                  "path": "src/shared/constants/status-codes.ts",
                  "content": "export const STATUS_CODES = {\r\n  // 2xx Success\r\n  OK: 200,\r\n  CREATED: 201,\r\n  ACCEPTED: 202,\r\n  NO_CONTENT: 204,\r\n\r\n  // 3xx Redirection\r\n  MOVED_PERMANENTLY: 301,\r\n  FOUND: 302,\r\n  NOT_MODIFIED: 304,\r\n\r\n  // 4xx Client Errors\r\n  BAD_REQUEST: 400,\r\n  UNAUTHORIZED: 401,\r\n  FORBIDDEN: 403,\r\n  NOT_FOUND: 404,\r\n  CONFLICT: 409,\r\n  UNPROCESSABLE_ENTITY: 422,\r\n  TOO_MANY_REQUESTS: 429,\r\n\r\n  // 5xx Server Errors\r\n  INTERNAL_SERVER_ERROR: 500,\r\n  NOT_IMPLEMENTED: 501,\r\n  BAD_GATEWAY: 502,\r\n  SERVICE_UNAVAILABLE: 503,\r\n  GATEWAY_TIMEOUT: 504\r\n} as const;\r\n\r\nexport type StatusCode = (typeof STATUS_CODES)[keyof typeof STATUS_CODES];\r\n"
                }
              ]
            }
          }
        }
      }
    }
  }
}
