├── .github ├── FUNDING.yml └── workflows │ ├── codeql-analysis.yml │ └── test.yml ├── .gitignore ├── .husky └── pre-commit ├── .nvmrc ├── .prettierrc ├── .vscode └── settings.json ├── LICENSE.md ├── README.md ├── docs ├── github-both.png ├── github-one.png ├── github-status.png └── vercel_settings.png ├── package.json ├── pnpm-lock.yaml ├── src ├── debug.ts ├── git.ts ├── index.ts ├── parseArgs.ts ├── pnpmWorkspace.ts ├── types.ts ├── utils.test.ts └── utils.ts └── tsconfig.json /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [typeofweb] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: typeofweb 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: ["main"] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: ["main"] 20 | schedule: 21 | - cron: "17 9 * * 4" 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: ["javascript"] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v3 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v2 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | 52 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 53 | # queries: security-extended,security-and-quality 54 | 55 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 56 | # If this step fails, then you should remove it and run the build manually (see below) 57 | - name: Autobuild 58 | uses: github/codeql-action/autobuild@v2 59 | 60 | # ℹ️ Command-line programs to run using the OS shell. 61 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 62 | 63 | # If the Autobuild fails above, remove it and uncomment the following three lines. 64 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 65 | 66 | # - run: | 67 | # echo "Run, Build Application using script" 68 | # ./location_of_script_within_repo/buildscript.sh 69 | 70 | - name: Perform CodeQL Analysis 71 | uses: github/codeql-action/analyze@v2 72 | with: 73 | category: "/language:${{matrix.language}}" 74 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | on: [pull_request] 3 | jobs: 4 | build_and_test: 5 | runs-on: ubuntu-latest 6 | 7 | steps: 8 | - uses: actions/checkout@v3 9 | - uses: pnpm/action-setup@v2 10 | - uses: actions/setup-node@v3 11 | with: 12 | node-version: "18.10" 13 | cache: "pnpm" 14 | 15 | - name: Install dependencies 16 | run: pnpm --version && pnpm install --frozen-lockfile 17 | 18 | - name: Build 19 | run: pnpm run build 20 | 21 | - name: Test 22 | run: pnpm run test 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | pnpm exec lint-staged 5 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 18 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "trailingComma": "all", 4 | "useTabs": true 5 | } 6 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true, 3 | "editor.defaultFormatter": "esbenp.prettier-vscode", 4 | "typescript.tsdk": "node_modules/typescript/lib", 5 | "eslint.packageManager": "yarn", 6 | "eslint.run": "onSave", 7 | "editor.codeActionsOnSave": { 8 | "source.fixAll": true 9 | }, 10 | "css.validate": false, 11 | "editor.quickSuggestions": { "strings": true } 12 | } 13 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Type of Web - Michał Miszczyszyn 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # @typeofweb/ignore-monorepo-buildstep 2 | 3 | A package that adds monorepo support for Vercel's "Ignore build-step" setting. Small, fast, with 0 external dependencies. 4 | 5 | ## Why? 6 | 7 | By default, when working in a monorepo, each push triggers Vercel to rebuild all the projects even when changes were introduced only to some of them. It takes time and blocks the build pipeline for your team. Thanks to `@typeofweb/ignore-monorepo-buildstep`, this is no longer a problem – Vercel becomes smarter and only rebuilds what needs building! 8 | 9 | In a real-life project such as [saleor/react-storefront](https://github.com/saleor/react-storefront), we've **saved up to 85% on Vercel build times – 6.6x speedup**! `@typeofweb/ignore-monorepo-buildstep` helps you save time and money. 10 | 11 | ## Example setup 12 | 13 | ### Repo structure 14 | 15 | Assume we're using [pnpm workspaces](https://pnpm.io/workspaces) and we have the following monorepo structure: 16 | 17 | ``` 18 | . 19 | ├── apps 20 | │   ├── a 21 | │   └── b 22 | └── packages 23 | ├── common 24 | └── depA 25 | ``` 26 | 27 | Apps `a` and `b` both depend on the `common` package. Moreover, app `a` depends on `depA` package. 28 | 29 | ### Vercel config 30 | 31 | Add the following command to the "Ignore Build Step" section in your Vercel project settings: 32 | 33 | ``` 34 | npx @typeofweb/ignore-monorepo-buildstep 35 | ``` 36 | 37 | ![Ignore Build Step settings in Vercel](./docs/vercel_settings.png) 38 | 39 | By default, `ignore-monorepo-buildstep` will compare `HEAD^` and `HEAD`. You can override this and use an env variable exposed by Vercel: 40 | 41 | ``` 42 | npx @typeofweb/ignore-monorepo-buildstep $VERCEL_GIT_PREVIOUS_SHA 43 | ``` 44 | 45 | ### Result 46 | 47 | When any changes are introduced to `packages/common`, both apps `a` and `b` will be built: 48 | ![](./docs/github-both.png) 49 | 50 | However, when `packages/depA` is modified, only `apps/a` is built while `apps/b` is skipped: 51 | ![](./docs/github-one.png) 52 | 53 | Moreover, deployment statuses are reported as successful even when builds are skipped: 54 | ![](./docs/github-status.png) 55 | 56 | ## How does it work? 57 | 58 | `@typeofweb/ignore-monorepo-buildstep` analyses the structure of the monorepo. It reads `pnpm-workspace.yaml` and `package.json` of every package, and creates a tree of dependencies inside the monorepo. 59 | 60 | Then, it proceeds to check whether the given package or any of its dependencies were modified since the last commit with the use of `git diff "HEAD^" "HEAD" --quiet`. 61 | 62 | Currently, only `pnpm` workspaces are supported but more is on the roadmap. 63 | -------------------------------------------------------------------------------- /docs/github-both.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/typeofweb-org/ignore-monorepo-buildstep/a0718e426f3a3e7e44123aeeb265503455eefd53/docs/github-both.png -------------------------------------------------------------------------------- /docs/github-one.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/typeofweb-org/ignore-monorepo-buildstep/a0718e426f3a3e7e44123aeeb265503455eefd53/docs/github-one.png -------------------------------------------------------------------------------- /docs/github-status.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/typeofweb-org/ignore-monorepo-buildstep/a0718e426f3a3e7e44123aeeb265503455eefd53/docs/github-status.png -------------------------------------------------------------------------------- /docs/vercel_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/typeofweb-org/ignore-monorepo-buildstep/a0718e426f3a3e7e44123aeeb265503455eefd53/docs/vercel_settings.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@typeofweb/ignore-monorepo-buildstep", 3 | "version": "0.6.2", 4 | "description": "Ignore Vercel buildstep in a pnpm monorepo", 5 | "main": "dist/index.js", 6 | "bin": "dist/index.js", 7 | "type": "module", 8 | "keywords": [ 9 | "Vercel", 10 | "pnpm", 11 | "monorepo" 12 | ], 13 | "files": [ 14 | "dist/*.js", 15 | "README.md", 16 | "LICENSE.md", 17 | "docs" 18 | ], 19 | "author": "Michał Miszczyszyn (https://typeofweb.com/)", 20 | "repository": { 21 | "url": "https://github.com/typeofweb/ignore-monorepo-buildstep" 22 | }, 23 | "bugs": { 24 | "url": "https://github.com/typeofweb/ignore-monorepo-buildstep/issues" 25 | }, 26 | "scripts": { 27 | "build": "rm -rf dist && tsc", 28 | "dev": "rm -rf dist && tsc -w", 29 | "test": "ts-node-test src/utils.test.ts ", 30 | "prepare": "husky install" 31 | }, 32 | "lint-staged": { 33 | "*.{mts,cts,ts,mjs,csj,js,md,json,yaml,yml}": "prettier --write" 34 | }, 35 | "private": false, 36 | "publishConfig": { 37 | "access": "public" 38 | }, 39 | "license": "MIT", 40 | "devDependencies": { 41 | "@types/node": "18.11.0", 42 | "husky": "8.0.1", 43 | "lint-staged": "13.0.3", 44 | "prettier": "2.7.1", 45 | "ts-node-test": "0.2.0", 46 | "typescript": "4.8.4" 47 | }, 48 | "packageManager": "pnpm@7.13.1" 49 | } 50 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: 5.4 2 | 3 | specifiers: 4 | "@types/node": 18.11.0 5 | husky: 8.0.1 6 | lint-staged: 13.0.3 7 | prettier: 2.7.1 8 | ts-node-test: 0.2.0 9 | typescript: 4.8.4 10 | 11 | devDependencies: 12 | "@types/node": registry.npmjs.org/@types/node/18.11.0 13 | husky: registry.npmjs.org/husky/8.0.1 14 | lint-staged: registry.npmjs.org/lint-staged/13.0.3 15 | prettier: registry.npmjs.org/prettier/2.7.1 16 | ts-node-test: registry.npmjs.org/ts-node-test/0.2.0_o6ib7qqltxpe7qrskddglns2ga 17 | typescript: registry.npmjs.org/typescript/4.8.4 18 | 19 | packages: 20 | registry.npmjs.org/@cspotcode/source-map-support/0.8.1: 21 | resolution: 22 | { 23 | integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==, 24 | registry: https://registry.npmjs.com/, 25 | tarball: https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz, 26 | } 27 | name: "@cspotcode/source-map-support" 28 | version: 0.8.1 29 | engines: { node: ">=12" } 30 | dependencies: 31 | "@jridgewell/trace-mapping": registry.npmjs.org/@jridgewell/trace-mapping/0.3.9 32 | dev: true 33 | 34 | registry.npmjs.org/@jridgewell/resolve-uri/3.1.0: 35 | resolution: 36 | { 37 | integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==, 38 | registry: https://registry.npmjs.com/, 39 | tarball: https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz, 40 | } 41 | name: "@jridgewell/resolve-uri" 42 | version: 3.1.0 43 | engines: { node: ">=6.0.0" } 44 | dev: true 45 | 46 | registry.npmjs.org/@jridgewell/sourcemap-codec/1.4.14: 47 | resolution: 48 | { 49 | integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==, 50 | registry: https://registry.npmjs.com/, 51 | tarball: https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz, 52 | } 53 | name: "@jridgewell/sourcemap-codec" 54 | version: 1.4.14 55 | dev: true 56 | 57 | registry.npmjs.org/@jridgewell/trace-mapping/0.3.9: 58 | resolution: 59 | { 60 | integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==, 61 | registry: https://registry.npmjs.com/, 62 | tarball: https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz, 63 | } 64 | name: "@jridgewell/trace-mapping" 65 | version: 0.3.9 66 | dependencies: 67 | "@jridgewell/resolve-uri": registry.npmjs.org/@jridgewell/resolve-uri/3.1.0 68 | "@jridgewell/sourcemap-codec": registry.npmjs.org/@jridgewell/sourcemap-codec/1.4.14 69 | dev: true 70 | 71 | registry.npmjs.org/@tsconfig/node10/1.0.9: 72 | resolution: 73 | { 74 | integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==, 75 | registry: https://registry.npmjs.com/, 76 | tarball: https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz, 77 | } 78 | name: "@tsconfig/node10" 79 | version: 1.0.9 80 | dev: true 81 | 82 | registry.npmjs.org/@tsconfig/node12/1.0.11: 83 | resolution: 84 | { 85 | integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==, 86 | registry: https://registry.npmjs.com/, 87 | tarball: https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz, 88 | } 89 | name: "@tsconfig/node12" 90 | version: 1.0.11 91 | dev: true 92 | 93 | registry.npmjs.org/@tsconfig/node14/1.0.3: 94 | resolution: 95 | { 96 | integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==, 97 | registry: https://registry.npmjs.com/, 98 | tarball: https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz, 99 | } 100 | name: "@tsconfig/node14" 101 | version: 1.0.3 102 | dev: true 103 | 104 | registry.npmjs.org/@tsconfig/node16/1.0.3: 105 | resolution: 106 | { 107 | integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==, 108 | registry: https://registry.npmjs.com/, 109 | tarball: https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz, 110 | } 111 | name: "@tsconfig/node16" 112 | version: 1.0.3 113 | dev: true 114 | 115 | registry.npmjs.org/@types/node/18.11.0: 116 | resolution: 117 | { 118 | integrity: sha512-IOXCvVRToe7e0ny7HpT/X9Rb2RYtElG1a+VshjwT00HxrM2dWBApHQoqsI6WiY7Q03vdf2bCrIGzVrkF/5t10w==, 119 | registry: https://registry.npmjs.com/, 120 | tarball: https://registry.npmjs.org/@types/node/-/node-18.11.0.tgz, 121 | } 122 | name: "@types/node" 123 | version: 18.11.0 124 | dev: true 125 | 126 | registry.npmjs.org/acorn-walk/8.2.0: 127 | resolution: 128 | { 129 | integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==, 130 | registry: https://registry.npmjs.com/, 131 | tarball: https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz, 132 | } 133 | name: acorn-walk 134 | version: 8.2.0 135 | engines: { node: ">=0.4.0" } 136 | dev: true 137 | 138 | registry.npmjs.org/acorn/8.8.0: 139 | resolution: 140 | { 141 | integrity: sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==, 142 | registry: https://registry.npmjs.com/, 143 | tarball: https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz, 144 | } 145 | name: acorn 146 | version: 8.8.0 147 | engines: { node: ">=0.4.0" } 148 | hasBin: true 149 | dev: true 150 | 151 | registry.npmjs.org/aggregate-error/3.1.0: 152 | resolution: 153 | { 154 | integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==, 155 | registry: https://registry.npmjs.com/, 156 | tarball: https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz, 157 | } 158 | name: aggregate-error 159 | version: 3.1.0 160 | engines: { node: ">=8" } 161 | dependencies: 162 | clean-stack: registry.npmjs.org/clean-stack/2.2.0 163 | indent-string: registry.npmjs.org/indent-string/4.0.0 164 | dev: true 165 | 166 | registry.npmjs.org/ansi-escapes/4.3.2: 167 | resolution: 168 | { 169 | integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==, 170 | registry: https://registry.npmjs.com/, 171 | tarball: https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz, 172 | } 173 | name: ansi-escapes 174 | version: 4.3.2 175 | engines: { node: ">=8" } 176 | dependencies: 177 | type-fest: registry.npmjs.org/type-fest/0.21.3 178 | dev: true 179 | 180 | registry.npmjs.org/ansi-regex/5.0.1: 181 | resolution: 182 | { 183 | integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==, 184 | registry: https://registry.npmjs.com/, 185 | tarball: https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz, 186 | } 187 | name: ansi-regex 188 | version: 5.0.1 189 | engines: { node: ">=8" } 190 | dev: true 191 | 192 | registry.npmjs.org/ansi-regex/6.0.1: 193 | resolution: 194 | { 195 | integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==, 196 | registry: https://registry.npmjs.com/, 197 | tarball: https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz, 198 | } 199 | name: ansi-regex 200 | version: 6.0.1 201 | engines: { node: ">=12" } 202 | dev: true 203 | 204 | registry.npmjs.org/ansi-styles/4.3.0: 205 | resolution: 206 | { 207 | integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==, 208 | registry: https://registry.npmjs.com/, 209 | tarball: https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz, 210 | } 211 | name: ansi-styles 212 | version: 4.3.0 213 | engines: { node: ">=8" } 214 | dependencies: 215 | color-convert: registry.npmjs.org/color-convert/2.0.1 216 | dev: true 217 | 218 | registry.npmjs.org/ansi-styles/6.1.1: 219 | resolution: 220 | { 221 | integrity: sha512-qDOv24WjnYuL+wbwHdlsYZFy+cgPtrYw0Tn7GLORicQp9BkQLzrgI3Pm4VyR9ERZ41YTn7KlMPuL1n05WdZvmg==, 222 | registry: https://registry.npmjs.com/, 223 | tarball: https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.1.tgz, 224 | } 225 | name: ansi-styles 226 | version: 6.1.1 227 | engines: { node: ">=12" } 228 | dev: true 229 | 230 | registry.npmjs.org/arg/4.1.3: 231 | resolution: 232 | { 233 | integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==, 234 | registry: https://registry.npmjs.com/, 235 | tarball: https://registry.npmjs.org/arg/-/arg-4.1.3.tgz, 236 | } 237 | name: arg 238 | version: 4.1.3 239 | dev: true 240 | 241 | registry.npmjs.org/astral-regex/2.0.0: 242 | resolution: 243 | { 244 | integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==, 245 | registry: https://registry.npmjs.com/, 246 | tarball: https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz, 247 | } 248 | name: astral-regex 249 | version: 2.0.0 250 | engines: { node: ">=8" } 251 | dev: true 252 | 253 | registry.npmjs.org/braces/3.0.2: 254 | resolution: 255 | { 256 | integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==, 257 | registry: https://registry.npmjs.com/, 258 | tarball: https://registry.npmjs.org/braces/-/braces-3.0.2.tgz, 259 | } 260 | name: braces 261 | version: 3.0.2 262 | engines: { node: ">=8" } 263 | dependencies: 264 | fill-range: registry.npmjs.org/fill-range/7.0.1 265 | dev: true 266 | 267 | registry.npmjs.org/clean-stack/2.2.0: 268 | resolution: 269 | { 270 | integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==, 271 | registry: https://registry.npmjs.com/, 272 | tarball: https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz, 273 | } 274 | name: clean-stack 275 | version: 2.2.0 276 | engines: { node: ">=6" } 277 | dev: true 278 | 279 | registry.npmjs.org/cli-cursor/3.1.0: 280 | resolution: 281 | { 282 | integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==, 283 | registry: https://registry.npmjs.com/, 284 | tarball: https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz, 285 | } 286 | name: cli-cursor 287 | version: 3.1.0 288 | engines: { node: ">=8" } 289 | dependencies: 290 | restore-cursor: registry.npmjs.org/restore-cursor/3.1.0 291 | dev: true 292 | 293 | registry.npmjs.org/cli-truncate/2.1.0: 294 | resolution: 295 | { 296 | integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==, 297 | registry: https://registry.npmjs.com/, 298 | tarball: https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz, 299 | } 300 | name: cli-truncate 301 | version: 2.1.0 302 | engines: { node: ">=8" } 303 | dependencies: 304 | slice-ansi: registry.npmjs.org/slice-ansi/3.0.0 305 | string-width: registry.npmjs.org/string-width/4.2.3 306 | dev: true 307 | 308 | registry.npmjs.org/cli-truncate/3.1.0: 309 | resolution: 310 | { 311 | integrity: sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==, 312 | registry: https://registry.npmjs.com/, 313 | tarball: https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz, 314 | } 315 | name: cli-truncate 316 | version: 3.1.0 317 | engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } 318 | dependencies: 319 | slice-ansi: registry.npmjs.org/slice-ansi/5.0.0 320 | string-width: registry.npmjs.org/string-width/5.1.2 321 | dev: true 322 | 323 | registry.npmjs.org/color-convert/2.0.1: 324 | resolution: 325 | { 326 | integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==, 327 | registry: https://registry.npmjs.com/, 328 | tarball: https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz, 329 | } 330 | name: color-convert 331 | version: 2.0.1 332 | engines: { node: ">=7.0.0" } 333 | dependencies: 334 | color-name: registry.npmjs.org/color-name/1.1.4 335 | dev: true 336 | 337 | registry.npmjs.org/color-name/1.1.4: 338 | resolution: 339 | { 340 | integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==, 341 | registry: https://registry.npmjs.com/, 342 | tarball: https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz, 343 | } 344 | name: color-name 345 | version: 1.1.4 346 | dev: true 347 | 348 | registry.npmjs.org/colorette/2.0.19: 349 | resolution: 350 | { 351 | integrity: sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==, 352 | registry: https://registry.npmjs.com/, 353 | tarball: https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz, 354 | } 355 | name: colorette 356 | version: 2.0.19 357 | dev: true 358 | 359 | registry.npmjs.org/commander/9.4.1: 360 | resolution: 361 | { 362 | integrity: sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==, 363 | registry: https://registry.npmjs.com/, 364 | tarball: https://registry.npmjs.org/commander/-/commander-9.4.1.tgz, 365 | } 366 | name: commander 367 | version: 9.4.1 368 | engines: { node: ^12.20.0 || >=14 } 369 | dev: true 370 | 371 | registry.npmjs.org/create-require/1.1.1: 372 | resolution: 373 | { 374 | integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==, 375 | registry: https://registry.npmjs.com/, 376 | tarball: https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz, 377 | } 378 | name: create-require 379 | version: 1.1.1 380 | dev: true 381 | 382 | registry.npmjs.org/cross-spawn/7.0.3: 383 | resolution: 384 | { 385 | integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==, 386 | registry: https://registry.npmjs.com/, 387 | tarball: https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz, 388 | } 389 | name: cross-spawn 390 | version: 7.0.3 391 | engines: { node: ">= 8" } 392 | dependencies: 393 | path-key: registry.npmjs.org/path-key/3.1.1 394 | shebang-command: registry.npmjs.org/shebang-command/2.0.0 395 | which: registry.npmjs.org/which/2.0.2 396 | dev: true 397 | 398 | registry.npmjs.org/debug/4.3.4: 399 | resolution: 400 | { 401 | integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==, 402 | registry: https://registry.npmjs.com/, 403 | tarball: https://registry.npmjs.org/debug/-/debug-4.3.4.tgz, 404 | } 405 | name: debug 406 | version: 4.3.4 407 | engines: { node: ">=6.0" } 408 | peerDependencies: 409 | supports-color: "*" 410 | peerDependenciesMeta: 411 | supports-color: 412 | optional: true 413 | dependencies: 414 | ms: registry.npmjs.org/ms/2.1.2 415 | dev: true 416 | 417 | registry.npmjs.org/diff/4.0.2: 418 | resolution: 419 | { 420 | integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==, 421 | registry: https://registry.npmjs.com/, 422 | tarball: https://registry.npmjs.org/diff/-/diff-4.0.2.tgz, 423 | } 424 | name: diff 425 | version: 4.0.2 426 | engines: { node: ">=0.3.1" } 427 | dev: true 428 | 429 | registry.npmjs.org/eastasianwidth/0.2.0: 430 | resolution: 431 | { 432 | integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==, 433 | registry: https://registry.npmjs.com/, 434 | tarball: https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz, 435 | } 436 | name: eastasianwidth 437 | version: 0.2.0 438 | dev: true 439 | 440 | registry.npmjs.org/emoji-regex/8.0.0: 441 | resolution: 442 | { 443 | integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==, 444 | registry: https://registry.npmjs.com/, 445 | tarball: https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz, 446 | } 447 | name: emoji-regex 448 | version: 8.0.0 449 | dev: true 450 | 451 | registry.npmjs.org/emoji-regex/9.2.2: 452 | resolution: 453 | { 454 | integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==, 455 | registry: https://registry.npmjs.com/, 456 | tarball: https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz, 457 | } 458 | name: emoji-regex 459 | version: 9.2.2 460 | dev: true 461 | 462 | registry.npmjs.org/execa/6.1.0: 463 | resolution: 464 | { 465 | integrity: sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==, 466 | registry: https://registry.npmjs.com/, 467 | tarball: https://registry.npmjs.org/execa/-/execa-6.1.0.tgz, 468 | } 469 | name: execa 470 | version: 6.1.0 471 | engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } 472 | dependencies: 473 | cross-spawn: registry.npmjs.org/cross-spawn/7.0.3 474 | get-stream: registry.npmjs.org/get-stream/6.0.1 475 | human-signals: registry.npmjs.org/human-signals/3.0.1 476 | is-stream: registry.npmjs.org/is-stream/3.0.0 477 | merge-stream: registry.npmjs.org/merge-stream/2.0.0 478 | npm-run-path: registry.npmjs.org/npm-run-path/5.1.0 479 | onetime: registry.npmjs.org/onetime/6.0.0 480 | signal-exit: registry.npmjs.org/signal-exit/3.0.7 481 | strip-final-newline: registry.npmjs.org/strip-final-newline/3.0.0 482 | dev: true 483 | 484 | registry.npmjs.org/fill-range/7.0.1: 485 | resolution: 486 | { 487 | integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==, 488 | registry: https://registry.npmjs.com/, 489 | tarball: https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz, 490 | } 491 | name: fill-range 492 | version: 7.0.1 493 | engines: { node: ">=8" } 494 | dependencies: 495 | to-regex-range: registry.npmjs.org/to-regex-range/5.0.1 496 | dev: true 497 | 498 | registry.npmjs.org/get-stream/6.0.1: 499 | resolution: 500 | { 501 | integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==, 502 | registry: https://registry.npmjs.com/, 503 | tarball: https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz, 504 | } 505 | name: get-stream 506 | version: 6.0.1 507 | engines: { node: ">=10" } 508 | dev: true 509 | 510 | registry.npmjs.org/human-signals/3.0.1: 511 | resolution: 512 | { 513 | integrity: sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==, 514 | registry: https://registry.npmjs.com/, 515 | tarball: https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz, 516 | } 517 | name: human-signals 518 | version: 3.0.1 519 | engines: { node: ">=12.20.0" } 520 | dev: true 521 | 522 | registry.npmjs.org/husky/8.0.1: 523 | resolution: 524 | { 525 | integrity: sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==, 526 | registry: https://registry.npmjs.com/, 527 | tarball: https://registry.npmjs.org/husky/-/husky-8.0.1.tgz, 528 | } 529 | name: husky 530 | version: 8.0.1 531 | engines: { node: ">=14" } 532 | hasBin: true 533 | dev: true 534 | 535 | registry.npmjs.org/indent-string/4.0.0: 536 | resolution: 537 | { 538 | integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==, 539 | registry: https://registry.npmjs.com/, 540 | tarball: https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz, 541 | } 542 | name: indent-string 543 | version: 4.0.0 544 | engines: { node: ">=8" } 545 | dev: true 546 | 547 | registry.npmjs.org/is-fullwidth-code-point/3.0.0: 548 | resolution: 549 | { 550 | integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==, 551 | registry: https://registry.npmjs.com/, 552 | tarball: https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz, 553 | } 554 | name: is-fullwidth-code-point 555 | version: 3.0.0 556 | engines: { node: ">=8" } 557 | dev: true 558 | 559 | registry.npmjs.org/is-fullwidth-code-point/4.0.0: 560 | resolution: 561 | { 562 | integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==, 563 | registry: https://registry.npmjs.com/, 564 | tarball: https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz, 565 | } 566 | name: is-fullwidth-code-point 567 | version: 4.0.0 568 | engines: { node: ">=12" } 569 | dev: true 570 | 571 | registry.npmjs.org/is-number/7.0.0: 572 | resolution: 573 | { 574 | integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==, 575 | registry: https://registry.npmjs.com/, 576 | tarball: https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz, 577 | } 578 | name: is-number 579 | version: 7.0.0 580 | engines: { node: ">=0.12.0" } 581 | dev: true 582 | 583 | registry.npmjs.org/is-stream/3.0.0: 584 | resolution: 585 | { 586 | integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==, 587 | registry: https://registry.npmjs.com/, 588 | tarball: https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz, 589 | } 590 | name: is-stream 591 | version: 3.0.0 592 | engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } 593 | dev: true 594 | 595 | registry.npmjs.org/isexe/2.0.0: 596 | resolution: 597 | { 598 | integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==, 599 | registry: https://registry.npmjs.com/, 600 | tarball: https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz, 601 | } 602 | name: isexe 603 | version: 2.0.0 604 | dev: true 605 | 606 | registry.npmjs.org/lilconfig/2.0.5: 607 | resolution: 608 | { 609 | integrity: sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==, 610 | registry: https://registry.npmjs.com/, 611 | tarball: https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz, 612 | } 613 | name: lilconfig 614 | version: 2.0.5 615 | engines: { node: ">=10" } 616 | dev: true 617 | 618 | registry.npmjs.org/lint-staged/13.0.3: 619 | resolution: 620 | { 621 | integrity: sha512-9hmrwSCFroTSYLjflGI8Uk+GWAwMB4OlpU4bMJEAT5d/llQwtYKoim4bLOyLCuWFAhWEupE0vkIFqtw/WIsPug==, 622 | registry: https://registry.npmjs.com/, 623 | tarball: https://registry.npmjs.org/lint-staged/-/lint-staged-13.0.3.tgz, 624 | } 625 | name: lint-staged 626 | version: 13.0.3 627 | engines: { node: ^14.13.1 || >=16.0.0 } 628 | hasBin: true 629 | dependencies: 630 | cli-truncate: registry.npmjs.org/cli-truncate/3.1.0 631 | colorette: registry.npmjs.org/colorette/2.0.19 632 | commander: registry.npmjs.org/commander/9.4.1 633 | debug: registry.npmjs.org/debug/4.3.4 634 | execa: registry.npmjs.org/execa/6.1.0 635 | lilconfig: registry.npmjs.org/lilconfig/2.0.5 636 | listr2: registry.npmjs.org/listr2/4.0.5 637 | micromatch: registry.npmjs.org/micromatch/4.0.5 638 | normalize-path: registry.npmjs.org/normalize-path/3.0.0 639 | object-inspect: registry.npmjs.org/object-inspect/1.12.2 640 | pidtree: registry.npmjs.org/pidtree/0.6.0 641 | string-argv: registry.npmjs.org/string-argv/0.3.1 642 | yaml: registry.npmjs.org/yaml/2.1.2 643 | transitivePeerDependencies: 644 | - enquirer 645 | - supports-color 646 | dev: true 647 | 648 | registry.npmjs.org/listr2/4.0.5: 649 | resolution: 650 | { 651 | integrity: sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==, 652 | registry: https://registry.npmjs.com/, 653 | tarball: https://registry.npmjs.org/listr2/-/listr2-4.0.5.tgz, 654 | } 655 | name: listr2 656 | version: 4.0.5 657 | engines: { node: ">=12" } 658 | peerDependencies: 659 | enquirer: ">= 2.3.0 < 3" 660 | peerDependenciesMeta: 661 | enquirer: 662 | optional: true 663 | dependencies: 664 | cli-truncate: registry.npmjs.org/cli-truncate/2.1.0 665 | colorette: registry.npmjs.org/colorette/2.0.19 666 | log-update: registry.npmjs.org/log-update/4.0.0 667 | p-map: registry.npmjs.org/p-map/4.0.0 668 | rfdc: registry.npmjs.org/rfdc/1.3.0 669 | rxjs: registry.npmjs.org/rxjs/7.5.7 670 | through: registry.npmjs.org/through/2.3.8 671 | wrap-ansi: registry.npmjs.org/wrap-ansi/7.0.0 672 | dev: true 673 | 674 | registry.npmjs.org/log-update/4.0.0: 675 | resolution: 676 | { 677 | integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==, 678 | registry: https://registry.npmjs.com/, 679 | tarball: https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz, 680 | } 681 | name: log-update 682 | version: 4.0.0 683 | engines: { node: ">=10" } 684 | dependencies: 685 | ansi-escapes: registry.npmjs.org/ansi-escapes/4.3.2 686 | cli-cursor: registry.npmjs.org/cli-cursor/3.1.0 687 | slice-ansi: registry.npmjs.org/slice-ansi/4.0.0 688 | wrap-ansi: registry.npmjs.org/wrap-ansi/6.2.0 689 | dev: true 690 | 691 | registry.npmjs.org/make-error/1.3.6: 692 | resolution: 693 | { 694 | integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==, 695 | registry: https://registry.npmjs.com/, 696 | tarball: https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz, 697 | } 698 | name: make-error 699 | version: 1.3.6 700 | dev: true 701 | 702 | registry.npmjs.org/merge-stream/2.0.0: 703 | resolution: 704 | { 705 | integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==, 706 | registry: https://registry.npmjs.com/, 707 | tarball: https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz, 708 | } 709 | name: merge-stream 710 | version: 2.0.0 711 | dev: true 712 | 713 | registry.npmjs.org/micromatch/4.0.5: 714 | resolution: 715 | { 716 | integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==, 717 | registry: https://registry.npmjs.com/, 718 | tarball: https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz, 719 | } 720 | name: micromatch 721 | version: 4.0.5 722 | engines: { node: ">=8.6" } 723 | dependencies: 724 | braces: registry.npmjs.org/braces/3.0.2 725 | picomatch: registry.npmjs.org/picomatch/2.3.1 726 | dev: true 727 | 728 | registry.npmjs.org/mimic-fn/2.1.0: 729 | resolution: 730 | { 731 | integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==, 732 | registry: https://registry.npmjs.com/, 733 | tarball: https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz, 734 | } 735 | name: mimic-fn 736 | version: 2.1.0 737 | engines: { node: ">=6" } 738 | dev: true 739 | 740 | registry.npmjs.org/mimic-fn/4.0.0: 741 | resolution: 742 | { 743 | integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==, 744 | registry: https://registry.npmjs.com/, 745 | tarball: https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz, 746 | } 747 | name: mimic-fn 748 | version: 4.0.0 749 | engines: { node: ">=12" } 750 | dev: true 751 | 752 | registry.npmjs.org/ms/2.1.2: 753 | resolution: 754 | { 755 | integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==, 756 | registry: https://registry.npmjs.com/, 757 | tarball: https://registry.npmjs.org/ms/-/ms-2.1.2.tgz, 758 | } 759 | name: ms 760 | version: 2.1.2 761 | dev: true 762 | 763 | registry.npmjs.org/normalize-path/3.0.0: 764 | resolution: 765 | { 766 | integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==, 767 | registry: https://registry.npmjs.com/, 768 | tarball: https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz, 769 | } 770 | name: normalize-path 771 | version: 3.0.0 772 | engines: { node: ">=0.10.0" } 773 | dev: true 774 | 775 | registry.npmjs.org/npm-run-path/5.1.0: 776 | resolution: 777 | { 778 | integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==, 779 | registry: https://registry.npmjs.com/, 780 | tarball: https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz, 781 | } 782 | name: npm-run-path 783 | version: 5.1.0 784 | engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } 785 | dependencies: 786 | path-key: registry.npmjs.org/path-key/4.0.0 787 | dev: true 788 | 789 | registry.npmjs.org/object-inspect/1.12.2: 790 | resolution: 791 | { 792 | integrity: sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==, 793 | registry: https://registry.npmjs.com/, 794 | tarball: https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz, 795 | } 796 | name: object-inspect 797 | version: 1.12.2 798 | dev: true 799 | 800 | registry.npmjs.org/onetime/5.1.2: 801 | resolution: 802 | { 803 | integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==, 804 | registry: https://registry.npmjs.com/, 805 | tarball: https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz, 806 | } 807 | name: onetime 808 | version: 5.1.2 809 | engines: { node: ">=6" } 810 | dependencies: 811 | mimic-fn: registry.npmjs.org/mimic-fn/2.1.0 812 | dev: true 813 | 814 | registry.npmjs.org/onetime/6.0.0: 815 | resolution: 816 | { 817 | integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==, 818 | registry: https://registry.npmjs.com/, 819 | tarball: https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz, 820 | } 821 | name: onetime 822 | version: 6.0.0 823 | engines: { node: ">=12" } 824 | dependencies: 825 | mimic-fn: registry.npmjs.org/mimic-fn/4.0.0 826 | dev: true 827 | 828 | registry.npmjs.org/p-map/4.0.0: 829 | resolution: 830 | { 831 | integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==, 832 | registry: https://registry.npmjs.com/, 833 | tarball: https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz, 834 | } 835 | name: p-map 836 | version: 4.0.0 837 | engines: { node: ">=10" } 838 | dependencies: 839 | aggregate-error: registry.npmjs.org/aggregate-error/3.1.0 840 | dev: true 841 | 842 | registry.npmjs.org/path-key/3.1.1: 843 | resolution: 844 | { 845 | integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==, 846 | registry: https://registry.npmjs.com/, 847 | tarball: https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz, 848 | } 849 | name: path-key 850 | version: 3.1.1 851 | engines: { node: ">=8" } 852 | dev: true 853 | 854 | registry.npmjs.org/path-key/4.0.0: 855 | resolution: 856 | { 857 | integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==, 858 | registry: https://registry.npmjs.com/, 859 | tarball: https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz, 860 | } 861 | name: path-key 862 | version: 4.0.0 863 | engines: { node: ">=12" } 864 | dev: true 865 | 866 | registry.npmjs.org/picomatch/2.3.1: 867 | resolution: 868 | { 869 | integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==, 870 | registry: https://registry.npmjs.com/, 871 | tarball: https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz, 872 | } 873 | name: picomatch 874 | version: 2.3.1 875 | engines: { node: ">=8.6" } 876 | dev: true 877 | 878 | registry.npmjs.org/pidtree/0.6.0: 879 | resolution: 880 | { 881 | integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==, 882 | registry: https://registry.npmjs.com/, 883 | tarball: https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz, 884 | } 885 | name: pidtree 886 | version: 0.6.0 887 | engines: { node: ">=0.10" } 888 | hasBin: true 889 | dev: true 890 | 891 | registry.npmjs.org/prettier/2.7.1: 892 | resolution: 893 | { 894 | integrity: sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==, 895 | registry: https://registry.npmjs.com/, 896 | tarball: https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz, 897 | } 898 | name: prettier 899 | version: 2.7.1 900 | engines: { node: ">=10.13.0" } 901 | hasBin: true 902 | dev: true 903 | 904 | registry.npmjs.org/restore-cursor/3.1.0: 905 | resolution: 906 | { 907 | integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==, 908 | registry: https://registry.npmjs.com/, 909 | tarball: https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz, 910 | } 911 | name: restore-cursor 912 | version: 3.1.0 913 | engines: { node: ">=8" } 914 | dependencies: 915 | onetime: registry.npmjs.org/onetime/5.1.2 916 | signal-exit: registry.npmjs.org/signal-exit/3.0.7 917 | dev: true 918 | 919 | registry.npmjs.org/rfdc/1.3.0: 920 | resolution: 921 | { 922 | integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==, 923 | registry: https://registry.npmjs.com/, 924 | tarball: https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz, 925 | } 926 | name: rfdc 927 | version: 1.3.0 928 | dev: true 929 | 930 | registry.npmjs.org/rxjs/7.5.7: 931 | resolution: 932 | { 933 | integrity: sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==, 934 | registry: https://registry.npmjs.com/, 935 | tarball: https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz, 936 | } 937 | name: rxjs 938 | version: 7.5.7 939 | dependencies: 940 | tslib: registry.npmjs.org/tslib/2.4.0 941 | dev: true 942 | 943 | registry.npmjs.org/shebang-command/2.0.0: 944 | resolution: 945 | { 946 | integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==, 947 | registry: https://registry.npmjs.com/, 948 | tarball: https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz, 949 | } 950 | name: shebang-command 951 | version: 2.0.0 952 | engines: { node: ">=8" } 953 | dependencies: 954 | shebang-regex: registry.npmjs.org/shebang-regex/3.0.0 955 | dev: true 956 | 957 | registry.npmjs.org/shebang-regex/3.0.0: 958 | resolution: 959 | { 960 | integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==, 961 | registry: https://registry.npmjs.com/, 962 | tarball: https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz, 963 | } 964 | name: shebang-regex 965 | version: 3.0.0 966 | engines: { node: ">=8" } 967 | dev: true 968 | 969 | registry.npmjs.org/signal-exit/3.0.7: 970 | resolution: 971 | { 972 | integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==, 973 | registry: https://registry.npmjs.com/, 974 | tarball: https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz, 975 | } 976 | name: signal-exit 977 | version: 3.0.7 978 | dev: true 979 | 980 | registry.npmjs.org/slice-ansi/3.0.0: 981 | resolution: 982 | { 983 | integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==, 984 | registry: https://registry.npmjs.com/, 985 | tarball: https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz, 986 | } 987 | name: slice-ansi 988 | version: 3.0.0 989 | engines: { node: ">=8" } 990 | dependencies: 991 | ansi-styles: registry.npmjs.org/ansi-styles/4.3.0 992 | astral-regex: registry.npmjs.org/astral-regex/2.0.0 993 | is-fullwidth-code-point: registry.npmjs.org/is-fullwidth-code-point/3.0.0 994 | dev: true 995 | 996 | registry.npmjs.org/slice-ansi/4.0.0: 997 | resolution: 998 | { 999 | integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==, 1000 | registry: https://registry.npmjs.com/, 1001 | tarball: https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz, 1002 | } 1003 | name: slice-ansi 1004 | version: 4.0.0 1005 | engines: { node: ">=10" } 1006 | dependencies: 1007 | ansi-styles: registry.npmjs.org/ansi-styles/4.3.0 1008 | astral-regex: registry.npmjs.org/astral-regex/2.0.0 1009 | is-fullwidth-code-point: registry.npmjs.org/is-fullwidth-code-point/3.0.0 1010 | dev: true 1011 | 1012 | registry.npmjs.org/slice-ansi/5.0.0: 1013 | resolution: 1014 | { 1015 | integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==, 1016 | registry: https://registry.npmjs.com/, 1017 | tarball: https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz, 1018 | } 1019 | name: slice-ansi 1020 | version: 5.0.0 1021 | engines: { node: ">=12" } 1022 | dependencies: 1023 | ansi-styles: registry.npmjs.org/ansi-styles/6.1.1 1024 | is-fullwidth-code-point: registry.npmjs.org/is-fullwidth-code-point/4.0.0 1025 | dev: true 1026 | 1027 | registry.npmjs.org/string-argv/0.3.1: 1028 | resolution: 1029 | { 1030 | integrity: sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==, 1031 | registry: https://registry.npmjs.com/, 1032 | tarball: https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz, 1033 | } 1034 | name: string-argv 1035 | version: 0.3.1 1036 | engines: { node: ">=0.6.19" } 1037 | dev: true 1038 | 1039 | registry.npmjs.org/string-width/4.2.3: 1040 | resolution: 1041 | { 1042 | integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==, 1043 | registry: https://registry.npmjs.com/, 1044 | tarball: https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz, 1045 | } 1046 | name: string-width 1047 | version: 4.2.3 1048 | engines: { node: ">=8" } 1049 | dependencies: 1050 | emoji-regex: registry.npmjs.org/emoji-regex/8.0.0 1051 | is-fullwidth-code-point: registry.npmjs.org/is-fullwidth-code-point/3.0.0 1052 | strip-ansi: registry.npmjs.org/strip-ansi/6.0.1 1053 | dev: true 1054 | 1055 | registry.npmjs.org/string-width/5.1.2: 1056 | resolution: 1057 | { 1058 | integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==, 1059 | registry: https://registry.npmjs.com/, 1060 | tarball: https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz, 1061 | } 1062 | name: string-width 1063 | version: 5.1.2 1064 | engines: { node: ">=12" } 1065 | dependencies: 1066 | eastasianwidth: registry.npmjs.org/eastasianwidth/0.2.0 1067 | emoji-regex: registry.npmjs.org/emoji-regex/9.2.2 1068 | strip-ansi: registry.npmjs.org/strip-ansi/7.0.1 1069 | dev: true 1070 | 1071 | registry.npmjs.org/strip-ansi/6.0.1: 1072 | resolution: 1073 | { 1074 | integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==, 1075 | registry: https://registry.npmjs.com/, 1076 | tarball: https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz, 1077 | } 1078 | name: strip-ansi 1079 | version: 6.0.1 1080 | engines: { node: ">=8" } 1081 | dependencies: 1082 | ansi-regex: registry.npmjs.org/ansi-regex/5.0.1 1083 | dev: true 1084 | 1085 | registry.npmjs.org/strip-ansi/7.0.1: 1086 | resolution: 1087 | { 1088 | integrity: sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==, 1089 | registry: https://registry.npmjs.com/, 1090 | tarball: https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz, 1091 | } 1092 | name: strip-ansi 1093 | version: 7.0.1 1094 | engines: { node: ">=12" } 1095 | dependencies: 1096 | ansi-regex: registry.npmjs.org/ansi-regex/6.0.1 1097 | dev: true 1098 | 1099 | registry.npmjs.org/strip-final-newline/3.0.0: 1100 | resolution: 1101 | { 1102 | integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==, 1103 | registry: https://registry.npmjs.com/, 1104 | tarball: https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz, 1105 | } 1106 | name: strip-final-newline 1107 | version: 3.0.0 1108 | engines: { node: ">=12" } 1109 | dev: true 1110 | 1111 | registry.npmjs.org/through/2.3.8: 1112 | resolution: 1113 | { 1114 | integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==, 1115 | registry: https://registry.npmjs.com/, 1116 | tarball: https://registry.npmjs.org/through/-/through-2.3.8.tgz, 1117 | } 1118 | name: through 1119 | version: 2.3.8 1120 | dev: true 1121 | 1122 | registry.npmjs.org/to-regex-range/5.0.1: 1123 | resolution: 1124 | { 1125 | integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==, 1126 | registry: https://registry.npmjs.com/, 1127 | tarball: https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz, 1128 | } 1129 | name: to-regex-range 1130 | version: 5.0.1 1131 | engines: { node: ">=8.0" } 1132 | dependencies: 1133 | is-number: registry.npmjs.org/is-number/7.0.0 1134 | dev: true 1135 | 1136 | registry.npmjs.org/ts-node-test/0.2.0_o6ib7qqltxpe7qrskddglns2ga: 1137 | resolution: 1138 | { 1139 | integrity: sha512-d3tMATFBY+ZmuEzXRRJ87MAHdh5vkefe+irpdy1DodVT2AHEf0z3tCDyV0O/tzH0oyQqeJXB3Y1B2emh5snFiA==, 1140 | registry: https://registry.npmjs.com/, 1141 | tarball: https://registry.npmjs.org/ts-node-test/-/ts-node-test-0.2.0.tgz, 1142 | } 1143 | id: registry.npmjs.org/ts-node-test/0.2.0 1144 | name: ts-node-test 1145 | version: 0.2.0 1146 | engines: { node: ">=18.7.0" } 1147 | hasBin: true 1148 | peerDependencies: 1149 | typescript: ^4.0.0 1150 | dependencies: 1151 | ts-node: registry.npmjs.org/ts-node/10.9.1_o6ib7qqltxpe7qrskddglns2ga 1152 | typescript: registry.npmjs.org/typescript/4.8.4 1153 | transitivePeerDependencies: 1154 | - "@swc/core" 1155 | - "@swc/wasm" 1156 | - "@types/node" 1157 | dev: true 1158 | 1159 | registry.npmjs.org/ts-node/10.9.1_o6ib7qqltxpe7qrskddglns2ga: 1160 | resolution: 1161 | { 1162 | integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==, 1163 | registry: https://registry.npmjs.com/, 1164 | tarball: https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz, 1165 | } 1166 | id: registry.npmjs.org/ts-node/10.9.1 1167 | name: ts-node 1168 | version: 10.9.1 1169 | hasBin: true 1170 | peerDependencies: 1171 | "@swc/core": ">=1.2.50" 1172 | "@swc/wasm": ">=1.2.50" 1173 | "@types/node": "*" 1174 | typescript: ">=2.7" 1175 | peerDependenciesMeta: 1176 | "@swc/core": 1177 | optional: true 1178 | "@swc/wasm": 1179 | optional: true 1180 | dependencies: 1181 | "@cspotcode/source-map-support": registry.npmjs.org/@cspotcode/source-map-support/0.8.1 1182 | "@tsconfig/node10": registry.npmjs.org/@tsconfig/node10/1.0.9 1183 | "@tsconfig/node12": registry.npmjs.org/@tsconfig/node12/1.0.11 1184 | "@tsconfig/node14": registry.npmjs.org/@tsconfig/node14/1.0.3 1185 | "@tsconfig/node16": registry.npmjs.org/@tsconfig/node16/1.0.3 1186 | "@types/node": registry.npmjs.org/@types/node/18.11.0 1187 | acorn: registry.npmjs.org/acorn/8.8.0 1188 | acorn-walk: registry.npmjs.org/acorn-walk/8.2.0 1189 | arg: registry.npmjs.org/arg/4.1.3 1190 | create-require: registry.npmjs.org/create-require/1.1.1 1191 | diff: registry.npmjs.org/diff/4.0.2 1192 | make-error: registry.npmjs.org/make-error/1.3.6 1193 | typescript: registry.npmjs.org/typescript/4.8.4 1194 | v8-compile-cache-lib: registry.npmjs.org/v8-compile-cache-lib/3.0.1 1195 | yn: registry.npmjs.org/yn/3.1.1 1196 | dev: true 1197 | 1198 | registry.npmjs.org/tslib/2.4.0: 1199 | resolution: 1200 | { 1201 | integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==, 1202 | registry: https://registry.npmjs.com/, 1203 | tarball: https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz, 1204 | } 1205 | name: tslib 1206 | version: 2.4.0 1207 | dev: true 1208 | 1209 | registry.npmjs.org/type-fest/0.21.3: 1210 | resolution: 1211 | { 1212 | integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==, 1213 | registry: https://registry.npmjs.com/, 1214 | tarball: https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz, 1215 | } 1216 | name: type-fest 1217 | version: 0.21.3 1218 | engines: { node: ">=10" } 1219 | dev: true 1220 | 1221 | registry.npmjs.org/typescript/4.8.4: 1222 | resolution: 1223 | { 1224 | integrity: sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==, 1225 | registry: https://registry.npmjs.com/, 1226 | tarball: https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz, 1227 | } 1228 | name: typescript 1229 | version: 4.8.4 1230 | engines: { node: ">=4.2.0" } 1231 | hasBin: true 1232 | dev: true 1233 | 1234 | registry.npmjs.org/v8-compile-cache-lib/3.0.1: 1235 | resolution: 1236 | { 1237 | integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==, 1238 | registry: https://registry.npmjs.com/, 1239 | tarball: https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz, 1240 | } 1241 | name: v8-compile-cache-lib 1242 | version: 3.0.1 1243 | dev: true 1244 | 1245 | registry.npmjs.org/which/2.0.2: 1246 | resolution: 1247 | { 1248 | integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==, 1249 | registry: https://registry.npmjs.com/, 1250 | tarball: https://registry.npmjs.org/which/-/which-2.0.2.tgz, 1251 | } 1252 | name: which 1253 | version: 2.0.2 1254 | engines: { node: ">= 8" } 1255 | hasBin: true 1256 | dependencies: 1257 | isexe: registry.npmjs.org/isexe/2.0.0 1258 | dev: true 1259 | 1260 | registry.npmjs.org/wrap-ansi/6.2.0: 1261 | resolution: 1262 | { 1263 | integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==, 1264 | registry: https://registry.npmjs.com/, 1265 | tarball: https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz, 1266 | } 1267 | name: wrap-ansi 1268 | version: 6.2.0 1269 | engines: { node: ">=8" } 1270 | dependencies: 1271 | ansi-styles: registry.npmjs.org/ansi-styles/4.3.0 1272 | string-width: registry.npmjs.org/string-width/4.2.3 1273 | strip-ansi: registry.npmjs.org/strip-ansi/6.0.1 1274 | dev: true 1275 | 1276 | registry.npmjs.org/wrap-ansi/7.0.0: 1277 | resolution: 1278 | { 1279 | integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==, 1280 | registry: https://registry.npmjs.com/, 1281 | tarball: https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz, 1282 | } 1283 | name: wrap-ansi 1284 | version: 7.0.0 1285 | engines: { node: ">=10" } 1286 | dependencies: 1287 | ansi-styles: registry.npmjs.org/ansi-styles/4.3.0 1288 | string-width: registry.npmjs.org/string-width/4.2.3 1289 | strip-ansi: registry.npmjs.org/strip-ansi/6.0.1 1290 | dev: true 1291 | 1292 | registry.npmjs.org/yaml/2.1.2: 1293 | resolution: 1294 | { 1295 | integrity: sha512-VSdf2/K3FqAetooKQv45Hcu6sA00aDgWZeGcG6V9IYJnVLTnb6988Tie79K5nx2vK7cEpf+yW8Oy+7iPAbdiHA==, 1296 | registry: https://registry.npmjs.com/, 1297 | tarball: https://registry.npmjs.org/yaml/-/yaml-2.1.2.tgz, 1298 | } 1299 | name: yaml 1300 | version: 2.1.2 1301 | engines: { node: ">= 14" } 1302 | dev: true 1303 | 1304 | registry.npmjs.org/yn/3.1.1: 1305 | resolution: 1306 | { 1307 | integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==, 1308 | registry: https://registry.npmjs.com/, 1309 | tarball: https://registry.npmjs.org/yn/-/yn-3.1.1.tgz, 1310 | } 1311 | name: yn 1312 | version: 3.1.1 1313 | engines: { node: ">=6" } 1314 | dev: true 1315 | -------------------------------------------------------------------------------- /src/debug.ts: -------------------------------------------------------------------------------- 1 | export const debug = 2 | (verbose: boolean) => 3 | (...args: unknown[]) => { 4 | if (verbose) { 5 | console.log(...args); 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /src/git.ts: -------------------------------------------------------------------------------- 1 | import { execFile } from "node:child_process"; 2 | import { promisify } from "node:util"; 3 | const execFileAsync = promisify(execFile); 4 | 5 | export const compare = ({ 6 | from, 7 | to, 8 | paths, 9 | pathsToIgnore, 10 | }: { 11 | from: string; 12 | to: string; 13 | paths: string[]; 14 | pathsToIgnore: string[]; 15 | }) => { 16 | return execFileAsync(`git`, [ 17 | `diff`, 18 | from, 19 | to, 20 | `--quiet`, 21 | ...paths, 22 | ...pathsToIgnore.map((path) => `:^${path}`), 23 | ]); 24 | }; 25 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { existsSync } from "node:fs"; 4 | import Path from "node:path"; 5 | 6 | import { promiseErrorToSettled } from "./utils.js"; 7 | import { 8 | readWorkspaceDirs, 9 | readWorkspaceSettings, 10 | resolveWorkspaceDeps, 11 | } from "./pnpmWorkspace.js"; 12 | import { compare } from "./git.js"; 13 | import { debug } from "./debug.js"; 14 | import { parseArgs } from "./parseArgs.js"; 15 | 16 | const cwd = process.cwd(); 17 | 18 | const [_node, _bin, ...args] = process.argv; 19 | 20 | const configuration = parseArgs({ 21 | args, 22 | allowPositionals: true, 23 | options: { 24 | verbose: { 25 | type: "boolean", 26 | default: false, 27 | }, 28 | }, 29 | }); 30 | 31 | const log = debug(configuration.values.verbose); 32 | 33 | const [gitFromPointer = "HEAD^", gitToPointer = "HEAD"] = 34 | configuration.positionals; 35 | 36 | log({ gitFromPointer, gitToPointer }); 37 | 38 | const rootDir = cwd 39 | .split(Path.sep) 40 | .map((_, idx) => Path.join(cwd, "../".repeat(idx))) 41 | .find((path) => existsSync(Path.join(path, "pnpm-workspace.yaml"))); 42 | 43 | log({ rootDir }); 44 | 45 | if (!rootDir) { 46 | throw new Error(`Couldn't determine rootDir!`); 47 | } 48 | 49 | const workspaceSettings = await readWorkspaceSettings({ rootDir, cwd }); 50 | const workspaceDeps = resolveWorkspaceDeps( 51 | workspaceSettings.workspaces, 52 | workspaceSettings.currentWorkspace, 53 | ); 54 | 55 | const workspaceDepsPaths = workspaceDeps 56 | .map((name) => workspaceSettings.workspaces[name]?.packagePath) 57 | .filter((path): path is string => typeof path === "string"); 58 | 59 | log({ workspaceDepsPaths }); 60 | 61 | const workspaceDepsRelativePaths = [cwd, ...workspaceDepsPaths].map( 62 | (path) => Path.relative(cwd, path) || ".", 63 | ); 64 | 65 | log({ workspaceDepsRelativePaths }); 66 | 67 | const result = await Promise.all([ 68 | ...workspaceDepsRelativePaths.map(async (path) => { 69 | return { 70 | result: await promiseErrorToSettled( 71 | compare({ 72 | from: gitFromPointer, 73 | to: gitToPointer, 74 | paths: [path], 75 | pathsToIgnore: [], 76 | }), 77 | ), 78 | path, 79 | }; 80 | }), 81 | (async () => { 82 | const pathsToIgnore = (await readWorkspaceDirs({ rootDir, cwd })).map( 83 | (path) => Path.relative(cwd, path), 84 | ); 85 | const relativeRoot = Path.relative(cwd, rootDir); 86 | 87 | return { 88 | result: await promiseErrorToSettled( 89 | compare({ 90 | from: gitFromPointer, 91 | to: gitToPointer, 92 | paths: [relativeRoot], 93 | pathsToIgnore, 94 | }), 95 | ), 96 | path: relativeRoot, 97 | }; 98 | })(), 99 | ]); 100 | 101 | const dirtyTrees = result 102 | .map((r) => { 103 | log(r); 104 | return r; 105 | }) 106 | .filter((r) => r.result.status === "rejected") 107 | .map((d) => "/" + Path.relative(rootDir, Path.resolve(cwd, d.path))) 108 | .sort(); 109 | if (dirtyTrees.length > 0) { 110 | console.log( 111 | ` 112 | Tree modified at: 113 | ${dirtyTrees.join("\n")} 114 | `.trim(), 115 | ); 116 | process.exit(1); 117 | } else { 118 | process.exit(0); 119 | } 120 | -------------------------------------------------------------------------------- /src/parseArgs.ts: -------------------------------------------------------------------------------- 1 | import assert from "node:assert"; 2 | 3 | // VERY simplified polyfill for parseArgs 4 | type Options = { 5 | type: "boolean"; 6 | default: boolean; 7 | }; 8 | export const parseArgs = ({ 9 | args, 10 | allowPositionals, 11 | options, 12 | }: { 13 | args: string[]; 14 | allowPositionals: true; 15 | options: Record; 16 | }) => { 17 | if (!allowPositionals) { 18 | assert(args.every((arg) => arg.startsWith("--"))); 19 | } 20 | 21 | const positionals = args.filter((arg) => !arg.startsWith("--")); 22 | 23 | const defaultNamed = Object.entries(options).map((arg) => { 24 | const [name, options] = arg as [Keys, Options]; 25 | return [name, options.default]; 26 | }); 27 | const named = args 28 | .filter((arg) => arg.startsWith("--")) 29 | .map((arg) => arg.slice(2)) 30 | .map((arg) => [arg, true]); 31 | 32 | return { 33 | values: Object.fromEntries([...defaultNamed, ...named]) as Record< 34 | Keys, 35 | boolean 36 | >, 37 | positionals, 38 | }; 39 | }; 40 | -------------------------------------------------------------------------------- /src/pnpmWorkspace.ts: -------------------------------------------------------------------------------- 1 | import { readFile, readdir } from "node:fs/promises"; 2 | import Path from "node:path"; 3 | import { fileExist, readJson } from "./utils.js"; 4 | import { Ctx, Workspace, PackageJson } from "./types.js"; 5 | 6 | export async function readWorkspaceSettings({ rootDir, cwd }: Ctx): Promise<{ 7 | workspaces: Record; 8 | currentWorkspace: Workspace; 9 | }> { 10 | const workspaceDirs = await readWorkspaceDirs({ rootDir, cwd }); 11 | 12 | const workspaces = (await Promise.all(workspaceDirs.map(findPackagesInDir))) 13 | .flat() 14 | .map((w) => [w.name, w] as const); 15 | const currentWorkspace = workspaces.find( 16 | ([, w]) => w.packagePath === cwd, 17 | )?.[1]; 18 | 19 | if (!currentWorkspace) { 20 | throw new Error(`Couldn't find currentWorkspace: ${cwd}`); 21 | } 22 | const { name } = currentWorkspace; 23 | if (!name) { 24 | throw new Error(`Workspace must have name: ${cwd}`); 25 | } 26 | 27 | return { 28 | workspaces: Object.fromEntries(workspaces), 29 | currentWorkspace: { ...currentWorkspace, name }, 30 | }; 31 | } 32 | 33 | export function resolveWorkspaceDeps( 34 | allWorkspaces: Record, 35 | { dependsOn }: Workspace, 36 | ): string[] { 37 | return [ 38 | ...new Set([ 39 | ...dependsOn, 40 | ...dependsOn.flatMap((d) => 41 | allWorkspaces[d] 42 | ? resolveWorkspaceDeps(allWorkspaces, allWorkspaces[d]!) 43 | : [], 44 | ), 45 | ]), 46 | ]; 47 | } 48 | 49 | export async function readWorkspaceDirs({ rootDir }: Ctx) { 50 | const workspaceSettingsPath = Path.join(rootDir, "pnpm-workspace.yaml"); 51 | const workspaceSettings = await readFile(workspaceSettingsPath, "utf-8"); 52 | 53 | return ( 54 | workspaceSettings 55 | .split("\n") 56 | .map((line) => line.trim()) 57 | .filter((line) => line.startsWith("-")) 58 | .map((line) => /"([^"]+)"/.exec(line)?.[1]?.trim()) 59 | .filter((glob): glob is string => typeof glob === "string") 60 | // @todo support exclusions? 61 | .filter((glob) => !glob.startsWith("!")) 62 | .map((glob) => glob.replace(/\/\*{1,2}$/, "")) 63 | .map((path) => Path.join(rootDir, path)) 64 | ); 65 | } 66 | 67 | async function findPackagesInDir(path: string) { 68 | const directories = await readdir(path); 69 | const packages = await Promise.all( 70 | directories.map(async (dir) => { 71 | const packagePath = Path.join(path, dir); 72 | const packageJsonPath = Path.join(packagePath, "package.json"); 73 | const exists = await fileExist(packageJsonPath); 74 | return { packagePath, packageJsonPath, exists }; 75 | }), 76 | ); 77 | 78 | return await Promise.all( 79 | packages 80 | .filter(({ exists }) => exists) 81 | .map(async ({ packagePath, packageJsonPath }) => { 82 | const pkg = await readJson(packageJsonPath); 83 | const dependsOn = getWorkspaceDeps(pkg); 84 | return { dependsOn, name: pkg.name, packagePath }; 85 | }), 86 | ); 87 | } 88 | 89 | function getWorkspaceDeps(pkg: PackageJson) { 90 | const deps = [ 91 | ...Object.entries(pkg.dependencies ?? {}), 92 | ...Object.entries(pkg.devDependencies ?? {}), 93 | ] 94 | .filter(([, version]) => version.startsWith("workspace:")) 95 | .map(([name]) => name); 96 | return [...new Set(deps)]; 97 | } 98 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | export type PackageJson = Partial<{ 2 | name: string; 3 | dependencies: Record; 4 | devDependencies: Record; 5 | }>; 6 | 7 | export type Ctx = { 8 | cwd: string; 9 | rootDir: string; 10 | }; 11 | 12 | export type Workspace = { 13 | name: string; 14 | packagePath: string; 15 | dependsOn: string[]; 16 | }; 17 | -------------------------------------------------------------------------------- /src/utils.test.ts: -------------------------------------------------------------------------------- 1 | import assert from "node:assert"; 2 | import { describe, it } from "node:test"; 3 | import { promiseErrorToSettled } from "./utils.js"; 4 | 5 | describe("utils", async () => { 6 | describe("promiseErrorToSettled", () => { 7 | it("should convert fulfilled promise", async () => { 8 | const result = await promiseErrorToSettled(Promise.resolve("test")); 9 | assert.deepEqual(result, { status: "fulfilled", value: "test" }); 10 | }); 11 | 12 | it("should convert rejected promise", async () => { 13 | const result = await promiseErrorToSettled(Promise.reject("test")); 14 | assert.deepEqual(result, { status: "rejected", reason: "test" }); 15 | }); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import { readFile, stat } from "node:fs/promises"; 2 | 3 | export function promiseErrorToSettled( 4 | promise: Promise, 5 | ): Promise> { 6 | return promise.then( 7 | (result) => ({ 8 | status: "fulfilled", 9 | value: result, 10 | }), 11 | (err) => ({ 12 | status: "rejected", 13 | reason: err, 14 | }), 15 | ); 16 | } 17 | 18 | export async function fileExist(path: string) { 19 | try { 20 | await stat(path); 21 | return true; 22 | } catch { 23 | return false; 24 | } 25 | } 26 | 27 | export async function readJson(path: string): Promise { 28 | try { 29 | const json = await readFile(path, "utf-8"); 30 | return JSON.parse(json) as T; 31 | } catch (err) { 32 | throw new Error(`Couldn't read JSON at ${path}!`); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "incremental": true /* Save .tsbuildinfo files to allow for incremental compilation of projects. */, 4 | "target": "ESNext" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, 5 | "module": "NodeNext" /* Specify what module code is generated. */, 6 | "resolveJsonModule": true /* Enable importing .json files. */, 7 | "allowJs": true /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */, 8 | "checkJs": true /* Enable error reporting in type-checked JavaScript files. */, 9 | "isolatedModules": true /* Ensure that each file can be safely transpiled without relying on other imports. */, 10 | "allowSyntheticDefaultImports": true /* Allow 'import x from y' when a module doesn't have a default export. */, 11 | "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, 12 | "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, 13 | 14 | "strict": true /* Enable all strict type-checking options. */, 15 | "noImplicitAny": true /* Enable error reporting for expressions and declarations with an implied 'any' type. */, 16 | "strictNullChecks": true /* When type checking, take into account 'null' and 'undefined'. */, 17 | "strictFunctionTypes": true /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */, 18 | "strictBindCallApply": true /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */, 19 | "strictPropertyInitialization": true /* Check for class properties that are declared but not set in the constructor. */, 20 | "noImplicitThis": true /* Enable error reporting when 'this' is given the type 'any'. */, 21 | "useUnknownInCatchVariables": true /* Default catch clause variables as 'unknown' instead of 'any'. */, 22 | "alwaysStrict": true /* Ensure 'use strict' is always emitted. */, 23 | "noUnusedLocals": true /* Enable error reporting when local variables aren't read. */, 24 | "noUnusedParameters": true /* Raise an error when a function parameter isn't read. */, 25 | "exactOptionalPropertyTypes": true /* Interpret optional property types as written, rather than adding 'undefined'. */, 26 | "noImplicitReturns": true /* Enable error reporting for codepaths that do not explicitly return in a function. */, 27 | "noFallthroughCasesInSwitch": true /* Enable error reporting for fallthrough cases in switch statements. */, 28 | "noUncheckedIndexedAccess": true /* Add 'undefined' to a type when accessed using an index. */, 29 | "noImplicitOverride": true /* Ensure overriding members in derived classes are marked with an override modifier. */, 30 | "noPropertyAccessFromIndexSignature": true /* Enforces using indexed accessors for keys declared using an indexed type. */, 31 | "allowUnusedLabels": true /* Disable error reporting for unused labels. */, 32 | "allowUnreachableCode": true /* Disable error reporting for unreachable code. */, 33 | 34 | "skipLibCheck": true /* Skip type checking all .d.ts files. */, 35 | "outDir": "dist" 36 | }, 37 | "include": ["src"], 38 | "exclude": ["src/*.test.*"] 39 | } 40 | --------------------------------------------------------------------------------