express-zod-api 5.0.0 → 5.2.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,62 @@
2
2
 
3
3
  ## Version 5
4
4
 
5
+ ### v5.2.0
6
+
7
+ - Feature #254: the ability to configure routes for serving static files.
8
+ - Use `new ServeStatic()` with the same arguments as `express.static()`.
9
+ - You can find the documentation on these arguments here: http://expressjs.com/en/4x/api.html#express.static
10
+
11
+ ```typescript
12
+ import { Routing, ServeStatic } from "express-zod-api";
13
+ import path from "path";
14
+
15
+ const routing: Routing = {
16
+ // path /public serves static files from ./assets
17
+ public: new ServeStatic(path.join(__dirname, "assets"), {
18
+ dotfiles: "deny",
19
+ index: false,
20
+ redirect: false,
21
+ }),
22
+ };
23
+ ```
24
+
25
+ ### v5.1.0
26
+
27
+ - No changes.
28
+
29
+ ### v5.1.0-beta2
30
+
31
+ - Fixing a warning message when using `testEndpoint()` method.
32
+
33
+ ### v5.1.0-beta1
34
+
35
+ - Feature #252: a helper method for testing your endpoints: `testEndpoint()`.
36
+ - Requires `jest` (and optionally `@types/jest`) to be installed.
37
+ - The method helps to mock the request, response, config and logger required to execute the endpoint.
38
+ - The method executes the endpoint and returns the created mocks.
39
+ - After that you only need to assert your expectations in the test.
40
+
41
+ ```typescript
42
+ import { testEndpoint } from "express-zod-api";
43
+
44
+ test("should respond successfully", async () => {
45
+ const { responseMock, loggerMock } = await testEndpoint({
46
+ endpoint: yourEndpoint,
47
+ requestProps: {
48
+ method: "POST",
49
+ body: { ... },
50
+ },
51
+ });
52
+ expect(loggerMock.error).toBeCalledTimes(0);
53
+ expect(responseMock.status).toBeCalledWith(200);
54
+ expect(responseMock.json).toBeCalledWith({
55
+ status: "success",
56
+ data: { ... },
57
+ });
58
+ });
59
+ ```
60
+
5
61
  ### v5.0.0
6
62
 
7
63
  - No changes.
