@xylabs/express 6.1.3 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,8 @@
1
1
  import type { Express } from 'express-serve-static-core';
2
2
  import type { RouteDefinition } from './RouteDefinition.ts';
3
3
  /**
4
- * Registers an array of route definitions on an Express application.
5
- * @param app The Express application to register routes on.
4
+ * Registers an array of route definitions on an Express app.
5
+ * @param app The Express app to register routes on.
6
6
  * @param routeDefinitions The route definitions to register.
7
7
  */
8
8
  export declare const addRouteDefinitions: (app: Express, routeDefinitions: RouteDefinition[]) => void;
@@ -4,7 +4,7 @@ import type { NextFunction, ParamsDictionary, Query, Request, RequestHandler, Re
4
4
  * @param fn The async request handler to wrap.
5
5
  * @returns A request handler that catches async errors and passes them to next().
6
6
  */
7
- export declare function asyncHandler<P = NoReqParams, ResBody = NoResBody, ReqBody = NoReqBody, ReqQuery = NoReqQuery, Locals extends NoLocals = NoLocals>(fn: RequestHandler<P, ResBody, ReqBody, ReqQuery, Locals>): (req: Request<P, ResBody, ReqBody, ReqQuery, Locals>, res: Response<ResBody, Locals>, next: NextFunction) => Promise<unknown>;
7
+ export declare function asyncHandler<P = NoReqParams, ResBody = NoResBody, ReqBody = NoReqBody, ReqQuery = NoReqQuery, Locals extends NoLocals = NoLocals>(fn: RequestHandler<P, ResBody, ReqBody, ReqQuery, Locals>): (req: Request<P, ResBody, ReqBody, ReqQuery, Locals>, res: Response<ResBody, Locals>, next: NextFunction) => Promise<void>;
8
8
  /** Empty object type used as a default for request/response body generics. */
9
9
  export interface Empty {
10
10
  }
@@ -1 +1 @@
1
- {"version":3,"file":"asyncHandler.d.ts","sourceRoot":"","sources":["../../../src/Handler/asyncHandler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EAAE,gBAAgB,EAAE,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EACzE,MAAM,2BAA2B,CAAA;AAElC;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,CAAC,GAAG,WAAW,EAAE,OAAO,GAAG,SAAS,EAAE,OAAO,GAAG,SAAS,EAAE,QAAQ,GAAG,UAAU,EAAE,MAAM,SAAS,QAAQ,GAAG,QAAQ,EAC/I,EAAE,EAAE,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,IAEjD,KAAK,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,KAAK,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,YAAY,sBAGhH;AAED,8EAA8E;AAC9E,MAAM,WAAW,KAAK;CAAG;AAEzB,iDAAiD;AACjD,MAAM,MAAM,WAAW,GAAG,gBAAgB,CAAA;AAC1C,6DAA6D;AAC7D,MAAM,MAAM,SAAS,GAAG,KAAK,CAAA;AAC7B,4DAA4D;AAC5D,MAAM,MAAM,SAAS,GAAG,KAAK,CAAA;AAC7B,iDAAiD;AACjD,MAAM,MAAM,UAAU,GAAG,KAAK,CAAA;AAC9B,wCAAwC;AAExC,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA"}
1
+ {"version":3,"file":"asyncHandler.d.ts","sourceRoot":"","sources":["../../../src/Handler/asyncHandler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EAAE,gBAAgB,EAAE,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EACzE,MAAM,2BAA2B,CAAA;AAElC;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,CAAC,GAAG,WAAW,EAAE,OAAO,GAAG,SAAS,EAAE,OAAO,GAAG,SAAS,EAAE,QAAQ,GAAG,UAAU,EAAE,MAAM,SAAS,QAAQ,GAAG,QAAQ,EAC/I,EAAE,EAAE,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,IAE3C,KAAK,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,KAAK,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,YAAY,mBAOtH;AAED,8EAA8E;AAC9E,MAAM,WAAW,KAAK;CAAG;AAEzB,iDAAiD;AACjD,MAAM,MAAM,WAAW,GAAG,gBAAgB,CAAA;AAC1C,6DAA6D;AAC7D,MAAM,MAAM,SAAS,GAAG,KAAK,CAAA;AAC7B,4DAA4D;AAC5D,MAAM,MAAM,SAAS,GAAG,KAAK,CAAA;AAC7B,iDAAiD;AACjD,MAAM,MAAM,UAAU,GAAG,KAAK,CAAA;AAC9B,wCAAwC;AAExC,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Follows NPM log levels
2
+ * Follows npm log levels
3
3
  * https://docs.npmjs.com/cli/v8/using-npm/logging#loglevel
4
4
  */
5
5
  export type WinstonVerbosity = 'error' | 'warn' | 'info' | 'http' | 'verbose' | 'debug' | 'silly';
@@ -1 +1 @@
1
- {"version":3,"file":"getDefaultLogger.d.ts","sourceRoot":"","sources":["../../../src/Logger/getDefaultLogger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAG5C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AAErE;;;GAGG;AAEH,OAAO,CAAC,MAAM,CAAC;IACb,IAAI,EAAE,EAAE;QACN,aAAa,CAAC,EAAE,oBAAoB,CAAA;KACrC,CAAA;CACF;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,QAAO,MAInC,CAAA"}
1
+ {"version":3,"file":"getDefaultLogger.d.ts","sourceRoot":"","sources":["../../../src/Logger/getDefaultLogger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAG5C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AAErE;;;GAGG;AAEH,OAAO,CAAC,MAAM,CAAC;IACb,IAAI,EAAE,EAAE;QACN,aAAa,CAAC,EAAE,oBAAoB,CAAA;KACrC,CAAA;CACF;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,QAAO,MAMnC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"requestHandlerValidator.d.ts","sourceRoot":"","sources":["../../../src/Validation/requestHandlerValidator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAChD,MAAM,2BAA2B,CAAA;AAClC,OAAO,KAAK,CAAC,MAAM,UAAU,CAAA;AAK7B;;GAEG;AACH,eAAO,MAAM,cAAc,gEAAuC,CAAA;AAElE;;GAEG;AACH,eAAO,MAAM,mBAAmB,oIAAuE,CAAA;AAEvG;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;;CAKnC,CAAA;AAID;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,SAAS,OAAO,mBAAmB,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,OAAO,mBAAmB,EACjH,MAAM,SAAS,OAAO,mBAAmB,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC,GAAG,OAAO,mBAAmB,EAC3H,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EACjE,SAAS,SAAS,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EACrE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,KAAK,CAAA;IACX,MAAM,EAAE,OAAO,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,SAAS,CAAA;CACpB,CAAC,IAOQ,SAAS,CAAC,GAAG,EAAE,OAAO,+FAA0B,EAAE,GAAG,EAAE,QAAQ,0BAAK,EAAE,IAAI,EAAE,YAAY,KAAK,OAAO,KAAG,cAAc,CAoE9H"}
1
+ {"version":3,"file":"requestHandlerValidator.d.ts","sourceRoot":"","sources":["../../../src/Validation/requestHandlerValidator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAChD,MAAM,2BAA2B,CAAA;AAClC,OAAO,KAAK,CAAC,MAAM,UAAU,CAAA;AAiB7B;;GAEG;AACH,eAAO,MAAM,cAAc,gEAAuC,CAAA;AAElE;;GAEG;AACH,eAAO,MAAM,mBAAmB,oIAAuE,CAAA;AAEvG;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;;CAKnC,CAAA;AAID;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,SAAS,OAAO,mBAAmB,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,OAAO,mBAAmB,EACjH,MAAM,SAAS,OAAO,mBAAmB,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC,GAAG,OAAO,mBAAmB,EAC3H,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EACjE,SAAS,SAAS,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EACrE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,KAAK,CAAA;IACX,MAAM,EAAE,OAAO,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,SAAS,CAAA;CACpB,CAAC,IAOQ,SAAS,CAAC,GAAG,EAAE,OAAO,+FAA0B,EAAE,GAAG,EAAE,QAAQ,0BAAK,EAAE,IAAI,EAAE,YAAY,KAAK,OAAO,KAAG,cAAc,CA+D9H"}
@@ -1,7 +1,11 @@
1
1
  // src/Handler/asyncHandler.ts
2
2
  function asyncHandler(fn) {
3
- return (req, res, next) => {
4
- return Promise.resolve(fn(req, res, next)).catch(next);
3
+ return async (req, res, next) => {
4
+ try {
5
+ await fn(req, res, next);
6
+ } catch (error) {
7
+ next(error);
8
+ }
5
9
  };
6
10
  }
7
11
 
@@ -22,7 +26,7 @@ var {
22
26
  var logFormatLocalDev = combine(
23
27
  colorize(),
24
28
  timestamp(),
25
- printf((info) => `[${String(info.timestamp)} ${String(info.level)}] ${String(info.message)}`)
29
+ printf((info) => `[${String(info.timestamp)} ${info.level}] ${String(info.message)}`)
26
30
  );
27
31
 
28
32
  // src/Logger/LogFormats/Rollbar/logFormatRollbar.ts
@@ -94,8 +98,8 @@ var WrappedWinstonLogger = class {
94
98
  };
95
99
 
96
100
  // src/Logger/getLogger.ts
97
- var exitOnError = false;
98
- var handleRejections = true;
101
+ var isExitOnError = false;
102
+ var isHandleRejections = true;
99
103
  var { Console } = winstonTransports;
100
104
  var consoleTransport = new Console();
101
105
  var format4 = process.env.NODE_ENV === "development" ? logFormatLocalDev : logFormatStructured;
@@ -122,9 +126,9 @@ var getLogger = (minVerbosity = "info") => {
122
126
  if (existing) return existing;
123
127
  const logger = new WrappedWinstonLogger(
124
128
  createLogger({
125
- exitOnError,
129
+ exitOnError: isExitOnError,
126
130
  format: format4,
127
- handleRejections,
131
+ handleRejections: isHandleRejections,
128
132
  level,
129
133
  rejectionHandlers: transports,
130
134
  transports
@@ -136,7 +140,9 @@ var getLogger = (minVerbosity = "info") => {
136
140
 
137
141
  // src/Logger/getDefaultLogger.ts
138
142
  var getDefaultLogger = () => {
139
- globalThis.xy ??= {};
143
+ if (globalThis.xy === void 0) {
144
+ Reflect.set(globalThis, "xy", {});
145
+ }
140
146
  if (globalThis.xy.defaultLogger) return globalThis.xy.defaultLogger;
141
147
  return getLogger();
142
148
  };
@@ -326,10 +332,10 @@ var standardErrors = (err, req, res, next) => {
326
332
  return;
327
333
  }
328
334
  getDefaultLogger().error(err.message);
329
- err.statusCode = err.statusCode ?? 500;
335
+ err.statusCode ??= 500;
330
336
  const error = {
331
337
  detail: err.message,
332
- status: `${err.statusCode}`,
338
+ status: String(err.statusCode),
333
339
  title: err.name
334
340
  };
335
341
  res.status(err.statusCode).json(error);
@@ -344,7 +350,7 @@ var clearRawResponseFormat = (res) => {
344
350
  res.locals.rawResponse = false;
345
351
  };
346
352
  var isRawResponseFormatSet = (res) => {
347
- return res.locals.rawResponse ? true : false;
353
+ return res.locals.rawResponse === true;
348
354
  };
349
355
  var transformResponse = (body, _req, res) => {
350
356
  return isRawResponseFormatSet(res) ? body : res.statusCode >= 200 && res.statusCode < 300 ? { data: body, meta: getResponseMetadata(res) } : { error: body, meta: getResponseMetadata(res) };
@@ -365,9 +371,9 @@ var standardResponses = (req, res, next) => {
365
371
  // src/Util/compactObject.ts
366
372
  var compactObject = (obj) => {
367
373
  const result = {};
368
- for (const key in obj) {
369
- if (obj[key] !== void 0 && obj[key] !== null) {
370
- result[key] = obj[key];
374
+ for (const [key, value] of Object.entries(obj)) {
375
+ if (value !== void 0 && value !== null) {
376
+ result[key] = value;
371
377
  }
372
378
  }
373
379
  return result;
@@ -389,6 +395,17 @@ var tryParse = (func, value) => {
389
395
  // src/Validation/requestHandlerValidator.ts
390
396
  import { isDefined as isDefined3, isPromise } from "@xylabs/typeof";
391
397
  import * as z from "zod/mini";
398
+ var createExpressError = (message, errorName, statusCode) => {
399
+ const error = new Error(message);
400
+ Object.defineProperty(error, "name", {
401
+ configurable: true,
402
+ enumerable: false,
403
+ value: errorName,
404
+ writable: true
405
+ });
406
+ error.statusCode = statusCode;
407
+ return error;
408
+ };
392
409
  var EmptyParamsZod = z.catchall(z.object({}), z.string());
393
410
  var EmptyQueryParamsZod = z.catchall(z.object({}), z.union([z.string(), z.array(z.string())]));
394
411
  var ValidateRequestDefaults = {
@@ -420,9 +437,7 @@ function requestHandlerValidator(schemas) {
420
437
  }
421
438
  if (errors.length > 0) {
422
439
  const message = errors.join("; ");
423
- const err = new Error(message);
424
- err.name = ReasonPhrases.BAD_REQUEST;
425
- err.statusCode = StatusCodes.BAD_REQUEST;
440
+ const err = createExpressError(message, ReasonPhrases.BAD_REQUEST, StatusCodes.BAD_REQUEST);
426
441
  next(err);
427
442
  return false;
428
443
  }
@@ -430,16 +445,13 @@ function requestHandlerValidator(schemas) {
430
445
  const result2 = z.safeParse(validators.response, data);
431
446
  if (result2.success) {
432
447
  return originalJson(result2.data);
433
- } else {
434
- const message = result2.error.issues.map(
435
- (issue) => issue.path.length === 0 ? `response: ${issue.message}` : `response.${issue.path.join(".")}: ${issue.message}`
436
- ).join("; ");
437
- const err = new Error(message);
438
- err.name = ReasonPhrases.INTERNAL_SERVER_ERROR;
439
- err.statusCode = StatusCodes.INTERNAL_SERVER_ERROR;
440
- res.json = originalJson;
441
- throw err;
442
448
  }
449
+ const message = result2.error.issues.map(
450
+ (issue) => issue.path.length === 0 ? `response: ${issue.message}` : `response.${issue.path.join(".")}: ${issue.message}`
451
+ ).join("; ");
452
+ const err = createExpressError(message, ReasonPhrases.INTERNAL_SERVER_ERROR, StatusCodes.INTERNAL_SERVER_ERROR);
453
+ res.json = originalJson;
454
+ throw err;
443
455
  };
444
456
  const typedReq = req;
445
457
  const typedRes = res;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/Handler/asyncHandler.ts", "../../src/Handler/errorToJsonHandler.ts", "../../src/Logger/getLogger.ts", "../../src/Logger/LogFormats/LocalDev/logFormatLocalDev.ts", "../../src/Logger/LogFormats/Rollbar/logFormatRollbar.ts", "../../src/Logger/LogFormats/Structured/logFormatStructured.ts", "../../src/Logger/toWinstonVerbosity.ts", "../../src/Logger/Transports/Rollbar/canGetDefaultRollbarTransport.ts", "../../src/Logger/Transports/Rollbar/getDefaultRollbarTransport.ts", "../../src/Logger/Transports/Rollbar/RollbarTransport.ts", "../../src/Logger/WrappedWinstonLogger.ts", "../../src/Logger/getDefaultLogger.ts", "../../src/Handler/RouteDefinition/addRouteDefinitions.ts", "../../src/HttpStatus.ts", "../../src/Handler/StatusCodeHandlers/notImplemented.ts", "../../src/HttpUtil/getHttpHeader.ts", "../../src/middleware/caseInsensitiveRouting/caseInsensitiveRouting.ts", "../../src/middleware/customPoweredByHeader/customPoweredByHeader.ts", "../../src/middleware/jsonBodyParser/jsonBodyParser.ts", "../../src/Performance/Counters.ts", "../../src/Performance/Profiler.ts", "../../src/middleware/metrics/counters.ts", "../../src/middleware/metrics/responseProfiler.ts", "../../src/middleware/standardResponses/getResponseMetadata.ts", "../../src/middleware/standardResponses/standardErrors.ts", "../../src/middleware/standardResponses/standardResponses.ts", "../../src/Util/compactObject.ts", "../../src/Util/tryParse.ts", "../../src/Validation/requestHandlerValidator.ts"],
4
- "sourcesContent": ["import type {\n NextFunction, ParamsDictionary, Query, Request, RequestHandler, Response,\n} from 'express-serve-static-core'\n\n/**\n * Wraps an async Express request handler to forward rejected promises to the error handler.\n * @param fn The async request handler to wrap.\n * @returns A request handler that catches async errors and passes them to next().\n */\nexport function asyncHandler<P = NoReqParams, ResBody = NoResBody, ReqBody = NoReqBody, ReqQuery = NoReqQuery, Locals extends NoLocals = NoLocals>(\n fn: RequestHandler<P, ResBody, ReqBody, ReqQuery, Locals>,\n) {\n return (req: Request<P, ResBody, ReqBody, ReqQuery, Locals>, res: Response<ResBody, Locals>, next: NextFunction) => {\n return Promise.resolve(fn(req, res, next)).catch(next)\n }\n}\n\n/** Empty object type used as a default for request/response body generics. */\nexport interface Empty {}\n\n/** Default type for request route parameters. */\nexport type NoReqParams = ParamsDictionary\n/** Default type for response body when none is specified. */\nexport type NoResBody = Empty\n/** Default type for request body when none is specified. */\nexport type NoReqBody = Empty\n/** Default type for request query parameters. */\nexport type NoReqQuery = Query\n/** Default type for response locals. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type NoLocals = Record<string, any>\n", "import { isError, isNumber } from '@xylabs/typeof'\nimport type {\n NextFunction, Request, Response,\n} from 'express-serve-static-core'\n\nimport { getDefaultLogger } from '../Logger/index.ts'\nimport type { ExpressError } from '../Model/index.ts'\n\n/**\n * Express error handler that logs the error and sends a JSON response with the error message and status code.\n * @param error The Express error to handle.\n * @param req The incoming request.\n * @param res The outgoing response.\n * @param next The next middleware function.\n */\nexport const errorToJsonHandler = (error: ExpressError, req: Request, res: Response, next: NextFunction) => {\n if (isError(error)) {\n getDefaultLogger().error(error.message)\n if (!isNumber(error.statusCode)) error.statusCode = 500\n res.status(error.statusCode).send({ error: error.message })\n }\n next(error)\n}\n", "import type { Logger } from '@xylabs/logger'\nimport { createLogger, transports as winstonTransports } from 'winston'\nimport type TransportStream from 'winston-transport'\n\nimport { logFormatLocalDev, logFormatStructured } from './LogFormats/index.ts'\nimport type { LoggerVerbosity } from './LoggerVerbosity.ts'\nimport { toWinstonVerbosity } from './toWinstonVerbosity.ts'\nimport { canGetDefaultRollbarTransport, getDefaultRollbarTransport } from './Transports/index.ts'\nimport type { WinstonVerbosity } from './WinstonVerbosity.ts'\nimport { WrappedWinstonLogger } from './WrappedWinstonLogger.ts'\n\nconst exitOnError = false\nconst handleRejections = true\n\nconst { Console } = winstonTransports\nconst consoleTransport = new Console()\nconst format = process.env.NODE_ENV === 'development' ? logFormatLocalDev : logFormatStructured\nconst transports: TransportStream[] = [consoleTransport]\nif (canGetDefaultRollbarTransport(process.env)) {\n try {\n const rollbarTransport = getDefaultRollbarTransport(process.env)\n transports.push(rollbarTransport)\n } catch {\n // NOTE: No error here, just gracefully adding logger if ENV VARs\n // were preset\n }\n}\n\nconst loggers: Record<WinstonVerbosity, Logger | undefined> = {\n debug: undefined,\n error: undefined,\n http: undefined,\n info: undefined,\n silly: undefined,\n verbose: undefined,\n warn: undefined,\n}\n\n/**\n * Returns a cached Winston-backed logger at the specified verbosity level.\n * @param minVerbosity The minimum log level to output. Defaults to 'info'.\n * @returns A logger instance configured for the given verbosity.\n */\nexport const getLogger = (minVerbosity: LoggerVerbosity = 'info'): Logger => {\n const level = toWinstonVerbosity(minVerbosity)\n const existing = loggers[level]\n if (existing) return existing\n const logger = new WrappedWinstonLogger(\n createLogger({\n exitOnError,\n format,\n handleRejections,\n level,\n rejectionHandlers: transports,\n transports,\n }),\n )\n loggers[level] = logger\n return logger\n}\n", "import type { Logform } from 'winston'\nimport { format } from 'winston'\n\nconst {\n colorize, combine, timestamp, printf,\n} = format\n\n/** Winston log format for local development with colorized output and timestamps. */\nexport const logFormatLocalDev: Logform.Format = combine(\n colorize(),\n timestamp(),\n printf(info => `[${String(info.timestamp)} ${String(info.level)}] ${String(info.message)}`),\n)\n", "import type { Logform } from 'winston'\nimport { format } from 'winston'\n\nconst { simple } = format\n\n/** Winston log format for Rollbar using simple text output. */\nexport const logFormatRollbar: Logform.Format = simple()\n", "import type { Logform } from 'winston'\nimport { format } from 'winston'\n\nconst {\n combine, timestamp, json,\n} = format\n\n/** Winston log format for production with structured JSON output and timestamps. */\nexport const logFormatStructured: Logform.Format = combine(timestamp(), json())\n", "import type { LoggerVerbosity } from './LoggerVerbosity.ts'\nimport type { WinstonVerbosity } from './WinstonVerbosity.ts'\n\n/**\n * Converts a LoggerVerbosity level to the corresponding Winston log level.\n * @param loggerVerbosity The application-level verbosity to convert.\n * @returns The equivalent Winston verbosity level.\n */\nexport const toWinstonVerbosity = (loggerVerbosity: LoggerVerbosity): WinstonVerbosity => {\n return loggerVerbosity === 'all' ? 'silly' : loggerVerbosity\n}\n", "/**\n * Checks whether the ROLLBAR_ACCESS_TOKEN environment variable is set.\n * @param env The environment variables to check.\n * @returns True if the Rollbar access token is available.\n */\nexport const canGetDefaultRollbarTransport = (env: Record<string, string | undefined>): boolean => {\n return env.ROLLBAR_ACCESS_TOKEN === undefined ? false : true\n}\n", "import { assertEx } from '@xylabs/assert'\nimport Rollbar from 'rollbar'\n\nimport { RollbarTransport } from './RollbarTransport.ts'\n\n/**\n * Creates a RollbarTransport using the ROLLBAR_ACCESS_TOKEN from the environment.\n * @param env The environment variables containing the Rollbar access token.\n * @returns A configured RollbarTransport instance.\n */\nexport const getDefaultRollbarTransport = (env: Record<string, string | undefined>): RollbarTransport => {\n const accessToken = assertEx(env.ROLLBAR_ACCESS_TOKEN, () => 'Missing ROLLBAR_ACCESS_TOKEN ENV VAR')\n const rollbar: Rollbar = new Rollbar({ accessToken })\n return new RollbarTransport({}, rollbar)\n}\n", "import type Rollbar from 'rollbar'\nimport type { TransportStreamOptions } from 'winston-transport'\nimport Transport from 'winston-transport'\n\nimport { logFormatRollbar } from '../../LogFormats/index.ts'\n\n/** Winston transport that forwards error-level log messages to Rollbar. */\nexport class RollbarTransport extends Transport {\n protected readonly rollbar?: Rollbar\n constructor(\n opts: TransportStreamOptions,\n rollbar?: Rollbar,\n ) {\n super({\n ...opts, format: logFormatRollbar, level: 'error',\n })\n this.rollbar = rollbar\n }\n\n override log(info: { message?: string }, next: () => void) {\n this.rollbar?.error(info?.message)\n this.emit('logged', info?.message)\n next()\n }\n}\n", "import type { LogFunction, Logger } from '@xylabs/logger'\nimport type { Logger as Winston } from 'winston'\n\n/**\n * Wrap Winston logger methods to adapt to familiar\n * console logging methods\n */\nexport class WrappedWinstonLogger implements Logger {\n protected readonly winston: Winston\n constructor(winston: Winston) {\n this.winston = winston\n }\n\n debug: LogFunction = message => this.winston.debug(message)\n error: LogFunction = message => this.winston.error(message)\n info: LogFunction = message => this.winston.info(message)\n log: LogFunction = message => this.winston.info(message)\n trace: LogFunction = message => this.winston.debug(message)\n warn: LogFunction = message => this.winston.warn(message)\n}\n", "import type { Logger } from '@xylabs/logger'\n\nimport { getLogger } from './getLogger.ts'\nimport type { WrappedWinstonLogger } from './WrappedWinstonLogger.ts'\n\n/**\n * Static instance to prevent multiple instances of the same logger\n * with the same config\n */\n\ndeclare global {\n var xy: {\n defaultLogger?: WrappedWinstonLogger\n }\n}\n\n/**\n * Returns the singleton default logger instance, creating one if it does not exist.\n * @returns The default logger.\n */\nexport const getDefaultLogger = (): Logger => {\n globalThis.xy ??= {}\n if (globalThis.xy.defaultLogger) return globalThis.xy.defaultLogger\n return getLogger()\n}\n", "import type { Express } from 'express-serve-static-core'\n\nimport type { RouteDefinition } from './RouteDefinition.ts'\n\n/**\n * Registers an array of route definitions on an Express application.\n * @param app The Express application to register routes on.\n * @param routeDefinitions The route definitions to register.\n */\nexport const addRouteDefinitions = (app: Express, routeDefinitions: RouteDefinition[]) => {\n for (const definition of routeDefinitions) {\n app[definition.method](definition.path, definition.handlers)\n }\n}\n", "export const ReasonPhrases = {\n BAD_REQUEST: 'Bad Request',\n INTERNAL_SERVER_ERROR: 'Internal Server Error',\n NOT_IMPLEMENTED: 'Not Implemented',\n} as const\n\nexport const StatusCodes = {\n BAD_REQUEST: 400,\n INTERNAL_SERVER_ERROR: 500,\n NOT_IMPLEMENTED: 501,\n} as const\n", "import type { RequestHandler } from 'express-serve-static-core'\n\nimport { ReasonPhrases, StatusCodes } from '../../HttpStatus.ts'\n\n/** Express request handler that responds with a 501 Not Implemented error. */\nexport const notImplemented: RequestHandler = (_req, _res, next) => {\n next({ message: ReasonPhrases.NOT_IMPLEMENTED, statusCode: StatusCodes.NOT_IMPLEMENTED })\n}\n", "import { isDefined } from '@xylabs/typeof'\nimport type { Request } from 'express-serve-static-core'\n\n/**\n * Since there can be multiple of certain HTTP headers or\n * to prevent ugliness if someone did send us multiple\n * instances of a header we only expect one of, this\n * method grabs the 1st/only one of the desired header\n * @param header The header to find\n * @param req The received HTTP request (with headers)\n * @returns The first or only occurrence of the specified HTTP header\n */\nexport const getHttpHeader = (header: string, req: Request): string | undefined => {\n const headerValue = req.headers[header]\n const value\n // If the header exists\n = isDefined(headerValue)\n // If there's multiple of the same header\n ? Array.isArray(headerValue)\n // Grab the first one\n ? (headerValue).shift()\n // Otherwise grab the only one\n : (headerValue)\n // Otherwise undefined\n : undefined\n return value\n}\n", "import type { Express } from 'express-serve-static-core'\n\nconst setting = 'case sensitive routing'\n\n/**\n * Enable case sensitivity. When enabled, \"/Foo\" and \"/foo\" are different\n * routes. When disabled, \"/Foo\" and \"/foo\" are treated the same.\n * @param app The Express app to disable the header on.\n */\nexport const enableCaseSensitiveRouting = (app: Express) => {\n app.enable(setting)\n}\n\n/**\n * Disable case sensitivity. When enabled, \"/Foo\" and \"/foo\" are different\n * routes. When disabled, \"/Foo\" and \"/foo\" are treated the same.\n * @param app The Express app to disable the header on.\n */\nexport const disableCaseSensitiveRouting = (app: Express) => {\n app.disable(setting)\n}\n", "import type {\n Express, NextFunction, Request, Response,\n} from 'express-serve-static-core'\n\nconst header = 'X-Powered-By'\nconst setting = 'x-powered-by'\n\n/**\n * By default Express appends the `X-Powered-By: Express` header to\n * all responses. Calling this method enables that behavior.\n * @param app The Express app to disable the header on.\n */\nexport const enableExpressDefaultPoweredByHeader = (app: Express) => {\n app.enable(setting)\n}\n\n/**\n * By default Express appends the `X-Powered-By: Express` header to\n * all responses. Calling this method disables that behavior.\n * @param app The Express app to disable the header on.\n */\nexport const disableExpressDefaultPoweredByHeader = (app: Express) => {\n app.disable(setting)\n}\n\n/** Express middleware that sets the X-Powered-By header to 'XYO'. */\nexport const customPoweredByHeader = (req: Request, res: Response, next: NextFunction) => {\n res.setHeader(header, 'XYO')\n next()\n}\n", "import type { OptionsJson } from 'body-parser'\nimport bodyParser from 'body-parser'\nimport type { NextHandleFunction } from 'connect'\n\nimport { getDefaultLogger } from '../../Logger/index.ts'\n\n/**\n * The default maximum request body size for the JSON Body Parser\n */\nexport const DefaultJsonBodyParserOptionsLimit = '100kb'\n\n/**\n * The default MIME types for the JSON Body Parser\n */\nexport const DefaultJsonBodyParserOptionsTypes = ['application/json', 'text/json']\n\n/**\n * The default options for the JSON Body Parser\n */\nexport const DefaultJsonBodyParserOptions: OptionsJson = {\n limit: DefaultJsonBodyParserOptionsLimit,\n type: DefaultJsonBodyParserOptionsTypes,\n}\n\n/**\n * Gets the default JSON Body Parser options merged with the supplied options\n * with the supplied options taking precedence\n * @param options The options to override the default JSON Body Parser options with\n * @returns The combined JSON Body Parser options with the supplied values taking\n * precedence over the default\n */\nexport const getJsonBodyParserOptions = (options?: Partial<OptionsJson>): OptionsJson => {\n return options ? { ...DefaultJsonBodyParserOptions, ...options } : DefaultJsonBodyParserOptions\n}\n\n/**\n * Get a JSON Body Parser connect middleware handler\n * @param options The options for the JSON Body Parser\n * @returns A middleware function that parses JSON bodies\n */\nexport const getJsonBodyParser = (options: OptionsJson = DefaultJsonBodyParserOptions): NextHandleFunction => {\n // Create closed instance of bodyParser to prevent instantiation of new instance on every request\n const parser = bodyParser.json(options)\n\n return (req, res, next) => {\n // If we do not trap this error, then it dumps too much to log, usually happens if request aborted\n try {\n parser(req, res, next)\n } catch (ex) {\n const error = ex as Error\n getDefaultLogger().log(`bodyParser failed [${error?.name}]: ${error?.message}`)\n }\n }\n}\n\n/**\n * A JSON Body Parser middleware handler initialized with the default options\n */\nexport const jsonBodyParser = getJsonBodyParser()\n", "/** Static counter registry for tracking named numeric metrics. */\nexport class Counters {\n static counters: Record<string, number> = {}\n\n static inc(name: string, count = 1) {\n this.catchError(name, (name: string) => {\n this.counters[name] = (this.counters[name] ?? 0) + count\n })\n }\n\n static max(name: string, count: number) {\n this.catchError(name, (name: string) => {\n const currentValue = this.counters[name]\n if (currentValue === undefined || count > currentValue) {\n this.counters[name] = count\n }\n })\n }\n\n static min(name: string, count: number) {\n this.catchError(name, (name: string) => {\n const currentValue = this.counters[name]\n if (currentValue === undefined || count < currentValue) {\n this.counters[name] = count\n }\n })\n }\n\n private static catchError = (name: string, func: (name: string) => void) => {\n try {\n func(name)\n } catch {\n this.counters[name] = 0\n this.inc('CountersErrors')\n }\n }\n}\n", "/** Measures and records the execution duration of async operations by name. */\nexport class Profiler {\n stats: Record<string, number> = {}\n\n async profile<T>(name: string, promise: Promise<T>) {\n const start = Date.now()\n const result = await promise\n this.stats[name] = Date.now() - start\n return result\n }\n}\n", "import type {\n Application, NextFunction, Request, Response,\n} from 'express-serve-static-core'\n\nimport { Counters } from '../../Performance/index.ts'\n\n/**\n * Registers middleware that increments per-path request counters and exposes a /stats endpoint.\n * @param app The Express application to attach counters to.\n */\nexport const useRequestCounters = (app: Application): void => {\n // Configure Global counters\n app.use((req: Request, res: Response, next: NextFunction) => {\n Counters.inc(req.path)\n Counters.inc('_calls')\n next()\n })\n\n app.get('/stats', (req: Request, res: Response, next: NextFunction) => {\n /* #swagger.tags = ['Metrics'] */\n /* #swagger.summary = 'Get the counters for single instance of diviner' */\n res.json({\n alive: true,\n avgTime: `${((Counters.counters._totalTime ?? 0) / (Counters.counters._calls ?? 1)).toFixed(2)}ms`,\n counters: Counters.counters,\n })\n next()\n })\n}\n", "import type {\n NextFunction, Request, Response,\n} from 'express-serve-static-core'\n\ninterface ResponseProfile {\n startTime: number\n}\n\ninterface ResponseMetadata extends Record<string, unknown> {\n profile?: ResponseProfile\n}\n\ninterface ResponseLocals {\n meta?: ResponseMetadata\n}\n\n/**\n * Connect middleware to enable profiling of response lifecycle timing. To effectively profile\n * the response timing, this middleware needs to be called first when initializing your Express\n * App\n * @example\n * const app = express()\n * app.use(responseProfiler)\n * // other initialization ...\n * @param _req The request\n * @param res The response\n * @param next The next function\n */\nexport const responseProfiler = (_req: Request, res: Response<unknown, ResponseLocals>, next: NextFunction) => {\n res.locals.meta ??= {}\n res.locals.meta.profile = { startTime: Date.now() }\n next()\n}\n", "import type { Response } from 'express-serve-static-core'\n\nexport interface ResponseProfile {\n duration?: number\n endTime?: number\n startTime?: number\n}\n\nexport interface ResponseMetadata extends Record<string, unknown> {\n profile?: ResponseProfile\n}\n\nexport interface ResponseLocals extends Record<string, unknown> {\n meta?: ResponseMetadata\n}\n\n/**\n * Extracts response metadata from res.locals, computing profile duration if profiling was started.\n * @param res The Express response to extract metadata from.\n * @returns The metadata record including any profiling information.\n */\nexport const getResponseMetadata = <TLocals extends ResponseLocals>(res: Response<unknown, TLocals>): Record<string, unknown> => {\n const meta = res.locals.meta ?? {}\n // NOTE: We should do this somewhere else to better separate concerns\n const profile = meta.profile\n if (profile !== undefined) {\n const startTime = profile.startTime\n if (startTime !== undefined) {\n const endTime = Date.now()\n const duration = endTime - startTime\n meta.profile = {\n duration, endTime, startTime,\n }\n }\n }\n return meta\n}\n", "import { isError } from '@xylabs/typeof'\nimport type {\n NextFunction, Request, Response,\n} from 'express-serve-static-core'\n\nimport { getDefaultLogger } from '../../Logger/index.ts'\nimport type { ExpressError } from '../../Model/index.ts'\nimport type { ApiError } from './jsonApi/index.ts'\n\n/**\n * Express error handler that logs the error and sends a JSON:API-compliant error response.\n * @param err The error to handle, or undefined if no error.\n * @param req The incoming request.\n * @param res The outgoing response.\n * @param next The next middleware function.\n */\nexport const standardErrors = (err: ExpressError | undefined, req: Request, res: Response, next: NextFunction) => {\n if (!isError(err)) {\n next(err)\n return\n }\n getDefaultLogger().error(err.message)\n err.statusCode = err.statusCode ?? 500\n\n const error: ApiError = {\n detail: err.message,\n status: `${err.statusCode}`,\n title: err.name,\n }\n\n res.status(err.statusCode).json(error)\n\n next(err)\n}\n", "import type {\n Request, RequestHandler, Response,\n} from 'express-serve-static-core'\n\nimport type { ResponseLocals } from './getResponseMetadata.js'\nimport { getResponseMetadata } from './getResponseMetadata.js'\n\ninterface TransformResponseLocals extends ResponseLocals {\n rawResponse?: boolean\n}\n\n/**\n * Flags the response to forgo the standard response envelope\n * and return the raw response body to the client\n * @param res The response to disable the standard response format on\n */\nexport const setRawResponseFormat = (res: Response): void => {\n res.locals.rawResponse = true\n}\n\n/**\n * Clears any flags on the response, allowing the response to\n * use the default standard response envelope\n * @param res The response to set to the standard response format\n */\nexport const clearRawResponseFormat = (res: Response): void => {\n res.locals.rawResponse = false\n}\n\n/**\n * Checks if there are any flags on the response that would cause it\n * to forgo the standard response envelope and return the raw response\n * body to the client\n * @param res\n * @returns True if there are any flags on the response, false otherwise\n */\nexport const isRawResponseFormatSet = (res: Response): boolean => {\n return res.locals.rawResponse ? true : false\n}\n\n/**\n * Transforms each response to conform to the standard response format (compatible with JSON API)\n * @param body The original request body\n * @param _req The request\n * @param res The response\n * @returns The transformed response body\n */\nconst transformResponse = (body: unknown, _req: Request, res: Response<unknown, TransformResponseLocals>) => {\n return isRawResponseFormatSet(res)\n ? body\n : (res.statusCode >= 200 && res.statusCode < 300)\n ? { data: body, meta: getResponseMetadata(res) }\n : { error: body, meta: getResponseMetadata(res) }\n}\n\n/**\n * Connect middleware to enable the transform of all responses to match\n * the standard response format (compatible with JSON API)\n */\n\nexport const standardResponses: RequestHandler = (req, res, next) => {\n const json = res.json.bind(res)\n res.json = ((body: unknown) => {\n try {\n return json(transformResponse(body, req, res))\n } catch (ex) {\n next(ex)\n return res\n }\n }) as Response['json']\n next()\n}\n", "/**\n * Returns a shallow copy of the object with all null and undefined values removed.\n * @param obj The object to compact.\n * @returns A new object with only defined, non-null properties.\n */\nexport const compactObject = <T extends Record<string, unknown>>(obj: T) => {\n const result: Record<string, unknown> = {}\n for (const key in obj) {\n if (obj[key] !== undefined && obj[key] !== null) {\n result[key] = obj[key]\n }\n }\n return result as T\n}\n", "import { isDefined } from '@xylabs/typeof'\n\n/** A function that parses a string value into the target type. */\nexport type ParseFunc<T = number> = (value: string) => T\n\n/**\n * @deprecated use zod instead\n */\nexport const tryParse = <T = number>(func: ParseFunc<T>, value?: string) => {\n try {\n const result = isDefined(value) ? func(value) : null\n if (!Number.isNaN(result) && result !== null) {\n return result\n }\n } catch {\n return\n }\n}\n", "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { isDefined, isPromise } from '@xylabs/typeof'\nimport type {\n NextFunction, Request, RequestHandler, Response,\n} from 'express-serve-static-core'\nimport * as z from 'zod/mini'\n\nimport { ReasonPhrases, StatusCodes } from '../HttpStatus.ts'\nimport type { ExpressError } from '../Model/index.ts'\n\n/**\n * Empty Zod schema for requests with no parameters.\n */\nexport const EmptyParamsZod = z.catchall(z.object({}), z.string())\n\n/**\n * Empty Zod schema for requests with no query parameters.\n */\nexport const EmptyQueryParamsZod = z.catchall(z.object({}), z.union([z.string(), z.array(z.string())]))\n\n/**\n * Default validation schemas for request handler validator.\n */\nexport const ValidateRequestDefaults = {\n params: EmptyParamsZod,\n query: EmptyQueryParamsZod,\n body: z.optional(z.json()),\n response: z.optional(z.json()),\n}\n\ntype ValidatableRequestKey = 'params' | 'query' | 'body'\n\n/**\n * Factory for Express middleware that validates request and response objects using Zod schemas.\n * @param schemas The Zod schemas to use for validation.\n * @returns A middleware function for validating requests and responses.\n */\nexport function requestHandlerValidator<\n TParams extends typeof EmptyQueryParamsZod | z.core.$ZodType<Record<string, string>> = typeof EmptyQueryParamsZod,\n TQuery extends typeof EmptyQueryParamsZod | z.core.$ZodType<Record<string, string | string[]>> = typeof EmptyQueryParamsZod,\n TBody extends z.core.$ZodType<unknown> = z.core.$ZodType<unknown>,\n TResponse extends z.core.$ZodType<unknown> = z.core.$ZodType<unknown>,\n>(schemas?: Partial<{\n body: TBody\n params: TParams\n query: TQuery\n response: TResponse\n}>) {\n type Params = z.infer<TParams>\n type Query = z.infer<TQuery>\n type Body = z.infer<TBody>\n type Res = z.infer<TResponse>\n const validators = { ...ValidateRequestDefaults, ...schemas }\n\n return (handler: (req: Request<Params, Res, Body, Query>, res: Response<Res>, next: NextFunction) => unknown): RequestHandler => {\n return async (req: Request, res: Response, next: NextFunction) => {\n const originalJson = res.json.bind(res)\n try {\n // Validate incoming request\n const errors: string[] = []\n const keys: ValidatableRequestKey[] = ['params', 'query', 'body']\n for (const key of keys) {\n const validator = validators[key]\n const result = z.safeParse(validator, req[key])\n if (result.success) {\n if (isDefined(result.data)) Object.assign(req[key], result.data)\n } else {\n errors.push(\n ...result.error.issues.map(\n issue => (issue.path.length === 0)\n ? `${key}: ${issue.message}`\n : `${key}.${issue.path.join('.')}: ${issue.message}`,\n ),\n )\n }\n }\n\n // If there were validation errors, short-circuit and return Bad Request\n if (errors.length > 0) {\n const message = errors.join('; ')\n const err: ExpressError = new Error(message)\n err.name = ReasonPhrases.BAD_REQUEST\n err.statusCode = StatusCodes.BAD_REQUEST\n next(err)\n return false\n }\n\n // Wrap res.json to validate outgoing response\n res.json = (data: any) => {\n const result = z.safeParse(validators.response, data)\n if (result.success) {\n return originalJson(result.data)\n } else {\n const message = result.error.issues.map(\n issue => (issue.path.length === 0)\n ? `response: ${issue.message}`\n : `response.${issue.path.join('.')}: ${issue.message}`,\n ).join('; ')\n const err: ExpressError = new Error(message)\n err.name = ReasonPhrases.INTERNAL_SERVER_ERROR\n err.statusCode = StatusCodes.INTERNAL_SERVER_ERROR\n\n // Restore original json function in case the error handler wants to use it\n res.json = originalJson\n throw err\n }\n }\n\n // Automatically handle async errors\n const typedReq = req as Request<Params, Res, Body, Query>\n const typedRes = res as Response<Res>\n const result: unknown = handler(typedReq, typedRes, next)\n if (isPromise(result)) {\n const resultPromise: Promise<unknown> = result\n await resultPromise\n }\n } catch (err) {\n res.json = originalJson\n next(err)\n }\n }\n }\n}\n"],
5
- "mappings": ";AASO,SAAS,aACd,IACA;AACA,SAAO,CAAC,KAAqD,KAAgC,SAAuB;AAClH,WAAO,QAAQ,QAAQ,GAAG,KAAK,KAAK,IAAI,CAAC,EAAE,MAAM,IAAI;AAAA,EACvD;AACF;;;ACfA,SAAS,SAAS,gBAAgB;;;ACClC,SAAS,cAAc,cAAc,yBAAyB;;;ACA9D,SAAS,cAAc;AAEvB,IAAM;AAAA,EACJ;AAAA,EAAU;AAAA,EAAS;AAAA,EAAW;AAChC,IAAI;AAGG,IAAM,oBAAoC;AAAA,EAC/C,SAAS;AAAA,EACT,UAAU;AAAA,EACV,OAAO,UAAQ,IAAI,OAAO,KAAK,SAAS,CAAC,IAAI,OAAO,KAAK,KAAK,CAAC,KAAK,OAAO,KAAK,OAAO,CAAC,EAAE;AAC5F;;;ACXA,SAAS,UAAAA,eAAc;AAEvB,IAAM,EAAE,OAAO,IAAIA;AAGZ,IAAM,mBAAmC,OAAO;;;ACLvD,SAAS,UAAAC,eAAc;AAEvB,IAAM;AAAA,EACJ,SAAAC;AAAA,EAAS,WAAAC;AAAA,EAAW;AACtB,IAAIF;AAGG,IAAM,sBAAsCC,SAAQC,WAAU,GAAG,KAAK,CAAC;;;ACAvE,IAAM,qBAAqB,CAAC,oBAAuD;AACxF,SAAO,oBAAoB,QAAQ,UAAU;AAC/C;;;ACLO,IAAM,gCAAgC,CAAC,QAAqD;AACjG,SAAO,IAAI,yBAAyB,SAAY,QAAQ;AAC1D;;;ACPA,SAAS,gBAAgB;AACzB,OAAO,aAAa;;;ACCpB,OAAO,eAAe;AAKf,IAAM,mBAAN,cAA+B,UAAU;AAAA,EAC3B;AAAA,EACnB,YACE,MACA,SACA;AACA,UAAM;AAAA,MACJ,GAAG;AAAA,MAAM,QAAQ;AAAA,MAAkB,OAAO;AAAA,IAC5C,CAAC;AACD,SAAK,UAAU;AAAA,EACjB;AAAA,EAES,IAAI,MAA4B,MAAkB;AACzD,SAAK,SAAS,MAAM,MAAM,OAAO;AACjC,SAAK,KAAK,UAAU,MAAM,OAAO;AACjC,SAAK;AAAA,EACP;AACF;;;ADdO,IAAM,6BAA6B,CAAC,QAA8D;AACvG,QAAM,cAAc,SAAS,IAAI,sBAAsB,MAAM,sCAAsC;AACnG,QAAM,UAAmB,IAAI,QAAQ,EAAE,YAAY,CAAC;AACpD,SAAO,IAAI,iBAAiB,CAAC,GAAG,OAAO;AACzC;;;AEPO,IAAM,uBAAN,MAA6C;AAAA,EAC/B;AAAA,EACnB,YAAY,SAAkB;AAC5B,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,QAAqB,aAAW,KAAK,QAAQ,MAAM,OAAO;AAAA,EAC1D,QAAqB,aAAW,KAAK,QAAQ,MAAM,OAAO;AAAA,EAC1D,OAAoB,aAAW,KAAK,QAAQ,KAAK,OAAO;AAAA,EACxD,MAAmB,aAAW,KAAK,QAAQ,KAAK,OAAO;AAAA,EACvD,QAAqB,aAAW,KAAK,QAAQ,MAAM,OAAO;AAAA,EAC1D,OAAoB,aAAW,KAAK,QAAQ,KAAK,OAAO;AAC1D;;;ARRA,IAAM,cAAc;AACpB,IAAM,mBAAmB;AAEzB,IAAM,EAAE,QAAQ,IAAI;AACpB,IAAM,mBAAmB,IAAI,QAAQ;AACrC,IAAMC,UAAS,QAAQ,IAAI,aAAa,gBAAgB,oBAAoB;AAC5E,IAAM,aAAgC,CAAC,gBAAgB;AACvD,IAAI,8BAA8B,QAAQ,GAAG,GAAG;AAC9C,MAAI;AACF,UAAM,mBAAmB,2BAA2B,QAAQ,GAAG;AAC/D,eAAW,KAAK,gBAAgB;AAAA,EAClC,QAAQ;AAAA,EAGR;AACF;AAEA,IAAM,UAAwD;AAAA,EAC5D,OAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,SAAS;AAAA,EACT,MAAM;AACR;AAOO,IAAM,YAAY,CAAC,eAAgC,WAAmB;AAC3E,QAAM,QAAQ,mBAAmB,YAAY;AAC7C,QAAM,WAAW,QAAQ,KAAK;AAC9B,MAAI,SAAU,QAAO;AACrB,QAAM,SAAS,IAAI;AAAA,IACjB,aAAa;AAAA,MACX;AAAA,MACA,QAAAA;AAAA,MACA;AAAA,MACA;AAAA,MACA,mBAAmB;AAAA,MACnB;AAAA,IACF,CAAC;AAAA,EACH;AACA,UAAQ,KAAK,IAAI;AACjB,SAAO;AACT;;;ASvCO,IAAM,mBAAmB,MAAc;AAC5C,aAAW,OAAO,CAAC;AACnB,MAAI,WAAW,GAAG,cAAe,QAAO,WAAW,GAAG;AACtD,SAAO,UAAU;AACnB;;;AVTO,IAAM,qBAAqB,CAAC,OAAqB,KAAc,KAAe,SAAuB;AAC1G,MAAI,QAAQ,KAAK,GAAG;AAClB,qBAAiB,EAAE,MAAM,MAAM,OAAO;AACtC,QAAI,CAAC,SAAS,MAAM,UAAU,EAAG,OAAM,aAAa;AACpD,QAAI,OAAO,MAAM,UAAU,EAAE,KAAK,EAAE,OAAO,MAAM,QAAQ,CAAC;AAAA,EAC5D;AACA,OAAK,KAAK;AACZ;;;AWbO,IAAM,sBAAsB,CAAC,KAAc,qBAAwC;AACxF,aAAW,cAAc,kBAAkB;AACzC,QAAI,WAAW,MAAM,EAAE,WAAW,MAAM,WAAW,QAAQ;AAAA,EAC7D;AACF;;;ACbO,IAAM,gBAAgB;AAAA,EAC3B,aAAa;AAAA,EACb,uBAAuB;AAAA,EACvB,iBAAiB;AACnB;AAEO,IAAM,cAAc;AAAA,EACzB,aAAa;AAAA,EACb,uBAAuB;AAAA,EACvB,iBAAiB;AACnB;;;ACLO,IAAM,iBAAiC,CAAC,MAAM,MAAM,SAAS;AAClE,OAAK,EAAE,SAAS,cAAc,iBAAiB,YAAY,YAAY,gBAAgB,CAAC;AAC1F;;;ACPA,SAAS,iBAAiB;AAYnB,IAAM,gBAAgB,CAACC,SAAgB,QAAqC;AACjF,QAAM,cAAc,IAAI,QAAQA,OAAM;AACtC,QAAM,QAEF,UAAU,WAAW,IAEnB,MAAM,QAAQ,WAAW,IAEtB,YAAa,MAAM,IAEnB,cAEH;AACN,SAAO;AACT;;;ACxBA,IAAM,UAAU;AAOT,IAAM,6BAA6B,CAAC,QAAiB;AAC1D,MAAI,OAAO,OAAO;AACpB;AAOO,IAAM,8BAA8B,CAAC,QAAiB;AAC3D,MAAI,QAAQ,OAAO;AACrB;;;AChBA,IAAM,SAAS;AACf,IAAMC,WAAU;AAOT,IAAM,sCAAsC,CAAC,QAAiB;AACnE,MAAI,OAAOA,QAAO;AACpB;AAOO,IAAM,uCAAuC,CAAC,QAAiB;AACpE,MAAI,QAAQA,QAAO;AACrB;AAGO,IAAM,wBAAwB,CAAC,KAAc,KAAe,SAAuB;AACxF,MAAI,UAAU,QAAQ,KAAK;AAC3B,OAAK;AACP;;;AC5BA,OAAO,gBAAgB;AAQhB,IAAM,oCAAoC;AAK1C,IAAM,oCAAoC,CAAC,oBAAoB,WAAW;AAK1E,IAAM,+BAA4C;AAAA,EACvD,OAAO;AAAA,EACP,MAAM;AACR;AASO,IAAM,2BAA2B,CAAC,YAAgD;AACvF,SAAO,UAAU,EAAE,GAAG,8BAA8B,GAAG,QAAQ,IAAI;AACrE;AAOO,IAAM,oBAAoB,CAAC,UAAuB,iCAAqD;AAE5G,QAAM,SAAS,WAAW,KAAK,OAAO;AAEtC,SAAO,CAAC,KAAK,KAAK,SAAS;AAEzB,QAAI;AACF,aAAO,KAAK,KAAK,IAAI;AAAA,IACvB,SAAS,IAAI;AACX,YAAM,QAAQ;AACd,uBAAiB,EAAE,IAAI,sBAAsB,OAAO,IAAI,MAAM,OAAO,OAAO,EAAE;AAAA,IAChF;AAAA,EACF;AACF;AAKO,IAAM,iBAAiB,kBAAkB;;;ACzDzC,IAAM,WAAN,MAAe;AAAA,EACpB,OAAO,WAAmC,CAAC;AAAA,EAE3C,OAAO,IAAI,MAAc,QAAQ,GAAG;AAClC,SAAK,WAAW,MAAM,CAACC,UAAiB;AACtC,WAAK,SAASA,KAAI,KAAK,KAAK,SAASA,KAAI,KAAK,KAAK;AAAA,IACrD,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,IAAI,MAAc,OAAe;AACtC,SAAK,WAAW,MAAM,CAACA,UAAiB;AACtC,YAAM,eAAe,KAAK,SAASA,KAAI;AACvC,UAAI,iBAAiB,UAAa,QAAQ,cAAc;AACtD,aAAK,SAASA,KAAI,IAAI;AAAA,MACxB;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,IAAI,MAAc,OAAe;AACtC,SAAK,WAAW,MAAM,CAACA,UAAiB;AACtC,YAAM,eAAe,KAAK,SAASA,KAAI;AACvC,UAAI,iBAAiB,UAAa,QAAQ,cAAc;AACtD,aAAK,SAASA,KAAI,IAAI;AAAA,MACxB;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,OAAe,aAAa,CAAC,MAAc,SAAiC;AAC1E,QAAI;AACF,WAAK,IAAI;AAAA,IACX,QAAQ;AACN,WAAK,SAAS,IAAI,IAAI;AACtB,WAAK,IAAI,gBAAgB;AAAA,IAC3B;AAAA,EACF;AACF;;;ACnCO,IAAM,WAAN,MAAe;AAAA,EACpB,QAAgC,CAAC;AAAA,EAEjC,MAAM,QAAW,MAAc,SAAqB;AAClD,UAAM,QAAQ,KAAK,IAAI;AACvB,UAAM,SAAS,MAAM;AACrB,SAAK,MAAM,IAAI,IAAI,KAAK,IAAI,IAAI;AAChC,WAAO;AAAA,EACT;AACF;;;ACAO,IAAM,qBAAqB,CAAC,QAA2B;AAE5D,MAAI,IAAI,CAAC,KAAc,KAAe,SAAuB;AAC3D,aAAS,IAAI,IAAI,IAAI;AACrB,aAAS,IAAI,QAAQ;AACrB,SAAK;AAAA,EACP,CAAC;AAED,MAAI,IAAI,UAAU,CAAC,KAAc,KAAe,SAAuB;AAGrE,QAAI,KAAK;AAAA,MACP,OAAO;AAAA,MACP,SAAS,KAAK,SAAS,SAAS,cAAc,MAAM,SAAS,SAAS,UAAU,IAAI,QAAQ,CAAC,CAAC;AAAA,MAC9F,UAAU,SAAS;AAAA,IACrB,CAAC;AACD,SAAK;AAAA,EACP,CAAC;AACH;;;ACAO,IAAM,mBAAmB,CAAC,MAAe,KAAwC,SAAuB;AAC7G,MAAI,OAAO,SAAS,CAAC;AACrB,MAAI,OAAO,KAAK,UAAU,EAAE,WAAW,KAAK,IAAI,EAAE;AAClD,OAAK;AACP;;;ACXO,IAAM,sBAAsB,CAAiC,QAA6D;AAC/H,QAAM,OAAO,IAAI,OAAO,QAAQ,CAAC;AAEjC,QAAM,UAAU,KAAK;AACrB,MAAI,YAAY,QAAW;AACzB,UAAM,YAAY,QAAQ;AAC1B,QAAI,cAAc,QAAW;AAC3B,YAAM,UAAU,KAAK,IAAI;AACzB,YAAM,WAAW,UAAU;AAC3B,WAAK,UAAU;AAAA,QACb;AAAA,QAAU;AAAA,QAAS;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;;;ACpCA,SAAS,WAAAC,gBAAe;AAgBjB,IAAM,iBAAiB,CAAC,KAA+B,KAAc,KAAe,SAAuB;AAChH,MAAI,CAACC,SAAQ,GAAG,GAAG;AACjB,SAAK,GAAG;AACR;AAAA,EACF;AACA,mBAAiB,EAAE,MAAM,IAAI,OAAO;AACpC,MAAI,aAAa,IAAI,cAAc;AAEnC,QAAM,QAAkB;AAAA,IACtB,QAAQ,IAAI;AAAA,IACZ,QAAQ,GAAG,IAAI,UAAU;AAAA,IACzB,OAAO,IAAI;AAAA,EACb;AAEA,MAAI,OAAO,IAAI,UAAU,EAAE,KAAK,KAAK;AAErC,OAAK,GAAG;AACV;;;ACjBO,IAAM,uBAAuB,CAAC,QAAwB;AAC3D,MAAI,OAAO,cAAc;AAC3B;AAOO,IAAM,yBAAyB,CAAC,QAAwB;AAC7D,MAAI,OAAO,cAAc;AAC3B;AASO,IAAM,yBAAyB,CAAC,QAA2B;AAChE,SAAO,IAAI,OAAO,cAAc,OAAO;AACzC;AASA,IAAM,oBAAoB,CAAC,MAAe,MAAe,QAAoD;AAC3G,SAAO,uBAAuB,GAAG,IAC7B,OACC,IAAI,cAAc,OAAO,IAAI,aAAa,MACvC,EAAE,MAAM,MAAM,MAAM,oBAAoB,GAAG,EAAE,IAC7C,EAAE,OAAO,MAAM,MAAM,oBAAoB,GAAG,EAAE;AACxD;AAOO,IAAM,oBAAoC,CAAC,KAAK,KAAK,SAAS;AACnE,QAAMC,QAAO,IAAI,KAAK,KAAK,GAAG;AAC9B,MAAI,QAAQ,CAAC,SAAkB;AAC7B,QAAI;AACF,aAAOA,MAAK,kBAAkB,MAAM,KAAK,GAAG,CAAC;AAAA,IAC/C,SAAS,IAAI;AACX,WAAK,EAAE;AACP,aAAO;AAAA,IACT;AAAA,EACF;AACA,OAAK;AACP;;;AClEO,IAAM,gBAAgB,CAAoC,QAAW;AAC1E,QAAM,SAAkC,CAAC;AACzC,aAAW,OAAO,KAAK;AACrB,QAAI,IAAI,GAAG,MAAM,UAAa,IAAI,GAAG,MAAM,MAAM;AAC/C,aAAO,GAAG,IAAI,IAAI,GAAG;AAAA,IACvB;AAAA,EACF;AACA,SAAO;AACT;;;ACbA,SAAS,aAAAC,kBAAiB;AAQnB,IAAM,WAAW,CAAa,MAAoB,UAAmB;AAC1E,MAAI;AACF,UAAM,SAASA,WAAU,KAAK,IAAI,KAAK,KAAK,IAAI;AAChD,QAAI,CAAC,OAAO,MAAM,MAAM,KAAK,WAAW,MAAM;AAC5C,aAAO;AAAA,IACT;AAAA,EACF,QAAQ;AACN;AAAA,EACF;AACF;;;AChBA,SAAS,aAAAC,YAAW,iBAAiB;AAIrC,YAAY,OAAO;AAQZ,IAAM,iBAAmB,WAAW,SAAO,CAAC,CAAC,GAAK,SAAO,CAAC;AAK1D,IAAM,sBAAwB,WAAW,SAAO,CAAC,CAAC,GAAK,QAAM,CAAG,SAAO,GAAK,QAAQ,SAAO,CAAC,CAAC,CAAC,CAAC;AAK/F,IAAM,0BAA0B;AAAA,EACrC,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,MAAQ,WAAW,OAAK,CAAC;AAAA,EACzB,UAAY,WAAW,OAAK,CAAC;AAC/B;AASO,SAAS,wBAKd,SAKE;AAKF,QAAM,aAAa,EAAE,GAAG,yBAAyB,GAAG,QAAQ;AAE5D,SAAO,CAAC,YAAyH;AAC/H,WAAO,OAAO,KAAc,KAAe,SAAuB;AAChE,YAAM,eAAe,IAAI,KAAK,KAAK,GAAG;AACtC,UAAI;AAEF,cAAM,SAAmB,CAAC;AAC1B,cAAM,OAAgC,CAAC,UAAU,SAAS,MAAM;AAChE,mBAAW,OAAO,MAAM;AACtB,gBAAM,YAAY,WAAW,GAAG;AAChC,gBAAMC,UAAW,YAAU,WAAW,IAAI,GAAG,CAAC;AAC9C,cAAIA,QAAO,SAAS;AAClB,gBAAIC,WAAUD,QAAO,IAAI,EAAG,QAAO,OAAO,IAAI,GAAG,GAAGA,QAAO,IAAI;AAAA,UACjE,OAAO;AACL,mBAAO;AAAA,cACL,GAAGA,QAAO,MAAM,OAAO;AAAA,gBACrB,WAAU,MAAM,KAAK,WAAW,IAC5B,GAAG,GAAG,KAAK,MAAM,OAAO,KACxB,GAAG,GAAG,IAAI,MAAM,KAAK,KAAK,GAAG,CAAC,KAAK,MAAM,OAAO;AAAA,cACtD;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAGA,YAAI,OAAO,SAAS,GAAG;AACrB,gBAAM,UAAU,OAAO,KAAK,IAAI;AAChC,gBAAM,MAAoB,IAAI,MAAM,OAAO;AAC3C,cAAI,OAAO,cAAc;AACzB,cAAI,aAAa,YAAY;AAC7B,eAAK,GAAG;AACR,iBAAO;AAAA,QACT;AAGA,YAAI,OAAO,CAAC,SAAc;AACxB,gBAAMA,UAAW,YAAU,WAAW,UAAU,IAAI;AACpD,cAAIA,QAAO,SAAS;AAClB,mBAAO,aAAaA,QAAO,IAAI;AAAA,UACjC,OAAO;AACL,kBAAM,UAAUA,QAAO,MAAM,OAAO;AAAA,cAClC,WAAU,MAAM,KAAK,WAAW,IAC5B,aAAa,MAAM,OAAO,KAC1B,YAAY,MAAM,KAAK,KAAK,GAAG,CAAC,KAAK,MAAM,OAAO;AAAA,YACxD,EAAE,KAAK,IAAI;AACX,kBAAM,MAAoB,IAAI,MAAM,OAAO;AAC3C,gBAAI,OAAO,cAAc;AACzB,gBAAI,aAAa,YAAY;AAG7B,gBAAI,OAAO;AACX,kBAAM;AAAA,UACR;AAAA,QACF;AAGA,cAAM,WAAW;AACjB,cAAM,WAAW;AACjB,cAAM,SAAkB,QAAQ,UAAU,UAAU,IAAI;AACxD,YAAI,UAAU,MAAM,GAAG;AACrB,gBAAM,gBAAkC;AACxC,gBAAM;AAAA,QACR;AAAA,MACF,SAAS,KAAK;AACZ,YAAI,OAAO;AACX,aAAK,GAAG;AAAA,MACV;AAAA,IACF;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["import type {\n NextFunction, ParamsDictionary, Query, Request, RequestHandler, Response,\n} from 'express-serve-static-core'\n\n/**\n * Wraps an async Express request handler to forward rejected promises to the error handler.\n * @param fn The async request handler to wrap.\n * @returns A request handler that catches async errors and passes them to next().\n */\nexport function asyncHandler<P = NoReqParams, ResBody = NoResBody, ReqBody = NoReqBody, ReqQuery = NoReqQuery, Locals extends NoLocals = NoLocals>(\n fn: RequestHandler<P, ResBody, ReqBody, ReqQuery, Locals>,\n) {\n return async (req: Request<P, ResBody, ReqBody, ReqQuery, Locals>, res: Response<ResBody, Locals>, next: NextFunction) => {\n try {\n await fn(req, res, next)\n } catch (error) {\n next(error)\n }\n }\n}\n\n/** Empty object type used as a default for request/response body generics. */\nexport interface Empty {}\n\n/** Default type for request route parameters. */\nexport type NoReqParams = ParamsDictionary\n/** Default type for response body when none is specified. */\nexport type NoResBody = Empty\n/** Default type for request body when none is specified. */\nexport type NoReqBody = Empty\n/** Default type for request query parameters. */\nexport type NoReqQuery = Query\n/** Default type for response locals. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type NoLocals = Record<string, any>\n", "import { isError, isNumber } from '@xylabs/typeof'\nimport type {\n NextFunction, Request, Response,\n} from 'express-serve-static-core'\n\nimport { getDefaultLogger } from '../Logger/index.ts'\nimport type { ExpressError } from '../Model/index.ts'\n\n/**\n * Express error handler that logs the error and sends a JSON response with the error message and status code.\n * @param error The Express error to handle.\n * @param req The incoming request.\n * @param res The outgoing response.\n * @param next The next middleware function.\n */\nexport const errorToJsonHandler = (error: ExpressError, req: Request, res: Response, next: NextFunction) => {\n if (isError(error)) {\n getDefaultLogger().error(error.message)\n if (!isNumber(error.statusCode)) error.statusCode = 500\n res.status(error.statusCode).send({ error: error.message })\n }\n next(error)\n}\n", "import type { Logger } from '@xylabs/logger'\nimport { createLogger, transports as winstonTransports } from 'winston'\nimport type TransportStream from 'winston-transport'\n\nimport { logFormatLocalDev, logFormatStructured } from './LogFormats/index.ts'\nimport type { LoggerVerbosity } from './LoggerVerbosity.ts'\nimport { toWinstonVerbosity } from './toWinstonVerbosity.ts'\nimport { canGetDefaultRollbarTransport, getDefaultRollbarTransport } from './Transports/index.ts'\nimport type { WinstonVerbosity } from './WinstonVerbosity.ts'\nimport { WrappedWinstonLogger } from './WrappedWinstonLogger.ts'\n\nconst isExitOnError = false\nconst isHandleRejections = true\n\nconst { Console } = winstonTransports\nconst consoleTransport = new Console()\nconst format = process.env.NODE_ENV === 'development' ? logFormatLocalDev : logFormatStructured\nconst transports: TransportStream[] = [consoleTransport]\nif (canGetDefaultRollbarTransport(process.env)) {\n try {\n const rollbarTransport = getDefaultRollbarTransport(process.env)\n transports.push(rollbarTransport)\n } catch {\n // NOTE: No error here, just gracefully adding logger if ENV VARs\n // were preset\n }\n}\n\nconst loggers: Record<WinstonVerbosity, Logger | undefined> = {\n debug: undefined,\n error: undefined,\n http: undefined,\n info: undefined,\n silly: undefined,\n verbose: undefined,\n warn: undefined,\n}\n\n/**\n * Returns a cached Winston-backed logger at the specified verbosity level.\n * @param minVerbosity The minimum log level to output. Defaults to 'info'.\n * @returns A logger instance configured for the given verbosity.\n */\nexport const getLogger = (minVerbosity: LoggerVerbosity = 'info'): Logger => {\n const level = toWinstonVerbosity(minVerbosity)\n const existing = loggers[level]\n if (existing) return existing\n const logger = new WrappedWinstonLogger(\n createLogger({\n exitOnError: isExitOnError,\n format,\n handleRejections: isHandleRejections,\n level,\n rejectionHandlers: transports,\n transports,\n }),\n )\n loggers[level] = logger\n return logger\n}\n", "import type { Logform } from 'winston'\nimport { format } from 'winston'\n\nconst {\n colorize, combine, timestamp, printf,\n} = format\n\n/** Winston log format for local development with colorized output and timestamps. */\nexport const logFormatLocalDev: Logform.Format = combine(\n colorize(),\n timestamp(),\n printf(info => `[${String(info.timestamp)} ${info.level}] ${String(info.message)}`),\n)\n", "import type { Logform } from 'winston'\nimport { format } from 'winston'\n\nconst { simple } = format\n\n/** Winston log format for Rollbar using simple text output. */\nexport const logFormatRollbar: Logform.Format = simple()\n", "import type { Logform } from 'winston'\nimport { format } from 'winston'\n\nconst {\n combine, timestamp, json,\n} = format\n\n/** Winston log format for production with structured JSON output and timestamps. */\nexport const logFormatStructured: Logform.Format = combine(timestamp(), json())\n", "import type { LoggerVerbosity } from './LoggerVerbosity.ts'\nimport type { WinstonVerbosity } from './WinstonVerbosity.ts'\n\n/**\n * Converts a LoggerVerbosity level to the corresponding Winston log level.\n * @param loggerVerbosity The application-level verbosity to convert.\n * @returns The equivalent Winston verbosity level.\n */\nexport const toWinstonVerbosity = (loggerVerbosity: LoggerVerbosity): WinstonVerbosity => {\n return loggerVerbosity === 'all' ? 'silly' : loggerVerbosity\n}\n", "/**\n * Checks whether the ROLLBAR_ACCESS_TOKEN environment variable is set.\n * @param env The environment variables to check.\n * @returns True if the Rollbar access token is available.\n */\nexport const canGetDefaultRollbarTransport = (env: Record<string, string | undefined>): boolean => {\n return env.ROLLBAR_ACCESS_TOKEN === undefined ? false : true\n}\n", "import { assertEx } from '@xylabs/assert'\nimport Rollbar from 'rollbar'\n\nimport { RollbarTransport } from './RollbarTransport.ts'\n\n/**\n * Creates a RollbarTransport using the ROLLBAR_ACCESS_TOKEN from the environment.\n * @param env The environment variables containing the Rollbar access token.\n * @returns A configured RollbarTransport instance.\n */\nexport const getDefaultRollbarTransport = (env: Record<string, string | undefined>): RollbarTransport => {\n const accessToken = assertEx(env.ROLLBAR_ACCESS_TOKEN, () => 'Missing ROLLBAR_ACCESS_TOKEN ENV VAR')\n const rollbar: Rollbar = new Rollbar({ accessToken })\n return new RollbarTransport({}, rollbar)\n}\n", "import type Rollbar from 'rollbar'\nimport type { TransportStreamOptions } from 'winston-transport'\nimport Transport from 'winston-transport'\n\nimport { logFormatRollbar } from '../../LogFormats/index.ts'\n\n/** Winston transport that forwards error-level log messages to Rollbar. */\nexport class RollbarTransport extends Transport {\n protected readonly rollbar?: Rollbar\n constructor(\n opts: TransportStreamOptions,\n rollbar?: Rollbar,\n ) {\n super({\n ...opts, format: logFormatRollbar, level: 'error',\n })\n this.rollbar = rollbar\n }\n\n override log(info: { message?: string }, next: () => void) {\n this.rollbar?.error(info?.message)\n this.emit('logged', info?.message)\n next()\n }\n}\n", "import type { LogFunction, Logger } from '@xylabs/logger'\nimport type { Logger as Winston } from 'winston'\n\n/**\n * Wrap Winston logger methods to adapt to familiar\n * console logging methods\n */\nexport class WrappedWinstonLogger implements Logger {\n protected readonly winston: Winston\n constructor(winston: Winston) {\n this.winston = winston\n }\n\n debug: LogFunction = message => this.winston.debug(message)\n error: LogFunction = message => this.winston.error(message)\n info: LogFunction = message => this.winston.info(message)\n log: LogFunction = message => this.winston.info(message)\n trace: LogFunction = message => this.winston.debug(message)\n warn: LogFunction = message => this.winston.warn(message)\n}\n", "import type { Logger } from '@xylabs/logger'\n\nimport { getLogger } from './getLogger.ts'\nimport type { WrappedWinstonLogger } from './WrappedWinstonLogger.ts'\n\n/**\n * Static instance to prevent multiple instances of the same logger\n * with the same config\n */\n\ndeclare global {\n var xy: {\n defaultLogger?: WrappedWinstonLogger\n }\n}\n\n/**\n * Returns the singleton default logger instance, creating one if it does not exist.\n * @returns The default logger.\n */\nexport const getDefaultLogger = (): Logger => {\n if (globalThis.xy === undefined) {\n Reflect.set(globalThis, 'xy', {})\n }\n if (globalThis.xy.defaultLogger) return globalThis.xy.defaultLogger\n return getLogger()\n}\n", "import type { Express } from 'express-serve-static-core'\n\nimport type { RouteDefinition } from './RouteDefinition.ts'\n\n/**\n * Registers an array of route definitions on an Express app.\n * @param app The Express app to register routes on.\n * @param routeDefinitions The route definitions to register.\n */\nexport const addRouteDefinitions = (app: Express, routeDefinitions: RouteDefinition[]) => {\n for (const definition of routeDefinitions) {\n app[definition.method](definition.path, definition.handlers)\n }\n}\n", "export const ReasonPhrases = {\n BAD_REQUEST: 'Bad Request',\n INTERNAL_SERVER_ERROR: 'Internal Server Error',\n NOT_IMPLEMENTED: 'Not Implemented',\n} as const\n\nexport const StatusCodes = {\n BAD_REQUEST: 400,\n INTERNAL_SERVER_ERROR: 500,\n NOT_IMPLEMENTED: 501,\n} as const\n", "import type { RequestHandler } from 'express-serve-static-core'\n\nimport { ReasonPhrases, StatusCodes } from '../../HttpStatus.ts'\n\n/** Express request handler that responds with a 501 Not Implemented error. */\nexport const notImplemented: RequestHandler = (_req, _res, next) => {\n next({ message: ReasonPhrases.NOT_IMPLEMENTED, statusCode: StatusCodes.NOT_IMPLEMENTED })\n}\n", "import { isDefined } from '@xylabs/typeof'\nimport type { Request } from 'express-serve-static-core'\n\n/**\n * Since there can be multiple of certain HTTP headers or\n * to prevent ugliness if someone did send us multiple\n * instances of a header we only expect one of, this\n * method grabs the 1st/only one of the desired header\n * @param header The header to find\n * @param req The received HTTP request (with headers)\n * @returns The first or only occurrence of the specified HTTP header\n */\nexport const getHttpHeader = (header: string, req: Request): string | undefined => {\n const headerValue = req.headers[header]\n const value\n // If the header exists\n = isDefined(headerValue)\n // If there's multiple of the same header\n ? Array.isArray(headerValue)\n // Grab the first one\n ? (headerValue).shift()\n // Otherwise grab the only one\n : (headerValue)\n // Otherwise undefined\n : undefined\n return value\n}\n", "import type { Express } from 'express-serve-static-core'\n\nconst setting = 'case sensitive routing'\n\n/**\n * Enable case sensitivity. When enabled, \"/Foo\" and \"/foo\" are different\n * routes. When disabled, \"/Foo\" and \"/foo\" are treated the same.\n * @param app The Express app to disable the header on.\n */\nexport const enableCaseSensitiveRouting = (app: Express) => {\n app.enable(setting)\n}\n\n/**\n * Disable case sensitivity. When enabled, \"/Foo\" and \"/foo\" are different\n * routes. When disabled, \"/Foo\" and \"/foo\" are treated the same.\n * @param app The Express app to disable the header on.\n */\nexport const disableCaseSensitiveRouting = (app: Express) => {\n app.disable(setting)\n}\n", "import type {\n Express, NextFunction, Request, Response,\n} from 'express-serve-static-core'\n\nconst header = 'X-Powered-By'\nconst setting = 'x-powered-by'\n\n/**\n * By default Express appends the `X-Powered-By: Express` header to\n * all responses. Calling this method enables that behavior.\n * @param app The Express app to disable the header on.\n */\nexport const enableExpressDefaultPoweredByHeader = (app: Express) => {\n app.enable(setting)\n}\n\n/**\n * By default Express appends the `X-Powered-By: Express` header to\n * all responses. Calling this method disables that behavior.\n * @param app The Express app to disable the header on.\n */\nexport const disableExpressDefaultPoweredByHeader = (app: Express) => {\n app.disable(setting)\n}\n\n/** Express middleware that sets the X-Powered-By header to 'XYO'. */\nexport const customPoweredByHeader = (req: Request, res: Response, next: NextFunction) => {\n res.setHeader(header, 'XYO')\n next()\n}\n", "import type { OptionsJson } from 'body-parser'\nimport bodyParser from 'body-parser'\nimport type { NextHandleFunction } from 'connect'\n\nimport { getDefaultLogger } from '../../Logger/index.ts'\n\n/**\n * The default maximum request body size for the JSON Body Parser\n */\nexport const DefaultJsonBodyParserOptionsLimit = '100kb'\n\n/**\n * The default MIME types for the JSON Body Parser\n */\nexport const DefaultJsonBodyParserOptionsTypes = ['application/json', 'text/json']\n\n/**\n * The default options for the JSON Body Parser\n */\nexport const DefaultJsonBodyParserOptions: OptionsJson = {\n limit: DefaultJsonBodyParserOptionsLimit,\n type: DefaultJsonBodyParserOptionsTypes,\n}\n\n/**\n * Gets the default JSON Body Parser options merged with the supplied options\n * with the supplied options taking precedence\n * @param options The options to override the default JSON Body Parser options with\n * @returns The combined JSON Body Parser options with the supplied values taking\n * precedence over the default\n */\nexport const getJsonBodyParserOptions = (options?: Partial<OptionsJson>): OptionsJson => {\n return options ? { ...DefaultJsonBodyParserOptions, ...options } : DefaultJsonBodyParserOptions\n}\n\n/**\n * Get a JSON Body Parser connect middleware handler\n * @param options The options for the JSON Body Parser\n * @returns A middleware function that parses JSON bodies\n */\nexport const getJsonBodyParser = (options: OptionsJson = DefaultJsonBodyParserOptions): NextHandleFunction => {\n // Create closed instance of bodyParser to prevent instantiation of new instance on every request\n const parser = bodyParser.json(options)\n\n return (req, res, next) => {\n // If we do not trap this error, then it dumps too much to log, usually happens if request aborted\n try {\n parser(req, res, next)\n } catch (ex) {\n const error = ex as Error\n getDefaultLogger().log(`bodyParser failed [${error?.name}]: ${error?.message}`)\n }\n }\n}\n\n/**\n * A JSON Body Parser middleware handler initialized with the default options\n */\nexport const jsonBodyParser = getJsonBodyParser()\n", "/** Static counter registry for tracking named numeric metrics. */\nexport class Counters {\n static counters: Record<string, number> = {}\n\n static inc(name: string, count = 1) {\n this.catchError(name, (name: string) => {\n this.counters[name] = (this.counters[name] ?? 0) + count\n })\n }\n\n static max(name: string, count: number) {\n this.catchError(name, (name: string) => {\n const currentValue = this.counters[name]\n if (currentValue === undefined || count > currentValue) {\n this.counters[name] = count\n }\n })\n }\n\n static min(name: string, count: number) {\n this.catchError(name, (name: string) => {\n const currentValue = this.counters[name]\n if (currentValue === undefined || count < currentValue) {\n this.counters[name] = count\n }\n })\n }\n\n private static catchError = (name: string, func: (name: string) => void) => {\n try {\n func(name)\n } catch {\n this.counters[name] = 0\n this.inc('CountersErrors')\n }\n }\n}\n", "/** Measures and records the execution duration of async operations by name. */\nexport class Profiler {\n stats: Record<string, number> = {}\n\n async profile<T>(name: string, promise: Promise<T>) {\n const start = Date.now()\n const result = await promise\n this.stats[name] = Date.now() - start\n return result\n }\n}\n", "import type {\n Application, NextFunction, Request, Response,\n} from 'express-serve-static-core'\n\nimport { Counters } from '../../Performance/index.ts'\n\n/**\n * Registers middleware that increments per-path request counters and exposes a /stats endpoint.\n * @param app The Express app to attach counters to.\n */\nexport const useRequestCounters = (app: Application): void => {\n // Configure Global counters\n app.use((req: Request, res: Response, next: NextFunction) => {\n Counters.inc(req.path)\n Counters.inc('_calls')\n next()\n })\n\n app.get('/stats', (req: Request, res: Response, next: NextFunction) => {\n /* #swagger.tags = ['Metrics'] */\n /* #swagger.summary = 'Get the counters for single instance of diviner' */\n res.json({\n alive: true,\n avgTime: `${((Counters.counters._totalTime ?? 0) / (Counters.counters._calls ?? 1)).toFixed(2)}ms`,\n counters: Counters.counters,\n })\n next()\n })\n}\n", "import type {\n NextFunction, Request, Response,\n} from 'express-serve-static-core'\n\ninterface ResponseProfile {\n startTime: number\n}\n\ninterface ResponseMetadata extends Record<string, unknown> {\n profile?: ResponseProfile\n}\n\ninterface ResponseLocals {\n meta?: ResponseMetadata\n}\n\n/**\n * Connect middleware to enable profiling of response lifecycle timing. To effectively profile\n * the response timing, this middleware needs to be called first when initializing your Express\n * App\n * @example\n * const app = express()\n * app.use(responseProfiler)\n * // other initialization ...\n * @param _req The request\n * @param res The response\n * @param next The next function\n */\nexport const responseProfiler = (_req: Request, res: Response<unknown, ResponseLocals>, next: NextFunction) => {\n res.locals.meta ??= {}\n res.locals.meta.profile = { startTime: Date.now() }\n next()\n}\n", "import type { Response } from 'express-serve-static-core'\n\nexport interface ResponseProfile {\n duration?: number\n endTime?: number\n startTime?: number\n}\n\nexport interface ResponseMetadata extends Record<string, unknown> {\n profile?: ResponseProfile\n}\n\nexport interface ResponseLocals extends Record<string, unknown> {\n meta?: ResponseMetadata\n}\n\n/**\n * Extracts response metadata from res.locals, computing profile duration if profiling was started.\n * @param res The Express response to extract metadata from.\n * @returns The metadata record including any profiling information.\n */\nexport const getResponseMetadata = <TLocals extends ResponseLocals>(res: Response<unknown, TLocals>): Record<string, unknown> => {\n const meta = res.locals.meta ?? {}\n // NOTE: We should do this somewhere else to better separate concerns\n const profile = meta.profile\n if (profile !== undefined) {\n const startTime = profile.startTime\n if (startTime !== undefined) {\n const endTime = Date.now()\n const duration = endTime - startTime\n meta.profile = {\n duration, endTime, startTime,\n }\n }\n }\n return meta\n}\n", "import { isError } from '@xylabs/typeof'\nimport type {\n NextFunction, Request, Response,\n} from 'express-serve-static-core'\n\nimport { getDefaultLogger } from '../../Logger/index.ts'\nimport type { ExpressError } from '../../Model/index.ts'\nimport type { ApiError } from './jsonApi/index.ts'\n\n/**\n * Express error handler that logs the error and sends a JSON:API-compliant error response.\n * @param err The error to handle, or undefined if no error.\n * @param req The incoming request.\n * @param res The outgoing response.\n * @param next The next middleware function.\n */\nexport const standardErrors = (err: ExpressError | undefined, req: Request, res: Response, next: NextFunction) => {\n if (!isError(err)) {\n next(err)\n return\n }\n getDefaultLogger().error(err.message)\n err.statusCode ??= 500\n\n const error: ApiError = {\n detail: err.message,\n status: String(err.statusCode),\n title: err.name,\n }\n\n res.status(err.statusCode).json(error)\n\n next(err)\n}\n", "import type {\n Request, RequestHandler, Response,\n} from 'express-serve-static-core'\n\nimport type { ResponseLocals } from './getResponseMetadata.js'\nimport { getResponseMetadata } from './getResponseMetadata.js'\n\ninterface TransformResponseLocals extends ResponseLocals {\n rawResponse?: boolean\n}\n\n/**\n * Flags the response to forgo the standard response envelope\n * and return the raw response body to the client\n * @param res The response to disable the standard response format on\n */\nexport const setRawResponseFormat = (res: Response): void => {\n res.locals.rawResponse = true\n}\n\n/**\n * Clears any flags on the response, allowing the response to\n * use the default standard response envelope\n * @param res The response to set to the standard response format\n */\nexport const clearRawResponseFormat = (res: Response): void => {\n res.locals.rawResponse = false\n}\n\n/**\n * Checks if there are any flags on the response that would cause it\n * to forgo the standard response envelope and return the raw response\n * body to the client\n * @param res\n * @returns True if there are any flags on the response, false otherwise\n */\nexport const isRawResponseFormatSet = (res: Response): boolean => {\n return res.locals.rawResponse === true\n}\n\n/**\n * Transforms each response to conform to the standard response format (compatible with JSON API)\n * @param body The original request body\n * @param _req The request\n * @param res The response\n * @returns The transformed response body\n */\nconst transformResponse = (body: unknown, _req: Request, res: Response<unknown, TransformResponseLocals>) => {\n return isRawResponseFormatSet(res)\n ? body\n : (res.statusCode >= 200 && res.statusCode < 300)\n ? { data: body, meta: getResponseMetadata(res) }\n : { error: body, meta: getResponseMetadata(res) }\n}\n\n/**\n * Connect middleware to enable the transform of all responses to match\n * the standard response format (compatible with JSON API)\n */\n\nexport const standardResponses: RequestHandler = (req, res, next) => {\n const json = res.json.bind(res)\n res.json = ((body: unknown) => {\n try {\n return json(transformResponse(body, req, res))\n } catch (ex) {\n next(ex)\n return res\n }\n }) as Response['json']\n next()\n}\n", "/**\n * Returns a shallow copy of the object with all null and undefined values removed.\n * @param obj The object to compact.\n * @returns A new object with only defined, non-null properties.\n */\nexport const compactObject = <T extends Record<string, unknown>>(obj: T) => {\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined && value !== null) {\n result[key] = value\n }\n }\n return result as T\n}\n", "import { isDefined } from '@xylabs/typeof'\n\n/** A function that parses a string value into the target type. */\nexport type ParseFunc<T = number> = (value: string) => T\n\n/**\n * @deprecated use zod instead\n */\nexport const tryParse = <T = number>(func: ParseFunc<T>, value?: string) => {\n try {\n const result = isDefined(value) ? func(value) : null\n if (!Number.isNaN(result) && result !== null) {\n return result\n }\n } catch {\n return\n }\n}\n", "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { isDefined, isPromise } from '@xylabs/typeof'\nimport type {\n NextFunction, Request, RequestHandler, Response,\n} from 'express-serve-static-core'\nimport * as z from 'zod/mini'\n\nimport { ReasonPhrases, StatusCodes } from '../HttpStatus.ts'\nimport type { ExpressError } from '../Model/index.ts'\n\nconst createExpressError = (message: string, errorName: string, statusCode: number): ExpressError => {\n const error = new Error(message) as ExpressError\n Object.defineProperty(error, 'name', {\n configurable: true,\n enumerable: false,\n value: errorName,\n writable: true,\n })\n error.statusCode = statusCode\n return error\n}\n\n/**\n * Empty Zod schema for requests with no parameters.\n */\nexport const EmptyParamsZod = z.catchall(z.object({}), z.string())\n\n/**\n * Empty Zod schema for requests with no query parameters.\n */\nexport const EmptyQueryParamsZod = z.catchall(z.object({}), z.union([z.string(), z.array(z.string())]))\n\n/**\n * Default validation schemas for request handler validator.\n */\nexport const ValidateRequestDefaults = {\n params: EmptyParamsZod,\n query: EmptyQueryParamsZod,\n body: z.optional(z.json()),\n response: z.optional(z.json()),\n}\n\ntype ValidatableRequestKey = 'params' | 'query' | 'body'\n\n/**\n * Factory for Express middleware that validates request and response objects using Zod schemas.\n * @param schemas The Zod schemas to use for validation.\n * @returns A middleware function for validating requests and responses.\n */\nexport function requestHandlerValidator<\n TParams extends typeof EmptyQueryParamsZod | z.core.$ZodType<Record<string, string>> = typeof EmptyQueryParamsZod,\n TQuery extends typeof EmptyQueryParamsZod | z.core.$ZodType<Record<string, string | string[]>> = typeof EmptyQueryParamsZod,\n TBody extends z.core.$ZodType<unknown> = z.core.$ZodType<unknown>,\n TResponse extends z.core.$ZodType<unknown> = z.core.$ZodType<unknown>,\n>(schemas?: Partial<{\n body: TBody\n params: TParams\n query: TQuery\n response: TResponse\n}>) {\n type Params = z.infer<TParams>\n type Query = z.infer<TQuery>\n type Body = z.infer<TBody>\n type Res = z.infer<TResponse>\n const validators = { ...ValidateRequestDefaults, ...schemas }\n\n return (handler: (req: Request<Params, Res, Body, Query>, res: Response<Res>, next: NextFunction) => unknown): RequestHandler => {\n return async (req: Request, res: Response, next: NextFunction) => {\n const originalJson = res.json.bind(res)\n try {\n // Validate incoming request\n const errors: string[] = []\n const keys: ValidatableRequestKey[] = ['params', 'query', 'body']\n for (const key of keys) {\n const validator = validators[key]\n const result = z.safeParse(validator, req[key])\n if (result.success) {\n if (isDefined(result.data)) Object.assign(req[key], result.data)\n } else {\n errors.push(\n ...result.error.issues.map(\n issue => (issue.path.length === 0)\n ? `${key}: ${issue.message}`\n : `${key}.${issue.path.join('.')}: ${issue.message}`,\n ),\n )\n }\n }\n\n // If there were validation errors, short-circuit and return Bad Request\n if (errors.length > 0) {\n const message = errors.join('; ')\n const err = createExpressError(message, ReasonPhrases.BAD_REQUEST, StatusCodes.BAD_REQUEST)\n next(err)\n return false\n }\n\n // Wrap res.json to validate outgoing response\n res.json = (data: any) => {\n const result = z.safeParse(validators.response, data)\n if (result.success) {\n return originalJson(result.data)\n }\n const message = result.error.issues.map(\n issue => (issue.path.length === 0)\n ? `response: ${issue.message}`\n : `response.${issue.path.join('.')}: ${issue.message}`,\n ).join('; ')\n const err = createExpressError(message, ReasonPhrases.INTERNAL_SERVER_ERROR, StatusCodes.INTERNAL_SERVER_ERROR)\n\n // Restore original JSON function in case the error handler wants to use it\n res.json = originalJson\n throw err\n }\n\n // Automatically handle async errors\n const typedReq = req as Request<Params, Res, Body, Query>\n const typedRes = res as Response<Res>\n const result: unknown = handler(typedReq, typedRes, next)\n if (isPromise(result)) {\n const resultPromise: Promise<unknown> = result\n await resultPromise\n }\n } catch (err) {\n res.json = originalJson\n next(err)\n }\n }\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["format", "format", "combine", "timestamp", "format", "header", "setting", "name", "isError", "isError", "json", "isDefined", "isDefined", "result", "isDefined"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  import type { Application } from 'express-serve-static-core';
2
2
  /**
3
3
  * Registers middleware that increments per-path request counters and exposes a /stats endpoint.
4
- * @param app The Express application to attach counters to.
4
+ * @param app The Express app to attach counters to.
5
5
  */
6
6
  export declare const useRequestCounters: (app: Application) => void;
7
7
  //# sourceMappingURL=counters.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xylabs/express",
3
- "version": "6.1.3",
3
+ "version": "7.0.0",
4
4
  "description": "SDK for base code for Api repos that use express and deploy on AWS ECS",
5
5
  "keywords": [
6
6
  "xylabs",
@@ -46,29 +46,31 @@
46
46
  "README.md"
47
47
  ],
48
48
  "dependencies": {
49
- "@xylabs/assert": "~6.1.3",
50
- "@xylabs/logger": "~6.1.3",
51
- "@xylabs/typeof": "~6.1.3"
49
+ "@xylabs/typeof": "~7.0.0",
50
+ "@xylabs/logger": "~7.0.0",
51
+ "@xylabs/assert": "~7.0.0"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@types/body-parser": "^1.19.6",
55
55
  "@types/connect": "^3.4.38",
56
56
  "@types/express-serve-static-core": "^5.1.1",
57
- "@types/node": "^25.9.2",
58
- "@xylabs/toolchain": "^8.1.20",
59
- "@xylabs/tsconfig": "^8.1.20",
60
- "body-parser": "^2.2.2",
57
+ "@types/node": "^26.0.1",
58
+ "@xylabs/toolchain": "^8.4.1",
59
+ "@xylabs/tsconfig": "^8.4.1",
60
+ "body-parser": "^2.3.0",
61
+ "browserslist": "4.28.4",
61
62
  "connect": "^3.7.0",
62
- "eslint": "^10.4.1",
63
+ "eslint": "^10.5.0",
64
+ "eslint-import-resolver-typescript": "^4.4.5",
63
65
  "rollbar": "^3.1.0",
64
66
  "typescript": "^6.0.3",
65
- "vite": "^8.0.16",
66
- "vitest": "^4.1.8",
67
+ "vite": "^8.1.0",
68
+ "vitest": "^4.1.9",
67
69
  "vitest-mock-extended": "^4.0.0",
68
70
  "winston": "^3.19.0",
69
71
  "winston-transport": "^4.9.0",
70
72
  "zod": "^4.4.3",
71
- "@xylabs/vitest-extended": "~6.1.3"
73
+ "@xylabs/vitest-extended": "~7.0.0"
72
74
  },
73
75
  "peerDependencies": {
74
76
  "body-parser": "^2.2",