├── .gitignore ├── .nycrc.json ├── LICENSE ├── .github └── workflows │ └── ci.yml ├── index.ts ├── package.json ├── README.md ├── test └── maestro.test.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | coverage 2 | node_modules 3 | *.log 4 | .DS_Store 5 | .node_repl_history 6 | .nyc_output 7 | npm-debug.log* 8 | dist/ -------------------------------------------------------------------------------- /.nycrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@istanbuljs/nyc-config-typescript", 3 | "all": true, 4 | "check-coverage": true, 5 | "include": [ 6 | "dist/**/*.js" 7 | ] 8 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Jarbas (Júnior) Gouveia 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created 2 | # For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages 3 | 4 | name: CI RELEASE 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: '*' 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | node-version: [16.x] 18 | steps: 19 | - uses: actions/checkout@v3 20 | - uses: actions/setup-node@v3 21 | with: 22 | node-version: ${{ matrix.node-version }} 23 | cache: 'npm' 24 | - run: npm ci 25 | - run: npm run build 26 | - run: npm test 27 | 28 | publish: 29 | runs-on: ubuntu-latest 30 | if: ${{ github.ref == 'refs/heads/master' }} 31 | needs: build 32 | steps: 33 | - uses: actions/checkout@v3 34 | - name: Use Node.js ${{ matrix.node-version }} 35 | uses: actions/setup-node@v3 36 | with: 37 | node-version: ${{ matrix.node-version }} 38 | - run: npm ci 39 | - run: npm run build 40 | - run: npm run semantic-release 41 | env: 42 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 43 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 44 | -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | import { ErrorRequestHandler, RequestHandler } from "express"; 2 | import { Request, Response, NextFunction } from "express"; 3 | import { ParamsDictionary, Query } from "express-serve-static-core"; 4 | import { ParsedQs } from "qs"; 5 | 6 | export type ErrorConstructor = new ( 7 | ...args: T 8 | ) => ErrorRequestHandler; 9 | 10 | export type Callback< 11 | P = ParamsDictionary, 12 | ResBody = any, 13 | ReqBody = any, 14 | ReqQuery = Query 15 | > = ( 16 | ...args: Parameters> 17 | ) => void; 18 | 19 | export interface Maestro { 20 | (middleware: Callback): Callback; 21 | from(constructor: ErrorConstructor<[]>, middleware: Callback): Callback; 22 | all(callbacks: Callback[]): Callback[]; 23 | } 24 | 25 | const maestro = function opera(middleware: Callback) { 26 | return async function orchestra(...args: any[]): Promise { 27 | const fnReturn = middleware(...(args as Parameters)); 28 | const next = args[args.length - 1]; 29 | if (typeof next !== "function") { 30 | throw new TypeError("Next is not a function"); 31 | } 32 | return Promise.resolve(fnReturn).catch(next); 33 | }; 34 | }; 35 | 36 | maestro.from = function from( 37 | constructor: any, 38 | middleware: ( 39 | arg0: Error, 40 | arg1: Request>, 41 | arg2: Response>, 42 | arg3: NextFunction 43 | ) => void 44 | ) { 45 | return function errorHandler( 46 | err: Error, 47 | req: Request, 48 | res: Response, 49 | next: NextFunction 50 | ) { 51 | if (!(err instanceof constructor)) { 52 | next(err); 53 | return; 54 | } 55 | 56 | middleware(err, req, res, next); 57 | }; 58 | }; 59 | 60 | maestro.all = function all(callbacks: Callback[]) { 61 | return callbacks.map(maestro); 62 | }; 63 | 64 | Object.freeze(maestro); 65 | Object.freeze(maestro.from); 66 | Object.freeze(maestro.all); 67 | 68 | export { maestro }; 69 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "maestro-express-async-errors", 3 | "version": "1.2.8", 4 | "description": "A simple an secure layer of code for async middlewares.", 5 | "main": "./dist/index.js", 6 | "types": "./dist/index.d.ts", 7 | "module": "./dist/index.mjs", 8 | "files": [ 9 | "dist", 10 | "test", 11 | "index.ts" 12 | ], 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/jjgouveia/maestro-express-async-errors.git" 16 | }, 17 | "scripts": { 18 | "test": "mocha --require ts-node/register test/**/*.ts", 19 | "coverage": "nyc -r text -r json-summary mocha --require ts-node/register test/**/*.ts", 20 | "build": "rm -rf ./dist && tsup index.ts --format cjs,esm --dts --out-dir dist", 21 | "lint": "tsc", 22 | "eslint": "eslint --ext .ts,.tsx .", 23 | "ci": "npm run lint && npm run build && npm run test", 24 | "semantic-release": "semantic-release --branches master", 25 | "commit": "git-cz", 26 | "acp": "git add . && npm run commit && git push" 27 | }, 28 | "keywords": [ 29 | "express", 30 | "async errors", 31 | "expressjs", 32 | "async", 33 | "error middleware", 34 | "await", 35 | "async/await", 36 | "error", 37 | "handling" 38 | ], 39 | "author": "Jr Gouveia ", 40 | "license": "MIT", 41 | "devDependencies": { 42 | "@istanbuljs/nyc-config-typescript": "^1.0.2", 43 | "@types/express": "4.17.17", 44 | "@types/mocha": "^10.0.1", 45 | "@types/sinon": "^10.0.13", 46 | "@types/sinon-chai": "^3.2.9", 47 | "chai": "^4.3.4", 48 | "commitizen": "^4.3.0", 49 | "cz-conventional-changelog": "^3.3.0", 50 | "mocha": "^10.2.0", 51 | "nyc": "^15.1.0", 52 | "semantic-release": "^21.0.1", 53 | "sinon": "^11.1.2", 54 | "sinon-chai": "^3.7.0", 55 | "tsup": "^6.7.0", 56 | "tsx": "^3.12.6", 57 | "typescript": "^5.0.4" 58 | }, 59 | "engines": { 60 | "node": ">=7.6.0" 61 | }, 62 | "bugs": { 63 | "url": "https://github.com/jjgouveia/maestro-express-async-errors/issues" 64 | }, 65 | "homepage": "https://github.com/jjgouveia/maestro-express-async-errors/#readme", 66 | "config": { 67 | "commitizen": { 68 | "path": "./node_modules/cz-conventional-changelog" 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![node-current](https://img.shields.io/node/v/maestro-express-async-errors) 2 | [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com) 3 | [![CI RELEASE](https://github.com/jjgouveia/maestro-express-async-errors/actions/workflows/ci.yml/badge.svg)](https://github.com/jjgouveia/maestro-express-async-errors/actions/workflows/ci.yml) 4 | ![Downloads](https://img.shields.io/npm/dy/maestro-express-async-errors) 5 | [![cov](https://jjgouveia.github.io/maestro-express-async-errors/badges/coverage.svg)](https://github.com/jjgouveia/maestro-express-async-errors/actions) 6 | # Maestro for ExpressJS Async Errors 7 | ### 🏆 The async/await heaven! 8 |
9 | 10 | ## Maestro is a slightly layer of code that acts as a wrapper, without any dependencies, for async middlewares. Its purpose is to ensure that all errors occurring in async operations are properly passed to your stack of error handlers. By doing so, Maestro helps to improve the readability and cleanliness of your code. 11 | 12 | ### Installation: 13 | 14 | ``` 15 | npm install --save maestro-express-async-errors 16 | ``` 17 | or 18 | ``` 19 | yarn add maestro-express-async-errors 20 | ``` 21 |
22 | 23 | > **Note** 24 | > The minimum supported `Node` version for Maestro is `7.6.0`. 25 | 26 | ## How to use it 27 | 28 | **With maestro:** 29 | 30 | ```javascript 31 | const { maestro } = require('maestro-express-async-errors'); 32 | 33 | 34 | express.get('/', maestro(async (req, res, next) => { 35 | const bar = await foo.findAll(); 36 | res.send(bar) 37 | })) 38 | ``` 39 | 40 | **Without maestro:** 41 | 42 | ```javascript 43 | express.get('/',(req, res, next) => { 44 | foo.findAll() 45 | .then ( bar => { 46 | res.send(bar) 47 | } ) 48 | .catch(next); // error passed on to the error handling route 49 | }) 50 | ``` 51 | ### So Easy right? 😉 52 | 53 | **Now let I show you more exemples and functionalities:** 54 | 55 | * `maestro` insures thrown errors are passed to `next` callback: 56 | 57 | ```js 58 | const { maestro } = require('maestro-express-async-errors'); 59 | 60 | app.get('/:id', maestro(async (req, res, next) => { 61 | const user = await repository.getById(req.params.id) 62 | 63 | if (!user) { 64 | throw new UserNotFoundError 65 | } 66 | 67 | res.status(200) 68 | .json(user) 69 | })) 70 | 71 | ``` 72 | 73 | * `maestro.from` allows you to handle a specific error which is helpful for handling domain driven errors. 74 | ```js 75 | 76 | app.use(maestro.from(UserNotFoundError, (err, req, res, next) => { 77 | res.status(404) 78 | .json({ error: 'these are not the droids you\'re looking for'}) 79 | }) 80 | 81 | /** 82 | Your error handlers still works as expected. If an error doesn't match your `maestro.from` criteria, it will find its way to the next error handler. 83 | */ 84 | app.use((err, req, res, next) => { 85 | res.status(500) 86 | .json({ error: 'i have a bad feeling about this'}) 87 | }) 88 | 89 | ``` 90 | 91 | * There's a helper function `maestro.all([...])` in case you want to wrap several functions with `maestro`. With `maestro.all`, doing `[maestro(fn1), maestro(fn2)]` can be shortened to `maestro.all([fn1, fn2])`. 92 | 93 | ```js 94 | const maestro = require('maestro-express-async-errors') 95 | 96 | // Doing it like this 97 | app.post('/products', maestro.all([ 98 | validationFn, 99 | createProductFn 100 | ])) 101 | 102 | // Is equivalent to this 103 | app.post('/products', [ 104 | maestro(validationFn), 105 | maestro(createProductFn) 106 | ]) 107 | ``` 108 | #### Import in Typescript: 109 | 110 | ```javascript 111 | import { maestro } from "maestro-express-async-errors" 112 | ``` 113 | 114 |
115 | 116 | ## Test Cases 117 | 118 | ```txt 119 | > maestro-express-async-errors@1.2.5 test 120 | > mocha --require ts-node/register test/**/*.ts 121 | 122 | 123 | 124 | Try maestro(async (req, res, next) => { next() or Error }) : 125 | Basic functionality: 126 | ✔ Maestro is a function. 127 | ✔ Maestro returns a function. 128 | ✔ Maestro returns a function that returns a promise. 129 | ✔ When an asynchronous function passed into it throws an error, it is expected that the calls next with that error. 130 | ✔ When a non-asynchronous function passed into it throws an error, it is expected that calls next with that error. 131 | ✔ Should invoke `next` when passing a non-async function. 132 | ✔ Thenables are not guaranteed to have a `catch` method. This test refers to this. 133 | Should invoke `next` with the thrown error: 134 | ✔ If an async function is passed as an argument, the next function should be called with the provided arguments. 135 | ✔ Works like a charm if all arguments are passed to the callback function. 136 | ✔ Raises a TypeError if next args it's not a function. 137 | ✔ A valid call works for routes and middlewares. 138 | ✔ A valid call works for error handler middlewares. 139 | 140 | Try maestro.from(RealProblems, (err) => { }) : 141 | ✔ Handles the error when error is instance of given constructor. 142 | ✔ It call `next` function if error is not an instance of given constructor. 143 | 144 | Try maestro.all([...args]) : 145 | ✔ Raises a TypeError when `next` it's not function. 146 | ✔ Should return an array. 147 | ✔ Should return an array of functions 148 | ✔ Should return an array of functions that returns a promise. 149 | ✔ Should return an array of functions that returns a promise that calls next. 150 | ✔ Should return an array of functions that returns a promise that calls next with the error. 151 | 152 | 153 | 20 passing (75ms) 154 | ``` 155 | 156 | -------------------------------------------------------------------------------- /test/maestro.test.ts: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | import { expect } from "chai"; 4 | import sinon from "sinon"; 5 | import chai from "chai"; 6 | import sinonChai from "sinon-chai"; 7 | import { maestro } from "../dist/index.js"; 8 | 9 | chai.use(sinonChai); 10 | chai.should(); 11 | 12 | describe("Try maestro(async (req, res, next) => { next() or Error }) :", () => { 13 | const next = sinon.spy(); 14 | 15 | describe("Basic functionality:", () => { 16 | it("Maestro is a function.", () => { 17 | expect(maestro).to.be.a("function"); 18 | }); 19 | 20 | it("Maestro returns a function.", () => { 21 | expect(maestro(() => {})).to.be.a("function"); 22 | }); 23 | 24 | it("Maestro returns a function that returns a promise.", () => { 25 | expect(maestro(() => {})()).to.be.a("promise"); 26 | }); 27 | 28 | it("When an asynchronous function passed into it throws an error, it is expected that the calls next with that error.", async () => { 29 | const error = new Error("Oh! You catch me!"); 30 | const foo = maestro(async (_req: any, _res: any, _next: any) => { 31 | throw error; 32 | }); 33 | 34 | await foo({}, {}, next); 35 | expect(next).to.have.been.calledWith(error); 36 | }); 37 | 38 | it("When a non-asynchronous function passed into it throws an error, it is expected that calls next with that error.", async () => { 39 | const error = new Error("Oh! You catch me!"); 40 | const foo = maestro((_req: any, _res: any, _next: any) => { 41 | next(error); 42 | }); 43 | 44 | await foo({}, {}, next); 45 | expect(next).to.have.been.calledWith(error); 46 | }); 47 | 48 | it("Should invoke `next` when passing a non-async function.", async () => { 49 | const next = sinon.spy(); 50 | const foo = maestro((_req: any, _res: any, _next: any) => { 51 | next("test"); 52 | }); 53 | 54 | await foo({}, {}, next); 55 | expect(next).to.have.been.calledWith("test"); 56 | }); 57 | 58 | it("Thenables are not guaranteed to have a `catch` method. This test refers to this.", async () => { 59 | const error: Error = Error("Wow!"); 60 | let thenable: any; 61 | let triggerFailure: any; 62 | 63 | const registeringThenable: Promise = new Promise( 64 | (resolve) => { 65 | thenable = { 66 | then: sinon.spy((_success: any, fail: any) => { 67 | triggerFailure = fail; 68 | resolve(); 69 | }), 70 | }; 71 | } 72 | ); 73 | 74 | const next: sinon.SinonSpy = sinon.spy(); 75 | const catchingThenable: Promise = maestro(() => thenable)( 76 | null, 77 | null, 78 | next 79 | ); 80 | await registeringThenable; 81 | 82 | expect(thenable.then).to.have.been.called; 83 | expect(next).not.to.have.been.called; 84 | 85 | triggerFailure(error); 86 | await catchingThenable; 87 | 88 | try { 89 | await catchingThenable; 90 | expect(next).to.have.been.calledWith(error); 91 | } catch (err) { 92 | expect.fail(err as any); 93 | } 94 | }); 95 | }); 96 | 97 | describe("Should invoke `next` with the thrown error:", () => { 98 | const error = new TypeError("Next is not a function"); 99 | const route = maestro(async (_req: any, _res: any, _next: any) => { 100 | throw error; 101 | }); 102 | 103 | it("If an async function is passed as an argument, the next function should be called with the provided arguments.", async () => { 104 | const next = sinon.spy(); 105 | const foo = maestro(async (_req: any, _res: any, _next: any) => { 106 | next("test"); 107 | }); 108 | 109 | await foo(null, null, next); 110 | expect(next).to.have.been.calledWith("test"); 111 | }); 112 | 113 | it("Works like a charm if all arguments are passed to the callback function.", async () => { 114 | const spy1 = sinon.spy(); 115 | const spy2 = sinon.spy(); 116 | const spy3 = sinon.spy(); 117 | 118 | const callable = maestro((arg1: any, arg2: any, arg3: any) => { 119 | [arg1, arg2, arg3].forEach((arg) => arg()); 120 | }); 121 | 122 | await callable(spy1, spy2, spy3); 123 | 124 | expect(spy1.called).to.equals(true); 125 | expect(spy2.called).to.equals(true); 126 | expect(spy3.called).to.equals(true); 127 | }); 128 | 129 | it("Raises a TypeError if next args it's not a function.", async () => { 130 | try { 131 | await route({}, {}, {}); 132 | } catch (error) { 133 | expect(error).to.deep.equal(new TypeError("Next is not a function")); 134 | } 135 | }); 136 | 137 | it("A valid call works for routes and middlewares.", async () => { 138 | const spy = sinon.spy(); 139 | 140 | await route({}, {}, spy); 141 | expect(spy.called).to.equals(true); 142 | }); 143 | 144 | it("A valid call works for error handler middlewares.", async () => { 145 | const spy = sinon.spy(); 146 | 147 | await route({}, {}, {}, spy); 148 | expect(spy.called).to.equals(true); 149 | }); 150 | }); 151 | }); 152 | 153 | describe("Try maestro.from(RealProblems, (err) => { }) :", () => { 154 | class RealProblems extends Error {} // RealProblems is a subclass of Error. 155 | class NonRealProblems {} // NonRealProblems is not a subclass of Error, 156 | // that is, for example, what you get when you are anxious. 157 | 158 | const req = {} as any; 159 | const res = {} as any; 160 | 161 | it("Handles the error when error is instance of given constructor.", () => { 162 | const matchedHandler = (err: any) => { 163 | expect(err).to.be.instanceOf(RealProblems); 164 | }; 165 | 166 | const next = (_err: any) => { 167 | throw new Error("Not supposed to call this function"); 168 | }; 169 | 170 | maestro.from(RealProblems, matchedHandler)( 171 | new RealProblems(), 172 | req, 173 | res, 174 | next 175 | ); 176 | maestro.from(Error, matchedHandler)(new RealProblems(), req, res, next); 177 | }); 178 | 179 | it("It call `next` function if error is not an instance of given constructor.", () => { 180 | const matchedHandler = (_err: any) => { 181 | throw new Error("Not supposed to call this function"); 182 | }; 183 | 184 | const next = (err: any) => { 185 | expect(err).to.be.instanceOf(NonRealProblems); 186 | }; 187 | 188 | maestro.from(RealProblems, matchedHandler)( 189 | new NonRealProblems() as Error, 190 | req, 191 | res, 192 | next 193 | ); 194 | }); 195 | }); 196 | 197 | describe("Try maestro.all([...args]) :", () => { 198 | const fn = async (_cb: any) => { 199 | throw new TypeError(); 200 | }; 201 | const next = sinon.spy(); 202 | const req = {}; 203 | const res = {}; 204 | const error = new Error("Oh! You catch me!"); 205 | 206 | it("Raises a TypeError when `next` it's not function.", async () => { 207 | const [maestroFn] = maestro.all([fn]); 208 | try { 209 | await maestroFn(); 210 | } catch (error) { 211 | expect(error).to.deep.equal(new TypeError("Next is not a function")); 212 | } 213 | }); 214 | 215 | it("Should return an array.", async () => { 216 | const foo = maestro(async (_req: any, _res: any, _next: any) => { 217 | next("test"); 218 | }); 219 | 220 | expect(maestro.all([foo])).to.be.a("array"); 221 | }); 222 | it("Should return an array of functions", async () => { 223 | const foo = maestro(async (_req: any, _res: any, _next: any) => { 224 | next("test"); 225 | }); 226 | 227 | expect(maestro.all([foo])[0]).to.be.a("function"); 228 | }); 229 | it("Should return an array of functions that returns a promise.", async () => { 230 | const foo = maestro(async (_req: any, _res: any, _next: any) => { 231 | next("test"); 232 | }); 233 | 234 | expect(maestro.all([foo])[0]()).to.be.a("promise"); 235 | }); 236 | it("Should return an array of functions that returns a promise that calls next.", async () => { 237 | const foo = maestro(async (_req: any, _res: any, _next: any) => { 238 | next("test"); 239 | }); 240 | 241 | await maestro.all([foo])[0](req, res, next); 242 | expect(next).to.have.been.calledWith("test"); 243 | }); 244 | 245 | it("Should return an array of functions that returns a promise that calls next with the error.", async () => { 246 | const foo = maestro(async (_req: any, _res: any, _next: any) => { 247 | next(error); 248 | }); 249 | 250 | await maestro.all([foo])[0](req, res, next); 251 | expect(next).to.have.been.calledWith(error); 252 | }); 253 | }); 254 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "es2020", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 26 | 27 | /* Modules */ 28 | "module": "commonjs", /* Specify what module code is generated. */ 29 | // "rootDir": "./", /* Specify the root folder within your source files. */ 30 | // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ 31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 38 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ 39 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ 40 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ 41 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ 42 | // "resolveJsonModule": true, /* Enable importing .json files. */ 43 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ 44 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 45 | 46 | /* JavaScript Support */ 47 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 48 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 49 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 50 | 51 | /* Emit */ 52 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 53 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 54 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 55 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 56 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 57 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 58 | // "outDir": "./", /* Specify an output folder for all emitted files. */ 59 | // "removeComments": true, /* Disable emitting comments. */ 60 | // "noEmit": true, /* Disable emitting files from a compilation. */ 61 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 62 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ 63 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 64 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 65 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 66 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 67 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 68 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 69 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 70 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 71 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 72 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 73 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 74 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 75 | 76 | /* Interop Constraints */ 77 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 78 | // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ 79 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 80 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ 81 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 82 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 83 | 84 | /* Type Checking */ 85 | "strict": true, /* Enable all strict type-checking options. */ 86 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 87 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 88 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 89 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 90 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 91 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 92 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 93 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 94 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 95 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 96 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 97 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 98 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 99 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 100 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 101 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 102 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 103 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 104 | 105 | /* Completeness */ 106 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 107 | "skipLibCheck": true, /* Skip type checking all .d.ts files. */ 108 | "noEmit": true, /* Disable emitting files from a compilation. */ 109 | } 110 | } 111 | --------------------------------------------------------------------------------