package/README.md CHANGED
@@ -35,14 +35,16 @@ Start your API server with I/O schema validation and custom middlewares in minut
35
35
  7. [Non-object response](#non-object-response) including file downloads
36
36
  8. [File uploads](#file-uploads)
37
37
  9. [Customizing logger](#customizing-logger)
38
- 10. [Usage with your own express app](#usage-with-your-own-express-app)
38
+ 10. [Connect to your own express app](#connect-to-your-own-express-app)
39
39
  11. [Multiple schemas for one route](#multiple-schemas-for-one-route)
40
- 12. [Customizing input sources](#customizing-input-sources)
41
- 13. [Enabling HTTPS](#enabling-https)
42
- 14. [Exporting endpoint types to frontend](#exporting-endpoint-types-to-frontend)
43
- 15. [Creating a documentation](#creating-a-documentation)
44
- 5. [Known issues](#known-issues)
45
- 1. [Excessive properties in endpoint output](#excessive-properties-in-endpoint-output)
40
+ 12. [Serving static files](#serving-static-files)
41
+ 13. [Customizing input sources](#customizing-input-sources)
42
+ 14. [Enabling HTTPS](#enabling-https)
43
+ 15. [Informing the frontend about the API](#informing-the-frontend-about-the-api)
44
+ 16. [Creating a documentation](#creating-a-documentation)
45
+ 5. [Additional hints](#additional-hints)
46
+ 1. [How to test endpoints](#how-to-test-endpoints)
47
+ 2. [Excessive properties in endpoint output](#excessive-properties-in-endpoint-output)
46
48
  6. [Your input to my output](#your-input-to-my-output)
47
49
 
48
50
  You can find the release notes in [Changelog](CHANGELOG.md). Along with recommendations for migrating from
@@ -504,7 +506,7 @@ const logger = winston.createLogger({
504
506
  const config = createConfig({ logger /* ..., */ });
505
507
  ```
506
508
 
507
- ## Usage with your own express app
509
+ ## Connect to your own express app
508
510
 
509
511
  If you already have your own configured express application, or you find the library settings not enough,
510
512
  you can connect your routing to the app instead of using `createServer()`.
@@ -553,6 +555,26 @@ const routing: Routing = {
553
555
  };
554
556
  ```
555
557
 
558
+ ## Serving static files
559
+
560
+ In case you want your server to serve static files, you can use `new ServeStatic()` in `Routing` using the arguments
561
+ similar to `express.static()`.
562
+ The documentation on these arguments you may find [here](http://expressjs.com/en/4x/api.html#express.static).
563
+
564
+ ```typescript
565
+ import { Routing, ServeStatic } from "express-zod-api";
566
+ import path from "path";
567
+
568
+ const routing: Routing = {
569
+ // path /public serves static files from ./assets
570
+ public: new ServeStatic(path.join(__dirname, "assets"), {
571
+ dotfiles: "deny",
572
+ index: false,
573
+ redirect: false,
574
+ }),
575
+ };
576
+ ```
577
+
556
578
  ## Customizing input sources
557
579
 
558
580
  You can customize the list of `request` properties that are combined into `input` that is being validated and available
@@ -604,23 +626,46 @@ At least you need to specify the port or socket (usually it is 443), certificate
604
626
  certifying authority. For example, you can acquire a free TLS certificate for your API at
605
627
  [Let's Encrypt](https://letsencrypt.org/).
606
628
 
607
- ## Exporting endpoint types to frontend
629
+ ## Informing the frontend about the API
608
630
 
609
- You can export only the types of your endpoints for your frontend. Here is an approach:
631
+ You can inform your frontend about the I/O types of your endpoints by exporting them to `.d.ts` files (they only
632
+ contain types without any executable code). To achieve that you are going to need an additional `tsconfig.dts.json`
633
+ file with the following content:
610
634
 
611
- ```typescript
612
- export type YourEndpointType = typeof yourEndpoint;
635
+ ```json
636
+ {
637
+ "extends": "./tsconfig.json",
638
+ "compilerOptions": {
639
+ "outDir": "dts",
640
+ "declaration": true,
641
+ "emitDeclarationOnly": true
642
+ }
643
+ }
613
644
  ```
614
645
 
615
- Then use provided helpers to obtain their input and response types:
646
+ Most likely you have a file with all the configured routing, in which you can do the following:
616
647
 
617
648
  ```typescript
618
649
  import { EndpointInput, EndpointResponse } from "express-zod-api";
619
- import type { YourEndpointType } from "../your/backend";
620
- // ^---- please note the import syntax of the type only
621
650
 
622
- type YourEndpointInput = EndpointInput<YourEndpointType>;
623
- type YourEndpointResponse = EndpointResponse<YourEndpointType>;
651
+ export type YourEndpointInput = EndpointInput<typeof yourEndpoint>;
652
+ export type YourEndpointResponse = EndpointResponse<typeof yourEndpoint>;
653
+ ```
654
+
655
+ By executing the following command you'll get the compiled `/dts/routing.d.ts` file.
656
+
657
+ ```shell
658
+ yarn tsc -p tsconfig.dts.json
659
+ ```
660
+
661
+ The command might become a part of your CI/CD.
662
+ Then import the I/O type of your endpoint from the compiled file using `import type` syntax on the frontend.
663
+
664
+ ```typescript
665
+ import type {
666
+ YourEndpointInput,
667
+ YourEndpointResponse,
668
+ } from "../your_backend/dts/routing";
624
669
  ```
625
670
 
626
671
  ## Creating a documentation
@@ -660,7 +705,37 @@ const exampleEndpoint = defaultEndpointsFactory.build({
660
705
  _See the example of the generated documentation
661
706
  [here](https://github.com/RobinTail/express-zod-api/blob/master/example/example.swagger.yaml)_
662
707
 
663
- # Known issues
708
+ # Additional hints
709
+
710
+ ## How to test endpoints
711
+
712
+ The way to test endpoints is to mock the request, response, and logger objects, invoke the `execute()` method, and
713
+ assert the expectations for calls of certain mocked methods. The library provides a special method that makes mocking
714
+ easier, it requires `jest` (and optionally `@types/jest`) to be installed, so the test might look the following way:
715
+
716
+ ```typescript
717
+ import { testEndpoint } from "express-zod-api";
718
+
719
+ test("should respond successfully", async () => {
720
+ const { responseMock, loggerMock } = await testEndpoint({
721
+ endpoint: yourEndpoint,
722
+ requestProps: {
723
+ method: "POST", // default: GET
724
+ body: { ... },
725
+ },
726
+ // responseProps, configProps, loggerProps
727
+ });
728
+ expect(loggerMock.error).toBeCalledTimes(0);
729
+ expect(responseMock.status).toBeCalledWith(200);
730
+ expect(responseMock.json).toBeCalledWith({
731
+ status: "success",
732
+ data: { ... },
733
+ });
734
+ });
735
+ ```
736
+
737
+ _This method is optimized for the standard result handler. With the flexibility to customize, you can add additional
738
+ properties as needed._
664
739
 
665
740
  ## Excessive properties in endpoint output
666
741
 
@@ -0,0 +1,10 @@
1
+ import { Endpoint } from "./endpoint";
2
+ import { Method } from "./method";
3
+ export declare class DependsOnMethod {
4
+ readonly methods: {
5
+ [K in Method]?: Endpoint<any, any, any, any, K, any, any> | Endpoint<any, any, any, any, Method, any, any>;
6
+ };
7
+ constructor(methods: {
8
+ [K in Method]?: Endpoint<any, any, any, any, K, any, any> | Endpoint<any, any, any, any, Method, any, any>;
9
+ });
10
+ }
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DependsOnMethod = void 0;
4
+ const errors_1 = require("./errors");
5
+ class DependsOnMethod {
6
+ constructor(methods) {
7
+ this.methods = methods;
8
+ Object.keys(methods).forEach((key) => {
9
+ var _a, _b;
10
+ if (key in methods) {
11
+ const endpointMethods = ((_a = methods[key]) === null || _a === void 0 ? void 0 : _a.getMethods()) || [];
12
+ if (!endpointMethods.includes(key)) {
13
+ throw new errors_1.DependsOnMethodError(`The endpoint assigned to the '${key}' parameter must have at least this method in its specification.\n` +
14
+ "This error should prevent mistakes during the development process.\n" +
15
+ "Example:\n\n" +
16
+ `new ${this.constructor.name}({\n` +
17
+ ` ${key}: endpointsFactory.build({\n` +
18
+ ` methods: ['${key}', ` +
19
+ ((((_b = methods[key]) === null || _b === void 0 ? void 0 : _b.getMethods()) || [])
20
+ .map((m) => `'${m}'`)
21
+ .join(", ") || "...") +
22
+ "]\n" +
23
+ ` // or method: '${key}'\n` +
24
+ " ...\n" +
25
+ " })\n" +
26
+ "});\n");
27
+ }
28
+ }
29
+ });
30
+ }
31
+ }
32
+ exports.DependsOnMethod = DependsOnMethod;
33
+ //# sourceMappingURL=depends-on-method.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"depends-on-method.js","sourceRoot":"","sources":["../src/depends-on-method.ts"],"names":[],"mappings":";;;AACA,qCAAgD;AAGhD,MAAa,eAAe;IAC1B,YACkB,OAIf;QAJe,YAAO,GAAP,OAAO,CAItB;QAEA,MAAM,CAAC,IAAI,CAAC,OAAO,CAA8B,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;;YACjE,IAAI,GAAG,IAAI,OAAO,EAAE;gBAClB,MAAM,eAAe,GAAG,CAAA,MAAA,OAAO,CAAC,GAAG,CAAC,0CAAE,UAAU,EAAE,KAAI,EAAE,CAAC;gBACzD,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;oBAClC,MAAM,IAAI,6BAAoB,CAC5B,iCAAiC,GAAG,oEAAoE;wBACtG,sEAAsE;wBACtE,cAAc;wBACd,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,MAAM;wBAClC,KAAK,GAAG,8BAA8B;wBACtC,kBAAkB,GAAG,KAAK;wBAC1B,CAAC,CAAC,CAAA,MAAA,OAAO,CAAC,GAAG,CAAC,0CAAE,UAAU,EAAE,KAAI,EAAE,CAAC;6BAChC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC;6BACpB,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;wBACvB,KAAK;wBACL,sBAAsB,GAAG,KAAK;wBAC9B,WAAW;wBACX,QAAQ;wBACR,OAAO,CACV,CAAC;iBACH;aACF;QACH,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAhCD,0CAgCC"}
package/dist/index.d.ts CHANGED
@@ -7,11 +7,14 @@ export { createApiResponse } from "./api-response";
7
7
  export { createLogger } from "./logger";
8
8
  export { createMiddleware } from "./middleware";
9
9
  export { createResultHandler, defaultResultHandler } from "./result-handler";
10
- export { Routing, DependsOnMethod } from "./routing";
10
+ export { DependsOnMethod } from "./depends-on-method";
11
+ export { ServeStatic } from "./serve-static";
12
+ export { Routing } from "./routing";
11
13
  export { createServer, attachRouting } from "./server";
12
14
  export { OpenAPI } from "./open-api";
13
15
  export { OpenAPIError, DependsOnMethodError, RoutingError } from "./errors";
14
16
  export { withMeta } from "./metadata";
17
+ export { testEndpoint } from "./mock";
15
18
  import * as z from "./extend-zod";
16
19
  import createHttpError from "http-errors";
17
20
  export { createHttpError, z };
package/dist/index.js CHANGED
@@ -22,7 +22,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
22
22
  return (mod && mod.__esModule) ? mod : { "default": mod };
23
23
  };
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.z = exports.createHttpError = exports.withMeta = exports.RoutingError = exports.DependsOnMethodError = exports.OpenAPIError = exports.OpenAPI = exports.attachRouting = exports.createServer = exports.DependsOnMethod = exports.defaultResultHandler = exports.createResultHandler = exports.createMiddleware = exports.createLogger = exports.createApiResponse = exports.markOutput = exports.defaultEndpointsFactory = exports.EndpointsFactory = exports.AbstractEndpoint = exports.createConfig = void 0;
25
+ exports.z = exports.createHttpError = exports.testEndpoint = exports.withMeta = exports.RoutingError = exports.DependsOnMethodError = exports.OpenAPIError = exports.OpenAPI = exports.attachRouting = exports.createServer = exports.ServeStatic = exports.DependsOnMethod = exports.defaultResultHandler = exports.createResultHandler = exports.createMiddleware = exports.createLogger = exports.createApiResponse = exports.markOutput = exports.defaultEndpointsFactory = exports.EndpointsFactory = exports.AbstractEndpoint = exports.createConfig = void 0;
26
26
  var config_type_1 = require("./config-type");
27
27
  Object.defineProperty(exports, "createConfig", { enumerable: true, get: function () { return config_type_1.createConfig; } });
28
28
  var endpoint_1 = require("./endpoint");
@@ -41,8 +41,10 @@ Object.defineProperty(exports, "createMiddleware", { enumerable: true, get: func
41
41
  var result_handler_1 = require("./result-handler");
42
42
  Object.defineProperty(exports, "createResultHandler", { enumerable: true, get: function () { return result_handler_1.createResultHandler; } });
43
43
  Object.defineProperty(exports, "defaultResultHandler", { enumerable: true, get: function () { return result_handler_1.defaultResultHandler; } });
44
- var routing_1 = require("./routing");
45
- Object.defineProperty(exports, "DependsOnMethod", { enumerable: true, get: function () { return routing_1.DependsOnMethod; } });
44
+ var depends_on_method_1 = require("./depends-on-method");
45
+ Object.defineProperty(exports, "DependsOnMethod", { enumerable: true, get: function () { return depends_on_method_1.DependsOnMethod; } });
46
+ var serve_static_1 = require("./serve-static");
47
+ Object.defineProperty(exports, "ServeStatic", { enumerable: true, get: function () { return serve_static_1.ServeStatic; } });
46
48
  var server_1 = require("./server");
47
49
  Object.defineProperty(exports, "createServer", { enumerable: true, get: function () { return server_1.createServer; } });
48
50
  Object.defineProperty(exports, "attachRouting", { enumerable: true, get: function () { return server_1.attachRouting; } });
@@ -54,6 +56,8 @@ Object.defineProperty(exports, "DependsOnMethodError", { enumerable: true, get:
54
56
  Object.defineProperty(exports, "RoutingError", { enumerable: true, get: function () { return errors_1.RoutingError; } });
55
57
  var metadata_1 = require("./metadata");
56
58
  Object.defineProperty(exports, "withMeta", { enumerable: true, get: function () { return metadata_1.withMeta; } });
59
+ var mock_1 = require("./mock");
60
+ Object.defineProperty(exports, "testEndpoint", { enumerable: true, get: function () { return mock_1.testEndpoint; } });
57
61
  const z = __importStar(require("./extend-zod"));
58
62
  exports.z = z;
59
63
  const http_errors_1 = __importDefault(require("http-errors"));
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6CAA2D;AAAlD,2GAAA,YAAY,OAAA;AACrB,uCAKoB;AAJlB,4GAAA,gBAAgB,OAAA;AAMlB,yDAAgF;AAAvE,qHAAA,gBAAgB,OAAA;AAAE,4HAAA,uBAAuB,OAAA;AAClD,mDAAoE;AAArC,4GAAA,UAAU,OAAA;AACzC,+CAAmD;AAA1C,iHAAA,iBAAiB,OAAA;AAC1B,mCAAwC;AAA/B,sGAAA,YAAY,OAAA;AACrB,2CAAgD;AAAvC,8GAAA,gBAAgB,OAAA;AACzB,mDAA6E;AAApE,qHAAA,mBAAmB,OAAA;AAAE,sHAAA,oBAAoB,OAAA;AAClD,qCAAqD;AAAnC,0GAAA,eAAe,OAAA;AACjC,mCAAuD;AAA9C,sGAAA,YAAY,OAAA;AAAE,uGAAA,aAAa,OAAA;AACpC,uCAAqC;AAA5B,mGAAA,OAAO,OAAA;AAChB,mCAA4E;AAAnE,sGAAA,YAAY,OAAA;AAAE,8GAAA,oBAAoB,OAAA;AAAE,sGAAA,YAAY,OAAA;AACzD,uCAAsC;AAA7B,oGAAA,QAAQ,OAAA;AAEjB,gDAAkC;AAGR,cAAC;AAF3B,8DAA0C;AAEjC,0BAFF,qBAAe,CAEE"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6CAA2D;AAAlD,2GAAA,YAAY,OAAA;AACrB,uCAKoB;AAJlB,4GAAA,gBAAgB,OAAA;AAMlB,yDAAgF;AAAvE,qHAAA,gBAAgB,OAAA;AAAE,4HAAA,uBAAuB,OAAA;AAClD,mDAAoE;AAArC,4GAAA,UAAU,OAAA;AACzC,+CAAmD;AAA1C,iHAAA,iBAAiB,OAAA;AAC1B,mCAAwC;AAA/B,sGAAA,YAAY,OAAA;AACrB,2CAAgD;AAAvC,8GAAA,gBAAgB,OAAA;AACzB,mDAA6E;AAApE,qHAAA,mBAAmB,OAAA;AAAE,sHAAA,oBAAoB,OAAA;AAClD,yDAAsD;AAA7C,oHAAA,eAAe,OAAA;AACxB,+CAA6C;AAApC,2GAAA,WAAW,OAAA;AAEpB,mCAAuD;AAA9C,sGAAA,YAAY,OAAA;AAAE,uGAAA,aAAa,OAAA;AACpC,uCAAqC;AAA5B,mGAAA,OAAO,OAAA;AAChB,mCAA4E;AAAnE,sGAAA,YAAY,OAAA;AAAE,8GAAA,oBAAoB,OAAA;AAAE,sGAAA,YAAY,OAAA;AACzD,uCAAsC;AAA7B,oGAAA,QAAQ,OAAA;AACjB,+BAAsC;AAA7B,oGAAA,YAAY,OAAA;AAErB,gDAAkC;AAGR,cAAC;AAF3B,8DAA0C;AAEjC,0BAFF,qBAAe,CAEE"}
package/dist/mock.d.ts ADDED
@@ -0,0 +1,30 @@
1
+ /// <reference types="qs" />
2
+ /// <reference types="jest" />
3
+ import { Request, Response } from "express";
4
+ import { Logger } from "winston";
5
+ import { CommonConfig } from "./config-type";
6
+ import { AbstractEndpoint } from "./endpoint";
7
+ interface TestEndpointProps<REQ, RES, LOG> {
8
+ endpoint: AbstractEndpoint;
9
+ requestProps?: REQ;
10
+ responseProps?: RES;
11
+ configProps?: Partial<CommonConfig>;
12
+ loggerProps?: LOG;
13
+ /** @deprecated for testing purposes only */
14
+ __noJest?: boolean;
15
+ }
16
+ /**
17
+ * @description You need to install Jest and probably @types/jest to use this method
18
+ */
19
+ export declare const testEndpoint: <REQ extends Partial<Record<keyof Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>, any>> | undefined = undefined, RES extends Partial<Record<keyof Response<any, Record<string, any>>, any>> | undefined = undefined, LOG extends Partial<Record<keyof Logger, any>> | undefined = undefined>({ endpoint, requestProps, responseProps, configProps, loggerProps, __noJest, }: TestEndpointProps<REQ, RES, LOG>) => Promise<{
20
+ requestMock: {
21
+ method: string;
22
+ } & Record<"header", jest.Mock<any, any>> & (REQ extends undefined ? {} : REQ);
23
+ responseMock: {
24
+ writableEnded: boolean;
25
+ statusCode: number;
26
+ statusMessage: string;
27
+ } & Record<"json" | "status" | "set" | "end", jest.Mock<any, any>> & (RES extends undefined ? {} : RES);
28
+ loggerMock: Record<"error" | "warn" | "debug" | "info", jest.Mock<any, any>> & (LOG extends undefined ? {} : LOG);
29
+ }>;
30
+ export {};
package/dist/mock.js ADDED
@@ -0,0 +1,59 @@
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.testEndpoint = void 0;
7
+ const http_1 = __importDefault(require("http"));
8
+ const mime_1 = require("./mime");
9
+ /**
10
+ * @description You need to install Jest and probably @types/jest to use this method
11
+ */
12
+ const testEndpoint = async ({ endpoint, requestProps, responseProps, configProps, loggerProps, __noJest, }) => {
13
+ if (!jest || __noJest) {
14
+ throw new Error("You need to install Jest in order to use testEndpoint().");
15
+ }
16
+ const requestMock = {
17
+ method: "GET",
18
+ header: jest.fn(() => mime_1.mimeJson),
19
+ ...requestProps,
20
+ };
21
+ const responseMock = {
22
+ writableEnded: false,
23
+ statusCode: 200,
24
+ statusMessage: http_1.default.STATUS_CODES[200],
25
+ set: jest.fn(() => responseMock),
26
+ status: jest.fn((code) => {
27
+ responseMock.statusCode = code;
28
+ responseMock.statusMessage = http_1.default.STATUS_CODES[code];
29
+ return responseMock;
30
+ }),
31
+ json: jest.fn(() => responseMock),
32
+ end: jest.fn(() => {
33
+ responseMock.writableEnded = true;
34
+ return responseMock;
35
+ }),
36
+ ...responseProps,
37
+ };
38
+ const loggerMock = {
39
+ info: jest.fn(),
40
+ warn: jest.fn(),
41
+ error: jest.fn(),
42
+ debug: jest.fn(),
43
+ ...loggerProps,
44
+ };
45
+ const configMock = {
46
+ cors: false,
47
+ logger: loggerMock,
48
+ ...configProps,
49
+ };
50
+ await endpoint.execute({
51
+ request: requestMock,
52
+ response: responseMock,
53
+ config: configMock,
54
+ logger: loggerMock,
55
+ });
56
+ return { requestMock, responseMock, loggerMock };
57
+ };
58
+ exports.testEndpoint = testEndpoint;
59
+ //# sourceMappingURL=mock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock.js","sourceRoot":"","sources":["../src/mock.ts"],"names":[],"mappings":";;;;;;AACA,gDAAwB;AAIxB,iCAAkC;AAYlC;;GAEG;AACI,MAAM,YAAY,GAAG,KAAK,EAI/B,EACA,QAAQ,EACR,YAAY,EACZ,aAAa,EACb,WAAW,EACX,WAAW,EACX,QAAQ,GACyB,EAAE,EAAE;IACrC,IAAI,CAAC,IAAI,IAAI,QAAQ,EAAE;QACrB,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;KAC7E;IACD,MAAM,WAAW,GAGhB;QACC,MAAM,EAAE,KAAK;QACb,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,eAAQ,CAAC;QAC/B,GAAG,YAAY;KAChB,CAAC;IACF,MAAM,YAAY,GAOjB;QACC,aAAa,EAAE,KAAK;QACpB,UAAU,EAAE,GAAG;QACf,aAAa,EAAE,cAAI,CAAC,YAAY,CAAC,GAAG,CAAC;QACrC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC;QAChC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,IAAY,EAAE,EAAE;YAC/B,YAAY,CAAC,UAAU,GAAG,IAAI,CAAC;YAC/B,YAAY,CAAC,aAAa,GAAG,cAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;YACrD,OAAO,YAAY,CAAC;QACtB,CAAC,CAAC;QACF,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC;QACjC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE;YAChB,YAAY,CAAC,aAAa,GAAG,IAAI,CAAC;YAClC,OAAO,YAAY,CAAC;QACtB,CAAC,CAAC;QACF,GAAG,aAAa;KACjB,CAAC;IACF,MAAM,UAAU,GAGf;QACC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;QACf,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;QACf,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE;QAChB,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE;QAChB,GAAG,WAAW;KACf,CAAC;IACF,MAAM,UAAU,GAAG;QACjB,IAAI,EAAE,KAAK;QACX,MAAM,EAAE,UAAU;QAClB,GAAG,WAAW;KACf,CAAC;IACF,MAAM,QAAQ,CAAC,OAAO,CAAC;QACrB,OAAO,EAAE,WAAiC;QAC1C,QAAQ,EAAE,YAAmC;QAC7C,MAAM,EAAE,UAA0B;QAClC,MAAM,EAAE,UAA+B;KACxC,CAAC,CAAC;IACH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;AACnD,CAAC,CAAC;AArEW,QAAA,YAAY,gBAqEvB"}
package/dist/open-api.js CHANGED
@@ -9,7 +9,7 @@ class OpenAPI extends openapi3_ts_1.OpenApiBuilder {
9
9
  constructor({ routing, config, title, version, serverUrl, successfulResponseDescription = "Successful response", errorResponseDescription = "Error response", }) {
10
10
  super();
11
11
  this.addInfo({ title, version }).addServer({ url: serverUrl });
12
- const cb = (endpoint, path, _method) => {
12
+ const endpointCb = (endpoint, path, _method) => {
13
13
  var _a, _b;
14
14
  const method = _method;
15
15
  const commonParams = { path, method, endpoint };
@@ -47,7 +47,7 @@ class OpenAPI extends openapi3_ts_1.OpenApiBuilder {
47
47
  [method]: operation,
48
48
  });
49
49
  };
50
- (0, routing_1.routingCycle)({ routing, cb });
50
+ (0, routing_1.routingCycle)({ routing, endpointCb });
51
51
  }
52
52
  }
53
53
  exports.OpenAPI = OpenAPI;
@@ -1 +1 @@
1
- {"version":3,"file":"open-api.js","sourceRoot":"","sources":["../src/open-api.ts"],"names":[],"mappings":";;;AAAA,6CAA8D;AAC9D,qDAAuD;AAGvD,yDAK4B;AAC5B,uCAAsE;AAYtE,MAAa,OAAQ,SAAQ,4BAAc;IACzC,YAAmB,EACjB,OAAO,EACP,MAAM,EACN,KAAK,EACL,OAAO,EACP,SAAS,EACT,6BAA6B,GAAG,qBAAqB,EACrD,wBAAwB,GAAG,gBAAgB,GAC3B;QAChB,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QAC/D,MAAM,EAAE,GAA6B,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;;YAC/D,MAAM,MAAM,GAAG,OAAiB,CAAC;YACjC,MAAM,YAAY,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;YAChD,MAAM,YAAY,GAChB,CAAA,MAAA,MAAM,CAAC,YAAY,0CAAG,MAAM,CAAC,KAAI,oCAAmB,CAAC,MAAM,CAAC,CAAC;YAC/D,MAAM,cAAc,GAAG,IAAA,sCAAmB,EAAC;gBACzC,GAAG,YAAY;gBACf,YAAY;aACb,CAAC,CAAC;YACH,MAAM,SAAS,GAAoB;gBACjC,SAAS,EAAE;oBACT,KAAK,EAAE,IAAA,iCAAc,EAAC;wBACpB,GAAG,YAAY;wBACf,WAAW,EAAE,6BAA6B;wBAC1C,UAAU,EAAE,IAAI;qBACjB,CAAC;oBACF,KAAK,EAAE,IAAA,iCAAc,EAAC;wBACpB,GAAG,YAAY;wBACf,WAAW,EAAE,wBAAwB;wBACrC,UAAU,EAAE,KAAK;qBAClB,CAAC;iBACH;aACF,CAAC;YACF,IAAI,QAAQ,CAAC,cAAc,EAAE,EAAE;gBAC7B,SAAS,CAAC,WAAW,GAAG,QAAQ,CAAC,cAAc,EAAE,CAAC;aACnD;YACD,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE;gBAC7B,SAAS,CAAC,UAAU,GAAG,cAAc,CAAC;aACvC;YACD,IAAI,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;gBACjC,SAAS,CAAC,WAAW,GAAG,IAAA,gCAAa,EAAC,YAAY,CAAC,CAAC;aACrD;YACD,MAAM,qBAAqB,GAAG,IAAA,uCAAoB,EAAC,IAAI,CAAC,CAAC;YACzD,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE;gBAClC,GAAG,CAAC,CAAA,MAAA,IAAI,CAAC,OAAO,CAAC,KAAK,0CAAG,qBAAqB,CAAC,KAAI,EAAE,CAAC;gBACtD,CAAC,MAAM,CAAC,EAAE,SAAS;aACpB,CAAC,CAAC;QACL,CAAC,CAAC;QACF,IAAA,sBAAY,EAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;IAChC,CAAC;CACF;AApDD,0BAoDC"}
1
+ {"version":3,"file":"open-api.js","sourceRoot":"","sources":["../src/open-api.ts"],"names":[],"mappings":";;;AAAA,6CAA8D;AAC9D,qDAAuD;AAGvD,yDAK4B;AAC5B,uCAAsE;AAYtE,MAAa,OAAQ,SAAQ,4BAAc;IACzC,YAAmB,EACjB,OAAO,EACP,MAAM,EACN,KAAK,EACL,OAAO,EACP,SAAS,EACT,6BAA6B,GAAG,qBAAqB,EACrD,wBAAwB,GAAG,gBAAgB,GAC3B;QAChB,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QAC/D,MAAM,UAAU,GAAqC,CACnD,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,EAAE;;YACF,MAAM,MAAM,GAAG,OAAiB,CAAC;YACjC,MAAM,YAAY,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;YAChD,MAAM,YAAY,GAChB,CAAA,MAAA,MAAM,CAAC,YAAY,0CAAG,MAAM,CAAC,KAAI,oCAAmB,CAAC,MAAM,CAAC,CAAC;YAC/D,MAAM,cAAc,GAAG,IAAA,sCAAmB,EAAC;gBACzC,GAAG,YAAY;gBACf,YAAY;aACb,CAAC,CAAC;YACH,MAAM,SAAS,GAAoB;gBACjC,SAAS,EAAE;oBACT,KAAK,EAAE,IAAA,iCAAc,EAAC;wBACpB,GAAG,YAAY;wBACf,WAAW,EAAE,6BAA6B;wBAC1C,UAAU,EAAE,IAAI;qBACjB,CAAC;oBACF,KAAK,EAAE,IAAA,iCAAc,EAAC;wBACpB,GAAG,YAAY;wBACf,WAAW,EAAE,wBAAwB;wBACrC,UAAU,EAAE,KAAK;qBAClB,CAAC;iBACH;aACF,CAAC;YACF,IAAI,QAAQ,CAAC,cAAc,EAAE,EAAE;gBAC7B,SAAS,CAAC,WAAW,GAAG,QAAQ,CAAC,cAAc,EAAE,CAAC;aACnD;YACD,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE;gBAC7B,SAAS,CAAC,UAAU,GAAG,cAAc,CAAC;aACvC;YACD,IAAI,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;gBACjC,SAAS,CAAC,WAAW,GAAG,IAAA,gCAAa,EAAC,YAAY,CAAC,CAAC;aACrD;YACD,MAAM,qBAAqB,GAAG,IAAA,uCAAoB,EAAC,IAAI,CAAC,CAAC;YACzD,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE;gBAClC,GAAG,CAAC,CAAA,MAAA,IAAI,CAAC,OAAO,CAAC,KAAK,0CAAG,qBAAqB,CAAC,KAAI,EAAE,CAAC;gBACtD,CAAC,MAAM,CAAC,EAAE,SAAS;aACpB,CAAC,CAAC;QACL,CAAC,CAAC;QACF,IAAA,sBAAY,EAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC;IACxC,CAAC;CACF;AAxDD,0BAwDC"}
package/dist/routing.d.ts CHANGED
@@ -1,26 +1,21 @@
1
1
  import { Express } from "express";
2
2
  import { Logger } from "winston";
3
3
  import { CommonConfig } from "./config-type";
4
- import { AbstractEndpoint, Endpoint } from "./endpoint";
4
+ import { DependsOnMethod } from "./depends-on-method";
5
+ import { AbstractEndpoint } from "./endpoint";
5
6
  import { AuxMethod, Method } from "./method";
6
- export declare class DependsOnMethod {
7
- readonly methods: {
8
- [K in Method]?: Endpoint<any, any, any, any, K, any, any> | Endpoint<any, any, any, any, Method, any, any>;
9
- };
10
- constructor(methods: {
11
- [K in Method]?: Endpoint<any, any, any, any, K, any, any> | Endpoint<any, any, any, any, Method, any, any>;
12
- });
13
- }
7
+ import { ServeStatic, StaticHandler } from "./serve-static";
14
8
  export interface Routing {
15
- [SEGMENT: string]: Routing | DependsOnMethod | AbstractEndpoint;
9
+ [SEGMENT: string]: Routing | DependsOnMethod | AbstractEndpoint | ServeStatic;
16
10
  }
17
11
  export interface RoutingCycleParams {
18
12
  routing: Routing;
19
- cb: (endpoint: AbstractEndpoint, path: string, method: Method | AuxMethod) => void;
13
+ endpointCb: (endpoint: AbstractEndpoint, path: string, method: Method | AuxMethod) => void;
14
+ staticCb?: (path: string, handler: StaticHandler) => void;
20
15
  parentPath?: string;
21
16
  cors?: boolean;
22
17
  }
23
- export declare const routingCycle: ({ routing, cb, parentPath, cors, }: RoutingCycleParams) => void;
18
+ export declare const routingCycle: ({ routing, endpointCb, staticCb, parentPath, cors, }: RoutingCycleParams) => void;
24
19
  export declare const initRouting: ({ app, logger, config, routing, }: {
25
20
  app: Express;
26
21
  logger: Logger;
package/dist/routing.js CHANGED
@@ -1,38 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.initRouting = exports.routingCycle = exports.DependsOnMethod = void 0;
3
+ exports.initRouting = exports.routingCycle = void 0;
4
+ const express_1 = require("express");
5
+ const depends_on_method_1 = require("./depends-on-method");
4
6
  const endpoint_1 = require("./endpoint");
5
7
  const errors_1 = require("./errors");
8
+ const serve_static_1 = require("./serve-static");
6
9
  const startup_logo_1 = require("./startup-logo");
7
- class DependsOnMethod {
8
- constructor(methods) {
9
- this.methods = methods;
10
- Object.keys(methods).forEach((key) => {
11
- var _a, _b;
12
- if (key in methods) {
13
- const endpointMethods = ((_a = methods[key]) === null || _a === void 0 ? void 0 : _a.getMethods()) || [];
14
- if (!endpointMethods.includes(key)) {
15
- throw new errors_1.DependsOnMethodError(`The endpoint assigned to the '${key}' parameter must have at least this method in its specification.\n` +
16
- "This error should prevent mistakes during the development process.\n" +
17
- "Example:\n\n" +
18
- `new ${this.constructor.name}({\n` +
19
- ` ${key}: endpointsFactory.build({\n` +
20
- ` methods: ['${key}', ` +
21
- ((((_b = methods[key]) === null || _b === void 0 ? void 0 : _b.getMethods()) || [])
22
- .map((m) => `'${m}'`)
23
- .join(", ") || "...") +
24
- "]\n" +
25
- ` // or method: '${key}'\n` +
26
- " ...\n" +
27
- " })\n" +
28
- "});\n");
29
- }
30
- }
31
- });
32
- }
33
- }
34
- exports.DependsOnMethod = DependsOnMethod;
35
- const routingCycle = ({ routing, cb, parentPath, cors, }) => {
10
+ const routingCycle = ({ routing, endpointCb, staticCb, parentPath, cors, }) => {
36
11
  Object.entries(routing).forEach(([segment, element]) => {
37
12
  segment = segment.trim();
38
13
  if (segment.match(/\//)) {
@@ -48,22 +23,28 @@ const routingCycle = ({ routing, cb, parentPath, cors, }) => {
48
23
  methods.push("options");
49
24
  }
50
25
  methods.forEach((method) => {
51
- cb(element, path, method);
26
+ endpointCb(element, path, method);
52
27
  });
53
28
  }
54
- else if (element instanceof DependsOnMethod) {
29
+ else if (element instanceof serve_static_1.ServeStatic) {
30
+ if (staticCb) {
31
+ staticCb(path, (0, express_1.static)(...element.params));
32
+ }
33
+ }
34
+ else if (element instanceof depends_on_method_1.DependsOnMethod) {
55
35
  Object.entries(element.methods).forEach(([method, endpoint]) => {
56
- cb(endpoint, path, method);
36
+ endpointCb(endpoint, path, method);
57
37
  });
58
38
  if (cors && Object.keys(element.methods).length > 0) {
59
39
  const firstEndpoint = Object.values(element.methods)[0];
60
- cb(firstEndpoint, path, "options");
40
+ endpointCb(firstEndpoint, path, "options");
61
41
  }
62
42
  }
63
43
  else {
64
44
  (0, exports.routingCycle)({
65
45
  routing: element,
66
- cb,
46
+ endpointCb,
47
+ staticCb,
67
48
  cors,
68
49
  parentPath: path,
69
50
  });
@@ -78,12 +59,15 @@ const initRouting = ({ app, logger, config, routing, }) => {
78
59
  (0, exports.routingCycle)({
79
60
  routing,
80
61
  cors: config.cors,
81
- cb: (endpoint, path, method) => {
62
+ endpointCb: (endpoint, path, method) => {
82
63
  app[method](path, async (request, response) => {
83
64
  logger.info(`${request.method}: ${path}`);
84
65
  await endpoint.execute({ request, response, logger, config });
85
66
  });
86
67
  },
68
+ staticCb: (path, handler) => {
69
+ app.use(path, handler);
70
+ },
87
71
  });
88
72
  };
89
73
  exports.initRouting = initRouting;
@@ -1 +1 @@
1
- {"version":3,"file":"routing.js","sourceRoot":"","sources":["../src/routing.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"routing.js","sourceRoot":"","sources":["../src/routing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { static as _serveStatic } from "express";
2
+ declare type OriginalStatic = typeof _serveStatic;
3
+ export declare type StaticHandler = ReturnType<OriginalStatic>;
4
+ export declare class ServeStatic {
5
+ params: Parameters<OriginalStatic>;
6
+ constructor(...params: Parameters<OriginalStatic>);
7
+ }
8
+ export {};
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ServeStatic = void 0;
4
+ class ServeStatic {
5
+ constructor(...params) {
6
+ this.params = params;
7
+ }
8
+ }
9
+ exports.ServeStatic = ServeStatic;
10
+ //# sourceMappingURL=serve-static.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve-static.js","sourceRoot":"","sources":["../src/serve-static.ts"],"names":[],"mappings":";;;AAKA,MAAa,WAAW;IAGtB,YAAY,GAAG,MAAkC;QAC/C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAND,kCAMC"}
@@ -0,0 +1,29 @@
1
+ import { DependsOnMethodError } from "./errors.js";
2
+ export class DependsOnMethod {
3
+ constructor(methods) {
4
+ this.methods = methods;
5
+ Object.keys(methods).forEach((key) => {
6
+ var _a, _b;
7
+ if (key in methods) {
8
+ const endpointMethods = ((_a = methods[key]) === null || _a === void 0 ? void 0 : _a.getMethods()) || [];
9
+ if (!endpointMethods.includes(key)) {
10
+ throw new DependsOnMethodError(`The endpoint assigned to the '${key}' parameter must have at least this method in its specification.\n` +
11
+ "This error should prevent mistakes during the development process.\n" +
12
+ "Example:\n\n" +
13
+ `new ${this.constructor.name}({\n` +
14
+ ` ${key}: endpointsFactory.build({\n` +
15
+ ` methods: ['${key}', ` +
16
+ ((((_b = methods[key]) === null || _b === void 0 ? void 0 : _b.getMethods()) || [])
17
+ .map((m) => `'${m}'`)
18
+ .join(", ") || "...") +
19
+ "]\n" +
20
+ ` // or method: '${key}'\n` +
21
+ " ...\n" +
22
+ " })\n" +
23
+ "});\n");
24
+ }
25
+ }
26
+ });
27
+ }
28
+ }
29
+ //# sourceMappingURL=depends-on-method.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"depends-on-method.js","sourceRoot":"","sources":["../src/depends-on-method.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAGhD,MAAM,OAAO,eAAe;IAC1B,YACkB,OAIf;QAJe,YAAO,GAAP,OAAO,CAItB;QAEA,MAAM,CAAC,IAAI,CAAC,OAAO,CAA8B,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;;YACjE,IAAI,GAAG,IAAI,OAAO,EAAE;gBAClB,MAAM,eAAe,GAAG,CAAA,MAAA,OAAO,CAAC,GAAG,CAAC,0CAAE,UAAU,EAAE,KAAI,EAAE,CAAC;gBACzD,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;oBAClC,MAAM,IAAI,oBAAoB,CAC5B,iCAAiC,GAAG,oEAAoE;wBACtG,sEAAsE;wBACtE,cAAc;wBACd,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,MAAM;wBAClC,KAAK,GAAG,8BAA8B;wBACtC,kBAAkB,GAAG,KAAK;wBAC1B,CAAC,CAAC,CAAA,MAAA,OAAO,CAAC,GAAG,CAAC,0CAAE,UAAU,EAAE,KAAI,EAAE,CAAC;6BAChC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC;6BACpB,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;wBACvB,KAAK;wBACL,sBAAsB,GAAG,KAAK;wBAC9B,WAAW;wBACX,QAAQ;wBACR,OAAO,CACV,CAAC;iBACH;aACF;QACH,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
package/dist-esm/index.js CHANGED
@@ -6,11 +6,13 @@ export { createApiResponse } from "./api-response.js";
6
6
  export { createLogger } from "./logger.js";
7
7
  export { createMiddleware } from "./middleware.js";
8
8
  export { createResultHandler, defaultResultHandler } from "./result-handler.js";
9
- export { DependsOnMethod } from "./routing.js";
9
+ export { DependsOnMethod } from "./depends-on-method.js";
10
+ export { ServeStatic } from "./serve-static.js";
10
11
  export { createServer, attachRouting } from "./server.js";
11
12
  export { OpenAPI } from "./open-api.js";
12
13
  export { OpenAPIError, DependsOnMethodError, RoutingError } from "./errors.js";
13
14
  export { withMeta } from "./metadata.js";
15
+ export { testEndpoint } from "./mock.js";
14
16
  import * as z from "./extend-zod.js";
15
17
  import createHttpError from "http-errors";
16
18
  export { createHttpError, z };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAgB,MAAM,eAAe,CAAC;AAC3D,OAAO,EACL,gBAAgB,GAIjB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAChF,OAAO,EAAwB,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAAW,eAAe,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC5E,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,KAAK,CAAC,MAAM,cAAc,CAAC;AAClC,OAAO,eAAe,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,eAAe,EAAE,CAAC,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAgB,MAAM,eAAe,CAAC;AAC3D,OAAO,EACL,gBAAgB,GAIjB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAChF,OAAO,EAAwB,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC5E,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,KAAK,CAAC,MAAM,cAAc,CAAC;AAClC,OAAO,eAAe,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,eAAe,EAAE,CAAC,EAAE,CAAC"}
@@ -0,0 +1,52 @@
1
+ import http from "http";
2
+ import { mimeJson } from "./mime.js";
3
+ /**
4
+ * @description You need to install Jest and probably @types/jest to use this method
5
+ */
6
+ export const testEndpoint = async ({ endpoint, requestProps, responseProps, configProps, loggerProps, __noJest, }) => {
7
+ if (!jest || __noJest) {
8
+ throw new Error("You need to install Jest in order to use testEndpoint().");
9
+ }
10
+ const requestMock = {
11
+ method: "GET",
12
+ header: jest.fn(() => mimeJson),
13
+ ...requestProps,
14
+ };
15
+ const responseMock = {
16
+ writableEnded: false,
17
+ statusCode: 200,
18
+ statusMessage: http.STATUS_CODES[200],
19
+ set: jest.fn(() => responseMock),
20
+ status: jest.fn((code) => {
21
+ responseMock.statusCode = code;
22
+ responseMock.statusMessage = http.STATUS_CODES[code];
23
+ return responseMock;
24
+ }),
25
+ json: jest.fn(() => responseMock),
26
+ end: jest.fn(() => {
27
+ responseMock.writableEnded = true;
28
+ return responseMock;
29
+ }),
30
+ ...responseProps,
31
+ };
32
+ const loggerMock = {
33
+ info: jest.fn(),
34
+ warn: jest.fn(),
35
+ error: jest.fn(),
36
+ debug: jest.fn(),
37
+ ...loggerProps,
38
+ };
39
+ const configMock = {
40
+ cors: false,
41
+ logger: loggerMock,
42
+ ...configProps,
43
+ };
44
+ await endpoint.execute({
45
+ request: requestMock,
46
+ response: responseMock,
47
+ config: configMock,
48
+ logger: loggerMock,
49
+ });
50
+ return { requestMock, responseMock, loggerMock };
51
+ };
52
+ //# sourceMappingURL=mock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock.js","sourceRoot":"","sources":["../src/mock.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,MAAM,CAAC;AAIxB,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAYlC;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAI/B,EACA,QAAQ,EACR,YAAY,EACZ,aAAa,EACb,WAAW,EACX,WAAW,EACX,QAAQ,GACyB,EAAE,EAAE;IACrC,IAAI,CAAC,IAAI,IAAI,QAAQ,EAAE;QACrB,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;KAC7E;IACD,MAAM,WAAW,GAGhB;QACC,MAAM,EAAE,KAAK;QACb,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC;QAC/B,GAAG,YAAY;KAChB,CAAC;IACF,MAAM,YAAY,GAOjB;QACC,aAAa,EAAE,KAAK;QACpB,UAAU,EAAE,GAAG;QACf,aAAa,EAAE,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC;QACrC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC;QAChC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,IAAY,EAAE,EAAE;YAC/B,YAAY,CAAC,UAAU,GAAG,IAAI,CAAC;YAC/B,YAAY,CAAC,aAAa,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;YACrD,OAAO,YAAY,CAAC;QACtB,CAAC,CAAC;QACF,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC;QACjC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE;YAChB,YAAY,CAAC,aAAa,GAAG,IAAI,CAAC;YAClC,OAAO,YAAY,CAAC;QACtB,CAAC,CAAC;QACF,GAAG,aAAa;KACjB,CAAC;IACF,MAAM,UAAU,GAGf;QACC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;QACf,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;QACf,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE;QAChB,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE;QAChB,GAAG,WAAW;KACf,CAAC;IACF,MAAM,UAAU,GAAG;QACjB,IAAI,EAAE,KAAK;QACX,MAAM,EAAE,UAAU;QAClB,GAAG,WAAW;KACf,CAAC;IACF,MAAM,QAAQ,CAAC,OAAO,CAAC;QACrB,OAAO,EAAE,WAAiC;QAC1C,QAAQ,EAAE,YAAmC;QAC7C,MAAM,EAAE,UAA0B;QAClC,MAAM,EAAE,UAA+B;KACxC,CAAC,CAAC;IACH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;AACnD,CAAC,CAAC"}
@@ -6,7 +6,7 @@ export class OpenAPI extends OpenApiBuilder {
6
6
  constructor({ routing, config, title, version, serverUrl, successfulResponseDescription = "Successful response", errorResponseDescription = "Error response", }) {
7
7
  super();
8
8
  this.addInfo({ title, version }).addServer({ url: serverUrl });
9
- const cb = (endpoint, path, _method) => {
9
+ const endpointCb = (endpoint, path, _method) => {
10
10
  var _a, _b;
11
11
  const method = _method;
12
12
  const commonParams = { path, method, endpoint };
@@ -44,7 +44,7 @@ export class OpenAPI extends OpenApiBuilder {
44
44
  [method]: operation,
45
45
  });
46
46
  };
47
- routingCycle({ routing, cb });
47
+ routingCycle({ routing, endpointCb });
48
48
  }
49
49
  }
50
50
  //# sourceMappingURL=open-api.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"open-api.js","sourceRoot":"","sources":["../src/open-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAmB,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAW,YAAY,EAAsB,MAAM,WAAW,CAAC;AAYtE,MAAM,OAAO,OAAQ,SAAQ,cAAc;IACzC,YAAmB,EACjB,OAAO,EACP,MAAM,EACN,KAAK,EACL,OAAO,EACP,SAAS,EACT,6BAA6B,GAAG,qBAAqB,EACrD,wBAAwB,GAAG,gBAAgB,GAC3B;QAChB,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QAC/D,MAAM,EAAE,GAA6B,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;;YAC/D,MAAM,MAAM,GAAG,OAAiB,CAAC;YACjC,MAAM,YAAY,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;YAChD,MAAM,YAAY,GAChB,CAAA,MAAA,MAAM,CAAC,YAAY,0CAAG,MAAM,CAAC,KAAI,mBAAmB,CAAC,MAAM,CAAC,CAAC;YAC/D,MAAM,cAAc,GAAG,mBAAmB,CAAC;gBACzC,GAAG,YAAY;gBACf,YAAY;aACb,CAAC,CAAC;YACH,MAAM,SAAS,GAAoB;gBACjC,SAAS,EAAE;oBACT,KAAK,EAAE,cAAc,CAAC;wBACpB,GAAG,YAAY;wBACf,WAAW,EAAE,6BAA6B;wBAC1C,UAAU,EAAE,IAAI;qBACjB,CAAC;oBACF,KAAK,EAAE,cAAc,CAAC;wBACpB,GAAG,YAAY;wBACf,WAAW,EAAE,wBAAwB;wBACrC,UAAU,EAAE,KAAK;qBAClB,CAAC;iBACH;aACF,CAAC;YACF,IAAI,QAAQ,CAAC,cAAc,EAAE,EAAE;gBAC7B,SAAS,CAAC,WAAW,GAAG,QAAQ,CAAC,cAAc,EAAE,CAAC;aACnD;YACD,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE;gBAC7B,SAAS,CAAC,UAAU,GAAG,cAAc,CAAC;aACvC;YACD,IAAI,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;gBACjC,SAAS,CAAC,WAAW,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC;aACrD;YACD,MAAM,qBAAqB,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;YACzD,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE;gBAClC,GAAG,CAAC,CAAA,MAAA,IAAI,CAAC,OAAO,CAAC,KAAK,0CAAG,qBAAqB,CAAC,KAAI,EAAE,CAAC;gBACtD,CAAC,MAAM,CAAC,EAAE,SAAS;aACpB,CAAC,CAAC;QACL,CAAC,CAAC;QACF,YAAY,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;IAChC,CAAC;CACF"}
1
+ {"version":3,"file":"open-api.js","sourceRoot":"","sources":["../src/open-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAmB,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAW,YAAY,EAAsB,MAAM,WAAW,CAAC;AAYtE,MAAM,OAAO,OAAQ,SAAQ,cAAc;IACzC,YAAmB,EACjB,OAAO,EACP,MAAM,EACN,KAAK,EACL,OAAO,EACP,SAAS,EACT,6BAA6B,GAAG,qBAAqB,EACrD,wBAAwB,GAAG,gBAAgB,GAC3B;QAChB,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QAC/D,MAAM,UAAU,GAAqC,CACnD,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,EAAE;;YACF,MAAM,MAAM,GAAG,OAAiB,CAAC;YACjC,MAAM,YAAY,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;YAChD,MAAM,YAAY,GAChB,CAAA,MAAA,MAAM,CAAC,YAAY,0CAAG,MAAM,CAAC,KAAI,mBAAmB,CAAC,MAAM,CAAC,CAAC;YAC/D,MAAM,cAAc,GAAG,mBAAmB,CAAC;gBACzC,GAAG,YAAY;gBACf,YAAY;aACb,CAAC,CAAC;YACH,MAAM,SAAS,GAAoB;gBACjC,SAAS,EAAE;oBACT,KAAK,EAAE,cAAc,CAAC;wBACpB,GAAG,YAAY;wBACf,WAAW,EAAE,6BAA6B;wBAC1C,UAAU,EAAE,IAAI;qBACjB,CAAC;oBACF,KAAK,EAAE,cAAc,CAAC;wBACpB,GAAG,YAAY;wBACf,WAAW,EAAE,wBAAwB;wBACrC,UAAU,EAAE,KAAK;qBAClB,CAAC;iBACH;aACF,CAAC;YACF,IAAI,QAAQ,CAAC,cAAc,EAAE,EAAE;gBAC7B,SAAS,CAAC,WAAW,GAAG,QAAQ,CAAC,cAAc,EAAE,CAAC;aACnD;YACD,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE;gBAC7B,SAAS,CAAC,UAAU,GAAG,cAAc,CAAC;aACvC;YACD,IAAI,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;gBACjC,SAAS,CAAC,WAAW,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC;aACrD;YACD,MAAM,qBAAqB,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;YACzD,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE;gBAClC,GAAG,CAAC,CAAA,MAAA,IAAI,CAAC,OAAO,CAAC,KAAK,0CAAG,qBAAqB,CAAC,KAAI,EAAE,CAAC;gBACtD,CAAC,MAAM,CAAC,EAAE,SAAS;aACpB,CAAC,CAAC;QACL,CAAC,CAAC;QACF,YAAY,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC;IACxC,CAAC;CACF"}
@@ -1 +1 @@
1
- {"type":"module","version":"5.0.0"}
1
+ {"type":"module","version":"5.2.0"}
@@ -1,34 +1,10 @@
1
+ import { static as _serveStatic } from "express";
2
+ import { DependsOnMethod } from "./depends-on-method.js";
1
3
  import { AbstractEndpoint } from "./endpoint.js";
2
- import { DependsOnMethodError, RoutingError } from "./errors.js";
4
+ import { RoutingError } from "./errors.js";
5
+ import { ServeStatic } from "./serve-static.js";
3
6
  import { getStartupLogo } from "./startup-logo.js";
4
- export class DependsOnMethod {
5
- constructor(methods) {
6
- this.methods = methods;
7
- Object.keys(methods).forEach((key) => {
8
- var _a, _b;
9
- if (key in methods) {
10
- const endpointMethods = ((_a = methods[key]) === null || _a === void 0 ? void 0 : _a.getMethods()) || [];
11
- if (!endpointMethods.includes(key)) {
12
- throw new DependsOnMethodError(`The endpoint assigned to the '${key}' parameter must have at least this method in its specification.\n` +
13
- "This error should prevent mistakes during the development process.\n" +
14
- "Example:\n\n" +
15
- `new ${this.constructor.name}({\n` +
16
- ` ${key}: endpointsFactory.build({\n` +
17
- ` methods: ['${key}', ` +
18
- ((((_b = methods[key]) === null || _b === void 0 ? void 0 : _b.getMethods()) || [])
19
- .map((m) => `'${m}'`)
20
- .join(", ") || "...") +
21
- "]\n" +
22
- ` // or method: '${key}'\n` +
23
- " ...\n" +
24
- " })\n" +
25
- "});\n");
26
- }
27
- }
28
- });
29
- }
30
- }
31
- export const routingCycle = ({ routing, cb, parentPath, cors, }) => {
7
+ export const routingCycle = ({ routing, endpointCb, staticCb, parentPath, cors, }) => {
32
8
  Object.entries(routing).forEach(([segment, element]) => {
33
9
  segment = segment.trim();
34
10
  if (segment.match(/\//)) {
@@ -44,22 +20,28 @@ export const routingCycle = ({ routing, cb, parentPath, cors, }) => {
44
20
  methods.push("options");
45
21
  }
46
22
  methods.forEach((method) => {
47
- cb(element, path, method);
23
+ endpointCb(element, path, method);
48
24
  });
49
25
  }
26
+ else if (element instanceof ServeStatic) {
27
+ if (staticCb) {
28
+ staticCb(path, _serveStatic(...element.params));
29
+ }
30
+ }
50
31
  else if (element instanceof DependsOnMethod) {
51
32
  Object.entries(element.methods).forEach(([method, endpoint]) => {
52
- cb(endpoint, path, method);
33
+ endpointCb(endpoint, path, method);
53
34
  });
54
35
  if (cors && Object.keys(element.methods).length > 0) {
55
36
  const firstEndpoint = Object.values(element.methods)[0];
56
- cb(firstEndpoint, path, "options");
37
+ endpointCb(firstEndpoint, path, "options");
57
38
  }
58
39
  }
59
40
  else {
60
41
  routingCycle({
61
42
  routing: element,
62
- cb,
43
+ endpointCb,
44
+ staticCb,
63
45
  cors,
64
46
  parentPath: path,
65
47
  });
@@ -73,12 +55,15 @@ export const initRouting = ({ app, logger, config, routing, }) => {
73
55
  routingCycle({
74
56
  routing,
75
57
  cors: config.cors,
76
- cb: (endpoint, path, method) => {
58
+ endpointCb: (endpoint, path, method) => {
77
59
  app[method](path, async (request, response) => {
78
60
  logger.info(`${request.method}: ${path}`);
79
61
  await endpoint.execute({ request, response, logger, config });
80
62
  });
81
63
  },
64
+ staticCb: (path, handler) => {
65
+ app.use(path, handler);
66
+ },
82
67
  });
83
68
  };
84
69
  //# sourceMappingURL=routing.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"routing.js","sourceRoot":"","sources":["../src/routing.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"routing.js","sourceRoot":"","sources":["../src/routing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export class ServeStatic {
2
+ constructor(...params) {
3
+ this.params = params;
4
+ }
5
+ }
6
+ //# sourceMappingURL=serve-static.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve-static.js","sourceRoot":"","sources":["../src/serve-static.ts"],"names":[],"mappings":"AAKA,MAAM,OAAO,WAAW;IAGtB,YAAY,GAAG,MAAkC;QAC/C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "express-zod-api",
3
- "version": "5.0.0",
3
+ "version": "5.2.0",
4
4
  "description": "A Typescript library to help you get an API server up and running with I/O schema validation and custom middlewares in minutes.",
5
5
  "license": "MIT",
6
6
  "scripts": {
@@ -44,6 +44,18 @@
44
44
  "winston": "3.3.3",
45
45
  "zod": "3.11.6"
46
46
  },
47
+ "peerDependencies": {
48
+ "@types/jest": "*",
49
+ "jest": ">=25 <28"
50
+ },
51
+ "peerDependenciesMeta": {
52
+ "jest": {
53
+ "optional": true
54
+ },
55
+ "@types/jest": {
56
+ "optional": true
57
+ }
58
+ },
47
59
  "devDependencies": {
48
60
  "@tsconfig/node12": "^1.0.9",
49
61
  "@types/express": "^4.17.13",