├── .eslintignore ├── .eslintrc ├── .github ├── actions │ └── setup │ │ └── action.yml └── workflows │ └── ci.yml ├── .gitignore ├── .nvmrc ├── .prettierrc.json ├── .release-it.json ├── .yarn └── releases │ └── yarn-4.3.1.cjs ├── .yarnrc.yml ├── README.md ├── __fixtures__ └── output.md ├── __tests__ ├── __file_snapshots__ │ ├── matches-binary-content-of-file-on-disk-0 │ ├── matches-content-of-file-on-disk-with-file-extension-0.md │ ├── matches-content-of-file-on-disk-without-filename-0 │ ├── works-with-.not-0 │ ├── works-with-.not-for-binary-files-0 │ └── works-with-non-binary-buffer-content-0 ├── index.test.js └── minimal.pdf ├── commitlint.config.js ├── index.d.ts ├── index.js ├── lefthook.yml ├── package.json ├── tsconfig.json └── yarn.lock /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | 3 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | extends: "satya164", 3 | env: { 4 | node: true, 5 | jest: true, 6 | }, 7 | rules: { 8 | 'import/no-commonjs': 'off', 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.github/actions/setup/action.yml: -------------------------------------------------------------------------------- 1 | name: Setup 2 | description: Setup Node.js and install dependencies 3 | 4 | runs: 5 | using: composite 6 | steps: 7 | - name: Setup Node.js 8 | uses: actions/setup-node@v3 9 | with: 10 | node-version-file: .nvmrc 11 | 12 | - name: Cache dependencies 13 | id: yarn-cache 14 | uses: actions/cache@v3 15 | with: 16 | path: | 17 | **/node_modules 18 | .yarn/install-state.gz 19 | key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}-${{ hashFiles('**/package.json', '!node_modules/**') }} 20 | restore-keys: | 21 | ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} 22 | ${{ runner.os }}-yarn- 23 | 24 | - name: Install dependencies 25 | if: steps.yarn-cache.outputs.cache-hit != 'true' 26 | run: yarn install --immutable 27 | shell: bash 28 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | branches: 8 | - main 9 | 10 | jobs: 11 | lint: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v3 16 | 17 | - name: Setup 18 | uses: ./.github/actions/setup 19 | 20 | - name: Lint files 21 | run: yarn lint 22 | 23 | - name: Typecheck files 24 | run: yarn typecheck 25 | 26 | test: 27 | runs-on: ubuntu-latest 28 | steps: 29 | - name: Checkout 30 | uses: actions/checkout@v3 31 | 32 | - name: Setup 33 | uses: ./.github/actions/setup 34 | 35 | - name: Run unit tests 36 | run: yarn test --maxWorkers=2 --coverage 37 | 38 | - name: Store test coverage 39 | uses: actions/upload-artifact@v4 40 | with: 41 | name: coverage 42 | path: coverage 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | 4 | /node_modules/ 5 | 6 | 7 | # Yarn 8 | .yarn/* 9 | !.yarn/patches 10 | !.yarn/plugins 11 | !.yarn/releases 12 | !.yarn/sdks 13 | !.yarn/versions 14 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v20 2 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "tabWidth": 2, 4 | "trailingComma": "es5", 5 | "useTabs": false 6 | } 7 | -------------------------------------------------------------------------------- /.release-it.json: -------------------------------------------------------------------------------- 1 | { 2 | "git": { 3 | "commitMessage": "chore: release ${version}", 4 | "tagName": "v${version}" 5 | }, 6 | "npm": { 7 | "publish": true 8 | }, 9 | "github": { 10 | "release": true 11 | }, 12 | "plugins": { 13 | "@release-it/conventional-changelog": { 14 | "preset": "angular" 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | 3 | yarnPath: .yarn/releases/yarn-4.3.1.cjs 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jest-file-snapshot 2 | 3 | [![Build Status][build-badge]][build] 4 | [![Code Coverage][coverage-badge]][coverage] 5 | [![MIT License][license-badge]][license] 6 | [![Version][version-badge]][package] 7 | 8 | Jest matcher to write snapshots to a separate file instead of the default snapshot file used by Jest. Writing a snapshot to a separate file means you have proper syntax highlighting in the output file, and better readability without those pesky escape characters. It's also useful if you have binary content. 9 | 10 | ## Installation 11 | 12 | ```sh 13 | npm install --save-dev jest-file-snapshot 14 | ``` 15 | 16 | or 17 | 18 | ```sh 19 | yarn add --dev jest-file-snapshot 20 | ``` 21 | 22 | ## Usage 23 | 24 | Extend Jest's `expect`: 25 | 26 | ```js 27 | import { toMatchFile } from 'jest-file-snapshot'; 28 | 29 | expect.extend({ toMatchFile }); 30 | ``` 31 | 32 | Then use it in your tests: 33 | 34 | ```js 35 | it('matches content of file on disk', () => { 36 | expect(content).toMatchFile(); 37 | }); 38 | ``` 39 | 40 | The content passed can be of type `string` or a `Buffer`. The comparison be done using `Buffer.equals()` instead of `===` if a `Buffer` is passed. 41 | 42 | The matcher takes two optional arguments: 43 | 44 | - `filepath`: path to the file whose content should be matched, e.g. `expect(content).toMatchFile(path.join(__dirname, 'output.md'))` 45 | - `options`: additional options object for the matcher, with following properties: 46 | - `diff`: options for [`jest-diff`](https://github.com/facebook/jest/tree/master/packages/jest-diff) 47 | - `fileExtension`: optional file extension to use for the snapshot file. 48 | 49 | You should also [exclude the output files from Jest's watcher](https://jestjs.io/docs/en/configuration#watchpathignorepatterns-arraystring) so that updating the snapshot doesn't re-run the tests again. 50 | 51 | For example, by default `toMatchFile` uses a folder named `__file_snapshots__` which you can exclude by adding the following under the `jest` key in `package.json`: 52 | 53 | ```json 54 | "watchPathIgnorePatterns": [ 55 | "__file_snapshots__" 56 | ] 57 | ``` 58 | 59 | ## Credits 60 | 61 | - [jest-image-snapshot](https://github.com/americanexpress/jest-image-snapshot) 62 | 63 | ## Contributing 64 | 65 | Make sure your code passes the unit tests, ESLint and TypeScript. Run the following to verify: 66 | 67 | ```sh 68 | yarn test 69 | yarn lint 70 | yarn typescript 71 | ``` 72 | 73 | To fix formatting errors, run the following: 74 | 75 | ```sh 76 | yarn lint -- --fix 77 | ``` 78 | 79 | 80 | 81 | [build-badge]: https://img.shields.io/circleci/project/github/satya164/jest-file-snapshot/main.svg?style=flat-square 82 | [build]: https://circleci.com/gh/satya164/jest-file-snapshot 83 | [coverage-badge]: https://img.shields.io/codecov/c/github/satya164/jest-file-snapshot.svg?style=flat-square 84 | [coverage]: https://codecov.io/github/satya164/jest-file-snapshot 85 | [license-badge]: https://img.shields.io/npm/l/jest-file-snapshot.svg?style=flat-square 86 | [license]: https://opensource.org/licenses/MIT 87 | [version-badge]: https://img.shields.io/npm/v/jest-file-snapshot.svg?style=flat-square 88 | [package]: https://www.npmjs.com/package/jest-file-snapshot 89 | -------------------------------------------------------------------------------- /__fixtures__/output.md: -------------------------------------------------------------------------------- 1 | # this is a test -------------------------------------------------------------------------------- /__tests__/__file_snapshots__/matches-binary-content-of-file-on-disk-0: -------------------------------------------------------------------------------- 1 | %PDF-1.1 2 | %¥±ë 3 | 4 | 1 0 obj 5 | << /Type /Catalog 6 | /Pages 2 0 R 7 | >> 8 | endobj 9 | 10 | 2 0 obj 11 | << /Type /Pages 12 | /Kids [3 0 R] 13 | /Count 1 14 | /MediaBox [0 0 300 144] 15 | >> 16 | endobj 17 | 18 | 3 0 obj 19 | << /Type /Page 20 | /Parent 2 0 R 21 | /Resources 22 | << /Font 23 | << /F1 24 | << /Type /Font 25 | /Subtype /Type1 26 | /BaseFont /Times-Roman 27 | >> 28 | >> 29 | >> 30 | /Contents 4 0 R 31 | >> 32 | endobj 33 | 34 | 4 0 obj 35 | << /Length 55 >> 36 | stream 37 | BT 38 | /F1 18 Tf 39 | 0 0 Td 40 | (Hello World) Tj 41 | ET 42 | endstream 43 | endobj 44 | 45 | xref 46 | 0 5 47 | 0000000000 65535 f 48 | 0000000018 00000 n 49 | 0000000077 00000 n 50 | 0000000178 00000 n 51 | 0000000457 00000 n 52 | trailer 53 | << /Root 1 0 R 54 | /Size 5 55 | >> 56 | startxref 57 | 565 58 | %%EOF 59 | -------------------------------------------------------------------------------- /__tests__/__file_snapshots__/matches-content-of-file-on-disk-with-file-extension-0.md: -------------------------------------------------------------------------------- 1 | # this is a another test -------------------------------------------------------------------------------- /__tests__/__file_snapshots__/matches-content-of-file-on-disk-without-filename-0: -------------------------------------------------------------------------------- 1 | # this is a another test -------------------------------------------------------------------------------- /__tests__/__file_snapshots__/works-with-.not-0: -------------------------------------------------------------------------------- 1 | # this is a ugly test 2 | -------------------------------------------------------------------------------- /__tests__/__file_snapshots__/works-with-.not-for-binary-files-0: -------------------------------------------------------------------------------- 1 | %PDF-1.1 2 | %¥±ë 3 | 4 | % MIT License 5 | % 6 | % Copyright (c) 2010 Brendan Zagaeski 7 | % 8 | % Permission is hereby granted, free of charge, to any person obtaining a copy 9 | % of this software and associated documentation files (the "Software"), to deal 10 | % in the Software without restriction, including without limitation the rights 11 | % to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | % copies of the Software, and to permit persons to whom the Software is 13 | % furnished to do so, subject to the following conditions: 14 | % 15 | % The above copyright notice and this permission notice shall be included in all 16 | % copies or substantial portions of the Software. 17 | % 18 | % THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | % IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | % FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | % AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | % LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | % OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | % SOFTWARE. 25 | 26 | 1 0 obj 27 | << /Type /Catalog 28 | /Pages 2 0 R 29 | >> 30 | endobj 31 | 32 | 2 0 obj 33 | << /Type /Pages 34 | /Kids [3 0 R] 35 | /Count 1 36 | /MediaBox [0 0 300 144] 37 | >> 38 | endobj 39 | 40 | 3 0 obj 41 | << /Type /Page 42 | /Parent 2 0 R 43 | /Resources 44 | << /Font 45 | << /F1 46 | << /Type /Font 47 | /Subtype /Type1 48 | /BaseFont /Times-Roman 49 | >> 50 | >> 51 | >> 52 | /Contents 4 0 R 53 | >> 54 | endobj 55 | 56 | 4 0 obj 57 | << /Length 55 >> 58 | stream 59 | BT 60 | /F1 18 Tf 61 | 0 0 Td 62 | (Hello World) Tj 63 | ET 64 | endstream 65 | endobj 66 | 67 | xref 68 | 0 5 69 | 0000000000 65535 f 70 | 0000001130 00000 n 71 | 0000001189 00000 n 72 | 0000001290 00000 n 73 | 0000001569 00000 n 74 | trailer 75 | << /Root 1 0 R 76 | /Size 5 77 | >> 78 | startxref 79 | 1677 80 | %%EOF 81 | -------------------------------------------------------------------------------- /__tests__/__file_snapshots__/works-with-non-binary-buffer-content-0: -------------------------------------------------------------------------------- 1 | # this is a buffer test -------------------------------------------------------------------------------- /__tests__/index.test.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | const { toMatchFile } = require('../index'); 4 | 5 | expect.extend({ toMatchFile }); 6 | 7 | it('matches content of file on disk with specified filename', () => { 8 | expect(`# this is a test`).toMatchFile( 9 | path.join(__dirname, '..', '__fixtures__', 'output.md') 10 | ); 11 | }); 12 | 13 | it('matches content of file on disk without filename', () => { 14 | expect(`# this is a another test`).toMatchFile(); 15 | }); 16 | 17 | it('matches content of file on disk with file extension', () => { 18 | expect(`# this is a another test`).toMatchFile(undefined, { 19 | fileExtension: '.md', 20 | }); 21 | }); 22 | 23 | it('matches binary content of file on disk', () => { 24 | expect( 25 | fs.readFileSync(path.join(__dirname, 'minimal.pdf'), 'binary') 26 | ).toMatchFile(); 27 | }); 28 | 29 | it('works with non-binary buffer content', () => { 30 | expect(Buffer.from('# this is a buffer test')).toMatchFile(); 31 | }); 32 | 33 | it('works with .not', () => { 34 | expect(`# this is a nice test`).not.toMatchFile(); 35 | }); 36 | 37 | it('works with .not for binary files', () => { 38 | expect( 39 | fs.readFileSync(path.join(__dirname, 'minimal.pdf'), 'binary') 40 | ).not.toMatchFile(); 41 | }); 42 | -------------------------------------------------------------------------------- /__tests__/minimal.pdf: -------------------------------------------------------------------------------- 1 | %PDF-1.1 2 | %¥±ë 3 | 4 | 1 0 obj 5 | << /Type /Catalog 6 | /Pages 2 0 R 7 | >> 8 | endobj 9 | 10 | 2 0 obj 11 | << /Type /Pages 12 | /Kids [3 0 R] 13 | /Count 1 14 | /MediaBox [0 0 300 144] 15 | >> 16 | endobj 17 | 18 | 3 0 obj 19 | << /Type /Page 20 | /Parent 2 0 R 21 | /Resources 22 | << /Font 23 | << /F1 24 | << /Type /Font 25 | /Subtype /Type1 26 | /BaseFont /Times-Roman 27 | >> 28 | >> 29 | >> 30 | /Contents 4 0 R 31 | >> 32 | endobj 33 | 34 | 4 0 obj 35 | << /Length 55 >> 36 | stream 37 | BT 38 | /F1 18 Tf 39 | 0 0 Td 40 | (Hello World) Tj 41 | ET 42 | endstream 43 | endobj 44 | 45 | xref 46 | 0 5 47 | 0000000000 65535 f 48 | 0000000018 00000 n 49 | 0000000077 00000 n 50 | 0000000178 00000 n 51 | 0000000457 00000 n 52 | trailer 53 | << /Root 1 0 R 54 | /Size 5 55 | >> 56 | startxref 57 | 565 58 | %%EOF 59 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'], 3 | }; 4 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import { DiffOptions } from 'jest-diff'; 4 | 5 | export const toMatchFile: ( 6 | content: string | Buffer, 7 | filename?: string, 8 | options?: FileMatcherOptions 9 | ) => jest.CustomMatcherResult; 10 | 11 | declare interface FileMatcherOptions { 12 | diff?: DiffOptions; 13 | fileExtension?: string; 14 | } 15 | 16 | declare global { 17 | namespace jest { 18 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 19 | interface Matchers { 20 | toMatchFile: (filename?: string, options?: FileMatcherOptions) => void; 21 | } 22 | 23 | interface Expect { 24 | toMatchFile: (filename?: string, options?: FileMatcherOptions) => void; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /* istanbul ignore file */ 2 | 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const chalk = require('chalk'); 6 | const { diff } = require('jest-diff'); 7 | const mkdirp = require('mkdirp'); 8 | const filenamify = require('filenamify'); 9 | 10 | /** 11 | * Check if 2 strings or buffer are equal 12 | * @param {string | Buffer} a 13 | * @param {string | Buffer} b 14 | */ 15 | const isEqual = (a, b) => { 16 | // @ts-ignore: TypeScript gives error if we pass string to buffer.equals 17 | return Buffer.isBuffer(a) ? a.equals(b) : a === b; 18 | }; 19 | 20 | /** 21 | * Match given content against content of the specified file. 22 | * 23 | * @param {string | Buffer} content Output content to match 24 | * @param {string} [filepath] Path to the file to match against 25 | * @param {{ 26 | * diff?: import('jest-diff').DiffOptions, 27 | * diffMethod?: (a: string, b: string, options: import('jest-diff').DiffOptions) => string, 28 | * fileExtension?: string, 29 | * }} options 30 | * @this {{ testPath: string, currentTestName: string, assertionCalls: number, isNot: boolean, snapshotState: { added: number, updated: number, unmatched: number, _updateSnapshot: 'none' | 'new' | 'all' } }} 31 | */ 32 | exports.toMatchFile = function toMatchFile(content, filepath, options = {}) { 33 | const { isNot, snapshotState } = this; 34 | 35 | const fileExtension = options.fileExtension || ''; 36 | 37 | const filename = 38 | filepath === undefined 39 | ? // If file name is not specified, generate one from the test title 40 | path.join( 41 | path.dirname(this.testPath), 42 | '__file_snapshots__', 43 | `${filenamify( 44 | this.currentTestName, 45 | { 46 | replacement: '-', 47 | }, 48 | { maxLength: Infinity } 49 | ).replace(/\s/g, '-')}-${this.assertionCalls}` 50 | ) + fileExtension 51 | : filepath; 52 | 53 | options = { 54 | // Options for jest-diff 55 | diff: Object.assign( 56 | { 57 | expand: false, 58 | contextLines: 5, 59 | aAnnotation: 'Snapshot', 60 | }, 61 | options.diff 62 | ), 63 | }; 64 | 65 | if (snapshotState._updateSnapshot === 'none' && !fs.existsSync(filename)) { 66 | // We're probably running in CI environment 67 | 68 | snapshotState.unmatched++; 69 | 70 | return { 71 | pass: isNot, 72 | message: () => 73 | `New output file ${chalk.blue( 74 | path.basename(filename) 75 | )} was ${chalk.bold.red('not written')}.\n\n` + 76 | 'The update flag must be explicitly passed to write a new snapshot.\n\n' + 77 | `This is likely because this test is run in a ${chalk.blue( 78 | 'continuous integration (CI) environment' 79 | )} in which snapshots are not written by default.\n\n`, 80 | }; 81 | } 82 | 83 | if (fs.existsSync(filename)) { 84 | const output = fs.readFileSync( 85 | filename, 86 | Buffer.isBuffer(content) ? null : 'utf8' 87 | ); 88 | 89 | if (isNot) { 90 | // The matcher is being used with `.not` 91 | 92 | if (!isEqual(content, output)) { 93 | // The value of `pass` is reversed when used with `.not` 94 | return { pass: false, message: () => '' }; 95 | } else { 96 | snapshotState.unmatched++; 97 | 98 | return { 99 | pass: true, 100 | message: () => 101 | `Expected received content ${chalk.red( 102 | 'to not match' 103 | )} the file ${chalk.blue(path.basename(filename))}.`, 104 | }; 105 | } 106 | } else { 107 | if (isEqual(content, output)) { 108 | return { pass: true, message: () => '' }; 109 | } else { 110 | if (snapshotState._updateSnapshot === 'all') { 111 | mkdirp.sync(path.dirname(filename)); 112 | fs.writeFileSync(filename, content); 113 | 114 | snapshotState.updated++; 115 | 116 | return { pass: true, message: () => '' }; 117 | } else { 118 | snapshotState.unmatched++; 119 | 120 | const diffMethod = options.diffMethod || diff; 121 | const difference = 122 | Buffer.isBuffer(content) || Buffer.isBuffer(output) 123 | ? '' 124 | : `\n\n${diffMethod(output, content, options.diff)}`; 125 | 126 | return { 127 | pass: false, 128 | message: () => 129 | `Received content ${chalk.red( 130 | "doesn't match" 131 | )} the file ${chalk.blue(path.basename(filename))}.${difference}`, 132 | }; 133 | } 134 | } 135 | } 136 | } else { 137 | if ( 138 | !isNot && 139 | (snapshotState._updateSnapshot === 'new' || 140 | snapshotState._updateSnapshot === 'all') 141 | ) { 142 | mkdirp.sync(path.dirname(filename)); 143 | fs.writeFileSync(filename, content); 144 | 145 | snapshotState.added++; 146 | 147 | return { pass: true, message: () => '' }; 148 | } else { 149 | snapshotState.unmatched++; 150 | 151 | return { 152 | pass: true, 153 | message: () => 154 | `The output file ${chalk.blue( 155 | path.basename(filename) 156 | )} ${chalk.bold.red("doesn't exist")}.`, 157 | }; 158 | } 159 | } 160 | }; 161 | -------------------------------------------------------------------------------- /lefthook.yml: -------------------------------------------------------------------------------- 1 | pre-commit: 2 | parallel: true 3 | commands: 4 | lint: 5 | glob: "*.{js,ts,tsx}" 6 | run: yarn lint {staged_files} 7 | types: 8 | glob: "*.{json,js,ts,tsx}" 9 | run: yarn tsc --noEmit 10 | test: 11 | glob: "*.{json,js,ts,tsx}" 12 | run: yarn test 13 | commit-msg: 14 | parallel: true 15 | commands: 16 | commitlint: 17 | run: yarn commitlint --edit 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jest-file-snapshot", 3 | "version": "0.7.0", 4 | "description": "Jest matcher to write snapshots to a separate file instead of the default snapshot file used by Jest", 5 | "keywords": [ 6 | "test", 7 | "jest", 8 | "snapshot" 9 | ], 10 | "main": "index.js", 11 | "files": [ 12 | "index.js", 13 | "index.d.ts" 14 | ], 15 | "types": "index.d.ts", 16 | "license": "MIT", 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/satya164/jest-file-snapshot.git" 20 | }, 21 | "author": "Satyajit Sahoo (https://github.com/satya164/)", 22 | "scripts": { 23 | "test": "jest", 24 | "lint": "eslint .", 25 | "typecheck": "tsc --noEmit", 26 | "release": "release-it" 27 | }, 28 | "publishConfig": { 29 | "registry": "https://registry.npmjs.org/" 30 | }, 31 | "devDependencies": { 32 | "@babel/core": "^7.24.7", 33 | "@commitlint/cli": "^19.3.0", 34 | "@commitlint/config-conventional": "^19.2.2", 35 | "@release-it/conventional-changelog": "^8.0.1", 36 | "@types/jest": "^29.5.12", 37 | "@types/jest-diff": "^24.3.0", 38 | "@types/mkdirp": "^2.0.0", 39 | "conventional-changelog-cli": "^5.0.0", 40 | "eslint": "^8.56.0", 41 | "eslint-config-satya164": "^3.2.1", 42 | "jest": "^29.7.0", 43 | "lefthook": "^1.7.0", 44 | "prettier": "^3.3.2", 45 | "release-it": "^17.4.1", 46 | "typescript": "^5.5.3" 47 | }, 48 | "dependencies": { 49 | "chalk": "^4.1.2", 50 | "filenamify": "^4.3.0", 51 | "jest-diff": "^29.7.0", 52 | "mkdirp": "^3.0.1" 53 | }, 54 | "jest": { 55 | "testEnvironment": "node", 56 | "testMatch": [ 57 | "**/__tests__/**/*.test.js" 58 | ], 59 | "watchPathIgnorePatterns": [ 60 | "(__fixtures__|__file_snapshots__)" 61 | ] 62 | }, 63 | "packageManager": "yarn@4.3.1" 64 | } 65 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowUnreachableCode": false, 4 | "allowUnusedLabels": false, 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "lib": ["esnext", "dom"], 8 | "module": "esnext", 9 | "moduleResolution": "node", 10 | "noFallthroughCasesInSwitch": true, 11 | "noImplicitReturns": true, 12 | "noImplicitUseStrict": false, 13 | "noStrictGenericChecks": false, 14 | "noUnusedLocals": true, 15 | "noUnusedParameters": true, 16 | "resolveJsonModule": true, 17 | "skipLibCheck": true, 18 | "strict": true, 19 | "target": "esnext", 20 | "verbatimModuleSyntax": true 21 | } 22 | } 23 | --------------------------------------------------------------------------------