├── .editorconfig ├── .github └── workflows │ ├── codeql.yml │ ├── format.yml │ └── test.yml ├── .gitignore ├── .prettierignore ├── README.md ├── bin └── get-folder-size.js ├── eslint.config.js ├── example.js ├── index.d.ts ├── index.js ├── package-lock.json ├── package.json ├── test ├── cli.js ├── fixture │ ├── 500bytes.txt │ ├── 6000bytes.txt │ └── 8bytes.txt ├── logic.js ├── native.js └── stress.js └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | end_of_line = lf 3 | charset = utf-8 4 | indent_style = space 5 | indent_size = 2 6 | insert_final_newline = true 7 | 8 | [*.{ts,js}] 9 | indent_style = tab 10 | tab_width = 4 11 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: CodeQL 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | branches: [master] 8 | schedule: 9 | - cron: "7 4 19 * *" 10 | 11 | permissions: 12 | actions: read 13 | contents: read 14 | security-events: write 15 | 16 | jobs: 17 | codeql: 18 | strategy: 19 | fail-fast: false 20 | matrix: 21 | language: [javascript] 22 | 23 | runs-on: ubuntu-latest 24 | 25 | steps: 26 | - name: Checkout code 27 | uses: actions/checkout@v3 28 | 29 | - name: Initialize CodeQL 30 | uses: github/codeql-action/init@v2 31 | with: 32 | languages: ${{ matrix.language }} 33 | queries: +security-and-quality 34 | 35 | - name: Autobuild 36 | uses: github/codeql-action/autobuild@v2 37 | 38 | - name: Perform CodeQL Analysis 39 | uses: github/codeql-action/analyze@v2 40 | with: 41 | category: "/language:${{ matrix.language }}" 42 | -------------------------------------------------------------------------------- /.github/workflows/format.yml: -------------------------------------------------------------------------------- 1 | name: Format 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | branches: [master] 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | format: 14 | strategy: 15 | fail-fast: false 16 | 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - name: Checkout code 21 | uses: actions/checkout@v3 22 | 23 | - name: Set up Node lts/* 24 | uses: actions/setup-node@v3 25 | with: 26 | node-version: lts/* 27 | cache: npm 28 | 29 | - name: Install dependencies 30 | run: npm install-clean 31 | 32 | - name: Check formatting 33 | run: npm run format:nofix 34 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | branches: [master] 8 | schedule: 9 | - cron: "7 4 19 * *" 10 | 11 | permissions: 12 | contents: read 13 | 14 | jobs: 15 | test: 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | # These version names ensure that new Node versions are automatically tested, 20 | # but also ensures that the oldest supported version is changed on purpose. 21 | node-version: [lts/*] 22 | os: [ubuntu-latest, windows-latest, macOS-latest] 23 | include: 24 | - node-version: latest 25 | os: ubuntu-latest 26 | - node-version: lts/-1 27 | os: ubuntu-latest 28 | - node-version: 18.11.0 29 | os: ubuntu-latest 30 | 31 | runs-on: ${{ matrix.os }} 32 | 33 | steps: 34 | - name: Checkout code 35 | uses: actions/checkout@v3 36 | 37 | - name: Set up Node ${{ matrix.node-version }} 38 | uses: actions/setup-node@v3 39 | with: 40 | node-version: ${{ matrix.node-version }} 41 | cache: npm 42 | 43 | - name: Install dependencies 44 | run: npm install-clean 45 | 46 | - name: Test code 47 | run: npm test 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .nyc_output 3 | .tap 4 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # get-folder-size 2 | 3 | Get the size of a folder by iterating through its sub-files and -folders. 4 | 5 | ## Basic usage 6 | 7 | If you don't care about the details and just want a quick implementation, you can use: 8 | 9 | ```js 10 | getFolderSize.loose("/path/to/folder"); 11 | ``` 12 | 13 | Example: 14 | 15 | ```js 16 | import getFolderSize from "get-folder-size"; 17 | 18 | const myFolder = "/path/to/my/folder"; 19 | 20 | const size = await getFolderSize.loose(myFolder); 21 | console.log(`The folder is ${size} bytes large`); 22 | console.log(`That is the same as ${(size / 1000 / 1000).toFixed(2)} MB`); 23 | ``` 24 | 25 | ## Methods 26 | 27 | When reading the size of a folder, read errors can randomly occur for a number of reasons, especially if a different process is altering files in the same folder at the same time. There are three different ways to call this package, depending on how you want to handle those errors: 28 | 29 | ### `getFolderSize(path, [options]): object` 30 | 31 | The default method will return an object with the size of the folder and a list of encountered errors: 32 | 33 | ```js 34 | { 35 | size: 1435, 36 | errors: [ 37 | Error{} ... 38 | ] 39 | } 40 | ``` 41 | 42 | If no errors were encountered, `errors` will be `null`. If errors were encountered, `size` will likely be smaller than the real folder size. 43 | 44 | This method is great if you want to implement custom logic based on the errors that were encountered. 45 | 46 | ### `getFolderSize.loose(path, [options]): number | bigint` 47 | 48 | The `loose` method will return the folder size directly and ignore any errors it encounters, which means the returned folder size could be smaller than the real folder size. 49 | 50 | This method is great if the precise size isn't too important, for example when used only to display the folder size to the user. 51 | 52 | ### `getFolderSize.strict(path, [options]): number | bigint` 53 | 54 | The `strict` method will return the folder size directly, but throw an error if it encounters any read errors. 55 | 56 | This method is great if you need a very accurate number. You will have to implement some sort of error handling to use it reliably. 57 | 58 | ## Options 59 | 60 | Any of the three methods can also take an `options` object: 61 | 62 | ```js 63 | getFolderSize("/path/to/folder", { 64 | bigint: true, 65 | ignore: /pattern/, 66 | fs: customFS, 67 | }); 68 | ``` 69 | 70 | If the `bigint` option is set to true, the folder size is returned as a BigInt instead of the default Number. 71 | 72 | The `ignore` option takes a regex pattern. Any file or folder with a path that matches the pattern will not be counted in the total folder size. 73 | 74 | The `fs` option allows you to pass a different filesystem handler, such as [memfs](https://github.com/streamich/memfs), that will be used to read the folder size. The filesystem handler must incorporate `lstat` and `readdir` promise functions. 75 | 76 | ## CLI tool 77 | 78 | You can run this module from your command line: 79 | 80 | ```bash 81 | get-folder-size --folder "/my/folder" --ignore "node_modules" 82 | ``` 83 | 84 | The optional `ignore` statement takes a regex pattern. 85 | 86 | ## FAQ 87 | 88 | ### I don't care if I have a file or folder, I just want to get the size. 89 | 90 | If a file is passed to `get-folder-size`, it will simply return the size of the file. This means you can use it as a catch-all to get the size of any element in the filesystem. 91 | 92 | Example: 93 | 94 | ```js 95 | import getItemSize from "get-folder-size"; 96 | 97 | for (const path of [ 98 | "/path/to/small/file.txt", 99 | "/path/to/small/folder/", 100 | "/path/to/large/file.js", 101 | "/path/to/large/folder/", 102 | ]) { 103 | console.log(await getItemSize.strict(path)); 104 | } 105 | 106 | // Console: 107 | // 273 108 | // 402 109 | // 348614 110 | // 674362319 111 | ``` 112 | 113 | ### Does it return actual size or size on disk? 114 | 115 | This module calculates the actual folder size, and not the size on disk. [Read about the difference here.](https://web.archive.org/web/20140712235443/https://stackoverflow.com/questions/15470787/please-help-me-understand-size-vs-size-on-disk) 116 | 117 | ### How do I import it from a CommonJS module? 118 | 119 | CommonJS modules do not support the `import..from` method, but they do support this method: 120 | 121 | ```js 122 | const getFolderSize = (await import("get-folder-size")).default; 123 | ``` 124 | 125 | Note that this import only works inside an async function. 126 | 127 | If you want to use the `require` method, consider just staying on v2. You can make v2 return a promise by importing it this way: 128 | 129 | ```js 130 | const util = require("util"); 131 | const getFolderSize = util.promisify(require("get-folder-size")); 132 | ``` 133 | 134 | If none of these methods work for you, [send us a detailed explanation of your issue](https://github.com/alessioalex/get-folder-size/issues), and we will take a look at it. 135 | 136 | ### How do I use it? 137 | 138 | This is a Node module. If you are not sure what that means, please check out one of the many great tutorials online, like [nodejs.dev](https://nodejs.dev/learn/introduction-to-nodejs). 139 | 140 | When you have Node set up, you can install `get-folder-size` from your command line with this command: 141 | 142 | ```bash 143 | npm install get-folder-size 144 | ``` 145 | 146 | You can now import it into your JavaScript files, or you can use its command line interface (CLI). 147 | 148 | ## License 149 | 150 | MIT 151 | -------------------------------------------------------------------------------- /bin/get-folder-size.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import getFolderSize from "../index.js"; 4 | import { parseArgs } from "node:util"; 5 | import { resolve } from "node:path"; 6 | 7 | const args = parseArgs({ 8 | args: process.argv.slice(2), 9 | options: { 10 | folder: { 11 | short: "f", 12 | type: "string", 13 | }, 14 | ignore: { 15 | short: "i", 16 | type: "string", 17 | }, 18 | }, 19 | allowPositionals: true, 20 | }); 21 | 22 | // --folder or -f or last argument passed 23 | const folder = args.values.folder || args.positionals.at(-1); 24 | 25 | if (!folder) { 26 | console.error("missing folder argument"); 27 | console.error("\n Usage:\n"); 28 | console.error(`get-folder-size --folder "/home/alex/www"`); 29 | process.exit(1); 30 | } 31 | 32 | const ignore = args.values.ignore ? new RegExp(args.values.ignore) : undefined; 33 | 34 | const size = await getFolderSize.strict(resolve(folder), { ignore }); 35 | console.log((size / 1000 / 1000).toFixed(2) + " MB"); 36 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from "@eslint/js"; 2 | import tseslint from "typescript-eslint"; 3 | import globals from "globals"; 4 | 5 | export default [ 6 | js.configs.recommended, 7 | ...tseslint.configs.strictTypeChecked, 8 | ...tseslint.configs.stylisticTypeChecked, 9 | { 10 | languageOptions: { 11 | parserOptions: { 12 | project: true, 13 | tsconfigRootDir: import.meta.dirname, 14 | }, 15 | }, 16 | }, 17 | { 18 | files: ["**/*.js"], 19 | ...tseslint.configs.disableTypeChecked, 20 | }, 21 | { 22 | languageOptions: { 23 | globals: { 24 | ...globals.node, 25 | }, 26 | }, 27 | }, 28 | ]; 29 | -------------------------------------------------------------------------------- /example.js: -------------------------------------------------------------------------------- 1 | import path from "node:path"; 2 | import getFolderSize from "./index.js"; 3 | 4 | if (!process.env.FOLDER) { 5 | throw new Error("FOLDER env var needed"); 6 | } 7 | 8 | getFolderSize.strict(path.resolve(process.env.FOLDER)).then((size) => { 9 | console.log(size + " bytes"); 10 | console.log((size / 1000 / 1000).toFixed(2) + " MB"); 11 | }); 12 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The stats object returned by the underlying file system's lstat function. 3 | */ 4 | export interface Stats { 5 | isDirectory(): boolean; 6 | ino: bigint; 7 | size: bigint; 8 | } 9 | 10 | /** 11 | * The underlying filesystem implementation that will be used. 12 | * See the node fs documentation for more details: 13 | * https://nodejs.org/api/fs.html 14 | */ 15 | export interface Fs { 16 | lstat( 17 | path: string, 18 | options?: { 19 | bigint?: true; 20 | }, 21 | ): Promise; 22 | readdir(path: string): Promise; 23 | } 24 | 25 | /** 26 | * Configuration options. 27 | */ 28 | export interface Options { 29 | /** 30 | * Should the folder size be returned as a BigInt instead of a Number. 31 | */ 32 | bigint?: boolean; 33 | /** 34 | * If a file's path matches this regex object, its size is not counted. 35 | */ 36 | ignore?: RegExp; 37 | /** 38 | * The filesystem that should be used. Uses node fs by default. 39 | */ 40 | fs?: Fs; 41 | } 42 | 43 | /** 44 | * The result object returned by the default getFolderSize function. 45 | */ 46 | export interface Result { 47 | /** 48 | * The size of the folder in bytes. 49 | */ 50 | size: T; 51 | /** 52 | * A list of errors encountered while traversing the folder. 53 | */ 54 | errors: Error[] | null; 55 | } 56 | 57 | /** 58 | * Returns an object containing the size of the folder and a list of errors encountered while traversing the folder. 59 | * 60 | * If any errors are returned, the returned folder size is likely smaller than the real folder size. 61 | * 62 | * @param itemPath - Path of the folder. 63 | * @param options - Configuration options. 64 | * 65 | * @returns An object containing the size of the folder in bytes and a list of encountered errors. 66 | */ 67 | declare function getFolderSize( 68 | itemPath: string, 69 | options?: Options & { 70 | bigint?: false | undefined; 71 | }, 72 | ): Promise>; 73 | declare function getFolderSize( 74 | itemPath: string, 75 | options: Options & { 76 | bigint: true; 77 | }, 78 | ): Promise>; 79 | 80 | declare namespace getFolderSize { 81 | /** 82 | * Returns the size of the folder. If any errors are encountered while traversing the folder, they are silently ignored. 83 | * 84 | * The returned folder size might be smaller than the real folder size. It is impossible to know for sure, since errors are ignored. 85 | * 86 | * @param itemPath - Path of the folder. 87 | * @param options - Configuration options. 88 | * 89 | * @returns The size of the folder in bytes. 90 | */ 91 | function loose( 92 | itemPath: string, 93 | options?: Options & { 94 | bigint?: false | undefined; 95 | }, 96 | ): Promise; 97 | function loose( 98 | itemPath: string, 99 | options: Options & { 100 | bigint: true; 101 | }, 102 | ): Promise; 103 | 104 | /** 105 | * Returns the size of the folder. If any errors are encountered while traversing the folder, this method will throw an error. 106 | * 107 | * Because errors will otherwise make this method fail, the returned folder size will always be accurate. 108 | * 109 | * @param itemPath - Path of the folder. 110 | * @param options - Configuration options. 111 | * 112 | * @returns The size of the folder in bytes. 113 | */ 114 | function strict( 115 | itemPath: string, 116 | options?: Options & { 117 | bigint?: false | undefined; 118 | }, 119 | ): Promise; 120 | function strict( 121 | itemPath: string, 122 | options: Options & { 123 | bigint: true; 124 | }, 125 | ): Promise; 126 | } 127 | 128 | export default getFolderSize; 129 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import { join } from "node:path"; 2 | 3 | export default async function getFolderSize(itemPath, options) { 4 | return await core(itemPath, options, { errors: true }); 5 | } 6 | 7 | getFolderSize.loose = async (itemPath, options) => 8 | await core(itemPath, options); 9 | 10 | getFolderSize.strict = async (itemPath, options) => 11 | await core(itemPath, options, { strict: true }); 12 | 13 | async function core(rootItemPath, options = {}, returnType = {}) { 14 | const fs = options.fs || (await import("node:fs/promises")); 15 | 16 | let folderSize = 0n; 17 | const foundInos = new Set(); 18 | const errors = []; 19 | 20 | await processItem(rootItemPath); 21 | 22 | async function processItem(itemPath) { 23 | if (options.ignore?.test(itemPath)) return; 24 | 25 | const stats = returnType.strict 26 | ? await fs.lstat(itemPath, { bigint: true }) 27 | : await fs 28 | .lstat(itemPath, { bigint: true }) 29 | .catch((error) => errors.push(error)); 30 | if (typeof stats !== "object") return; 31 | if (!foundInos.has(stats.ino)) { 32 | foundInos.add(stats.ino); 33 | folderSize += stats.size; 34 | } 35 | 36 | if (stats.isDirectory()) { 37 | const directoryItems = returnType.strict 38 | ? await fs.readdir(itemPath) 39 | : await fs 40 | .readdir(itemPath) 41 | .catch((error) => errors.push(error)); 42 | if (typeof directoryItems !== "object") return; 43 | await Promise.all( 44 | directoryItems.map((directoryItem) => 45 | processItem(join(itemPath, directoryItem)), 46 | ), 47 | ); 48 | } 49 | } 50 | 51 | if (!options.bigint) { 52 | if (folderSize > BigInt(Number.MAX_SAFE_INTEGER)) { 53 | const error = new RangeError( 54 | "The folder size is too large to return as a Number. You can instruct this package to return a BigInt instead.", 55 | ); 56 | if (returnType.strict) { 57 | throw error; 58 | } 59 | errors.push(error); 60 | folderSize = Number.MAX_SAFE_INTEGER; 61 | } else { 62 | folderSize = Number(folderSize); 63 | } 64 | } 65 | 66 | if (returnType.errors) { 67 | return { 68 | size: folderSize, 69 | errors: errors.length > 0 ? errors : null, 70 | }; 71 | } else { 72 | return folderSize; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "get-folder-size", 3 | "version": "5.0.0", 4 | "description": "Get the size of a folder by iterating through its sub-files and -folders.", 5 | "type": "module", 6 | "exports": { 7 | ".": { 8 | "types": "./index.d.ts", 9 | "default": "./index.js" 10 | } 11 | }, 12 | "bin": { 13 | "get-folder-size": "./bin/get-folder-size.js" 14 | }, 15 | "files": [ 16 | "index.js", 17 | "index.d.ts", 18 | "bin/get-folder-size.js" 19 | ], 20 | "engines": { 21 | "node": ">=18.11.0" 22 | }, 23 | "devDependencies": { 24 | "@eslint/js": "^9.14.0", 25 | "@types/eslint__js": "^8.42.3", 26 | "eslint": "^9.14.0", 27 | "globals": "^15.12.0", 28 | "memfs": "^4.14.0", 29 | "prettier": "^3.3.3", 30 | "tap": "^21.0.1", 31 | "typescript": "^5.6.3", 32 | "typescript-eslint": "^8.14.0" 33 | }, 34 | "scripts": { 35 | "tap": "tap", 36 | "lint": "eslint \"**/*.{ts,js}\" --fix", 37 | "lint:nofix": "eslint \"**/*.{ts,js}\"", 38 | "format": "prettier --write .", 39 | "format:nofix": "prettier --check .", 40 | "test": "npm run lint:nofix && npm run tap" 41 | }, 42 | "keywords": [ 43 | "folder", 44 | "directory", 45 | "size" 46 | ], 47 | "repository": { 48 | "type": "git", 49 | "url": "https://github.com/alessioalex/get-folder-size.git" 50 | }, 51 | "author": "Alexandru Vladutu ", 52 | "license": "MIT" 53 | } 54 | -------------------------------------------------------------------------------- /test/cli.js: -------------------------------------------------------------------------------- 1 | import { exec as execCallback } from "node:child_process"; 2 | import { join as joinPaths, dirname as pathDirname } from "node:path"; 3 | import { fileURLToPath } from "node:url"; 4 | import { promisify } from "node:util"; 5 | import tap from "tap"; 6 | 7 | const exec = promisify(execCallback); 8 | 9 | /** 10 | * @file 11 | * This test checks that basic CLI functionality works. 12 | * Most of the args parsing is handled by a node module, so we don't 13 | * need to test a million edge cases, they should be handled correctly. 14 | */ 15 | 16 | /** 17 | * TODO: replace with `import.meta.dirname` when it becomes stable: 18 | * https://nodejs.org/api/esm.html#importmeta 19 | */ 20 | const dirname = pathDirname(fileURLToPath(import.meta.url)); 21 | 22 | /** 23 | * Skip the test on Windows. It has some weird args parsing that we don't want to deal with. 24 | * If the tests pass on all other platforms, we can expect it to work correctly on Windows as well. 25 | */ 26 | const skip = process.platform === "win32"; 27 | 28 | const cwd = joinPaths(dirname, ".."); 29 | const sizeOfFixtureFolder = "0.01 MB"; 30 | 31 | if (!skip) { 32 | for (const folderArg of ["--folder ", "--folder=", "-f ", ""]) { 33 | const args = `${folderArg}"test/fixture"`; 34 | 35 | tap.test(`get folder size with args: ${args}`, async () => { 36 | const result = await exec(`bin/get-folder-size.js ${args}`, { 37 | cwd, 38 | }); 39 | 40 | tap.ok( 41 | result.stdout.startsWith(sizeOfFixtureFolder), 42 | "should return the size of the folder", 43 | ); 44 | }); 45 | 46 | for (const ignoreArg of ["--ignore ", "--ignore=", "-i "]) { 47 | for (const flipArgs of [false, true]) { 48 | const arg1 = `${folderArg}"test/fixture"`; 49 | const arg2 = `${ignoreArg}".*txt"`; 50 | const args = flipArgs ? `${arg2} ${arg1}` : `${arg1} ${arg2}`; 51 | 52 | tap.test(`get folder size with args: ${args}`, async () => { 53 | const result = await exec( 54 | `bin/get-folder-size.js ${args}`, 55 | { 56 | cwd, 57 | }, 58 | ); 59 | 60 | tap.ok( 61 | result.stdout.startsWith("0.00 MB"), 62 | "should return zero as size", 63 | ); 64 | }); 65 | } 66 | } 67 | } 68 | 69 | tap.test("get folder size with missing args", async () => { 70 | tap.rejects(async () => { 71 | await exec("bin/get-folder-size.js", { cwd }); 72 | }, "should reject since no folder path is provided"); 73 | }); 74 | } 75 | -------------------------------------------------------------------------------- /test/fixture/500bytes.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | ####### ### ### 4 | # # # # # ##### # # ##### ###### #### 5 | # # # # # # # # # # # # 6 | ###### # # # # ##### # # ##### #### 7 | # # # # # # # # # # # 8 | # # # # # # # # # # # # # 9 | ##### ### ### ##### # # ###### #### 10 | 11 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -------------------------------------------------------------------------------- /test/fixture/6000bytes.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | ..,:cloodddddddddddddddl' .;lodxxxxxxxxxxxxxxdoc,. .,codxxxxxxxxxxxxxxdol;. .;coxxxxxxxxxxxxxxxdoc,. 'clllllllllllllllllllllc:,. .cllllll, .cllllll::loooooooooooooooooooooooo:. .;:cllllllllllllllllllll, ..,:cllllllllllllllllllc. 4 | .;ok0XXNNNNNNNNNNNNNNXXXXXO, 'oOXNNNXXXXXXXXXXXXNNNNXKk; .ckKXNNXXXXXXXXXXXXNNNNNXOc. 'oOXNNNXXXXXXXXXXXXNNNNXKk;. .oXNNNNNNNNNNNXXXXXNNNNNNXX0xc. lKNNNNNKc lXNNNNNXkkXNNNNNNNNNNNNXXXXXXXXXXXXx. .cx0XXNNNNNXXXXXXXXXXXXXXNXo..,okKXNNNNNNNNNNNNNNXXXXXXO, 5 | .:kXNNNNNNNNNNNNNNNNNNNNXXXXk' .c0NNNNNNXXXXXXXXXXXXNNNNNNNKc. ,kXNNNNNNXXXXXXXXXXXNNNNNNNXd. .:0NNNNNNXXXXXXXXXXXXNNNNNNNKc. .xNNNNNNNNNNNNNXXXXNNNNNNNNNNXx'.xNNNNNN0: .xNNNNNNXOONNNNNNNNNNNNNNNXXXNXXXXXKo. .:OXNNNNNNNNNNNNNNNNNNNXXNNNXl'oKNNNNNNNNNNNNNNNNNNXXXXXXk' 6 | .oXNNNNNNNXK0000000000000OOOOo. .lKNNNNNNNNXK000000KXNNNNNNNNN0;.;ONNNNNNNNXKK00000KKXNNNNNNNWXl..lKNWNNNNNNXK000000KKNNNNNNNNNO; ;0NNNNNNNNNXXXXXXXXXXNNNNNNNNNXo:ONNNNNN0; ,ONNNNNNXOKNNNNNNNNNNNNNNNNNNNNNNNNXl. .lKNNNNNNNXXKKKKKKKKKKKKKKKKK0odXWNNNNNNNNNNNNNNNNNNXXXXXXx. 7 | .dNWWWWWWXkl:;;;;;;;;;;,,'..... :KWWWWWWN0o;........,l0NWWWWWWXo;kNWWWWWNKx:'.......'ckXWWWWWWWk,:0WWWWWWN0o;........,l0NWWWWWWXo. cKWWWWWWWW0l;;,;;,,;;:dKWWWWWWNxoKWWWWWW0; cKWWWWWWKdokXWWWWWWWXOxxxxxxxxxxxxxd; cKWWWWWWNO:,'''''''''''''''',,oKWWWWWN0occcccccccccc:cc:c:,. 8 | .lXWWWWWWWNK000000000000OOxo:. .kNWWWWWNO; .lKWWWWWWNxdXWWWWWWKl. ;OWWWWWWWOckNWWWWWW0; .cKWWWWWWNd. .dNWWWWWWWWO;.........'lKWWWWWWXddXWWWWWWXx:;;;;;;;;;:xNWWWWWW0;.cKWWWWWWW0:. 'kWWWWWWWXd:;;;;;;;;;;;;;;;;;;;xNWWWWWNOc;;;;;;;;;;;,'.. 9 | ,kNNNNNNNWWWWWWWWWWWWWWWNNNNXOl..:KNNNNNNXo. :0NNNNNNXkONNNNNNNx' 'kNNNNNNNOd0NNNNNNXo. :0NNNNNNXd. 'xNNNNNNNNNX0000000000KXNNNNNNXx:oXWWWWNNNNNNNNNNNNNNXNNNNNNNNO,.oXNNNNNNNO, .lKNNNNNNNNXXXXXXXXXXXXXXXXXXXXkxXWWWWWWNNXXXXXXXXXXXKKOxl' 10 | :0XXKKKKXXNNNNNNNNNNNNXXXKXXNNKd;oKXKKKKKO; :OKKKKKK0kOXKKKKK0l. ,kKKKKKKKxd0XKKKKKO; :OKKKKKK0l. ,kKKKKKKKKKKKKKKKKKKKKKKKKKKKKk;.:OXXXXXXKXXXNNNNNNNNXXXKKKKKKd'.dKKKKKKKKd. .oKXKKKKKKKKXXKKKKKKKKKKKKKKKKKdckXXXXNXXXXXXKKKKKKKXXXNXXOc. 11 | :O00OOOOkdddddddddddddddxO00KKKOlo00OOOOOd. cOOOOO00kxk0OOOOOx; ,x0OOO000ooO0OOOOOd. cO0OOO00k: ,x0O0OOOOOOOOOOOOOOO00O00OO0OOOo'.:k00000OOO00000000000OOOOO0Oc..o0OOOOOOkc. .o000OOOOO0OOOOOOOOOOOOOOOOOOOk:.'ok00000OOOOOOOOO0000KKKKKk; 12 | :kkkkkOx:. .lkOOOOOooOOkkkkkl. .oOOkkOO0xdkOOkkkOd' .ckOkkOO0OloOOOkkkOo. .oOOkkOOOx' ;xOOkkkkkOkdooooooooodxkkkkkkkkkc. .:odxxkkxxxkkkkkkkkOkkkOOOk;.'dOkkkkkOx; .oOkkkkkOkoc::::::::::::::cccc:. .,:cllllllllllooodkOOOOOk: 13 | ;kOkkkkx; :xkkkOkooOOkkkkkd, .lkOkkkOOOockOkkkkkxc. .:xOkkkOO0x;lOOkkkkkd;. .lkOkkkOOOl. :xkkkkkkkkl. ..,dkkkkkkkkl. ...''''''''''',:dkkkkkkOd' ,xOkkkkkkko,...................lkkkkkkkx:. ..........lkkkkkx: 14 | 'xOOkkkxo;..............;dkkOOOk:cOOOkkxxkxolcclllccloxkkkkkkO0x;,xOkkkkxkkdlccllllccldkkkkkkOOOc.:OOkkkxxkxolcclllllloxkkkkkkOOx, .:xxkxxxxkko:;;;;;;;;;:lxkkkkkkkko::::::::::::::::::coxxxxkkkOo. 'dOOkkkkxkkkkkkkkkkkkkkkkkxxddcckOOkkkkkdlcccccccccccccccccc,.;ccc::::::::::::::cclxkkOOkd' 15 | .ckOOOkkxxdddddddddddoddxkkOOOOc.'xOOOOkkxxkkkkOOOOkkkxxkkkOOOk:..lOOOkkkxxxkkkOOOOOkkkxxkkOOOOo. 'dOOOkkkxxkkkOOOOOkkkxxkkkOOOk: .ckkkkkkkkkkkkkkxxxkkkkkkkOOOOOOolxxxxxxxxkkkkkkkkkkkkkkkkkOOkc .cOOOOOkkkxxxkkkkkkkkkkkkkkxxx:'oOOOkOkkkkxxxxxxxxxxxxxxxxxx:;dxxxxxxxxxxxxxxxxkkkkkOOOOk: 16 | .:kOOOkkxxxdddddddddxxxxkkOOk:. ;xOOOOOkkxxxxxxxxxxxxkkOOOOx:. .dOOOOOkkxxxxxxxxxxxxkkOOOOOl. ,xOOOOOkkxxxxxxxxxxxkkkOOOOk:. .okkOOOOOOOkkkkxxxxxkkkOOOOOOOkc'cxxxxxxkkkkkkkkkkkkkkOOOOOOOd' .lkOOOOOOkkkxxxxxxxxxxxxxxxxd, 'dOOOOOOkkkxxxxxxxxxxxxxxxxd;:dxxxxxxxxxxxxxxxxkkkkOOOOx;. 17 | .cxOOOOkkkxxxxxxxkkkkOOkdc. 'lxO000OOOOkkkkkkOOO000Oxc. .:xO000OOOOkkkkkkOOO000Oxo, .lxO000OOOOkkkkkkOOO00OOxc. 'dOOOOOOOOOOOOkkkkkkkkOOOOkdl:. .lOOkkOOOOOOOOOOOOOOO0000OOxc. 'cdkOOOOOOOOOOOOOOOOOkkkkOd' .;oxOOOOOOkkkkkkkkkkkkkkkko,ckkkkkkkkkkkkkkOkkOOOkkxo:. 18 | ..,;::;;;;;;;;;;;;;,'. .';::::::::::::::::;,.. ..,:::::::::::::::::;'. .';:::::::::::::::::,.. .'''''''''''''''''''''''.. '::::::::::::::::::::::;,.. ..',,,,,,,,,,,,,,,,,,,,. ..'''''''''''''''''''''...',,,,,,,,,,,,,,,,,,'... 19 | 20 | ########################################################################################################################################################################################################################################################################################################## 21 | ########################################################################################################################################################################################################################################################################################################## -------------------------------------------------------------------------------- /test/fixture/8bytes.txt: -------------------------------------------------------------------------------- 1 | 2 | 8 bytes -------------------------------------------------------------------------------- /test/logic.js: -------------------------------------------------------------------------------- 1 | import tap from "tap"; 2 | import { Volume } from "memfs"; 3 | import getFolderSize from "../index.js"; 4 | 5 | /** 6 | * @file 7 | * This test validates the internal logic of the package. It uses memfs to simulate the filesystem. 8 | */ 9 | 10 | //NOTE: Folder sizes are always 0 in memfs. This is not true in native filesystems. 11 | 12 | /** 13 | * Calls all the different function methods, makes sure their results are identical and non-failing, then outputs the result. 14 | * By using this method, all the different calling methods are automatically tested. 15 | */ 16 | async function callAll(itemPath, options) { 17 | const size = await getFolderSize.strict(itemPath, options); 18 | 19 | tap.equal( 20 | await getFolderSize.loose(itemPath, options), 21 | size, 22 | "loose method should return same size as strict", 23 | ); 24 | 25 | tap.strictSame( 26 | await getFolderSize(itemPath, options), 27 | { 28 | errors: null, 29 | size: size, 30 | }, 31 | "default method should return no errors and same size as strict", 32 | ); 33 | 34 | return size; 35 | } 36 | 37 | const B = "#"; //one byte 38 | 39 | const basicFS = Volume.fromJSON( 40 | { 41 | "./8bytes.txt": B.repeat(8), 42 | "./500bytes.txt": B.repeat(500), 43 | "./6000bytes.txt": B.repeat(6000), 44 | }, 45 | "/fixture", 46 | ).promisesApi; 47 | 48 | tap.test("basic folder", async () => { 49 | tap.test("get file sizes", async () => { 50 | tap.equal( 51 | await callAll("/fixture/8bytes.txt", { fs: basicFS }), 52 | 8, 53 | "should return the correct file size", 54 | ); 55 | tap.equal( 56 | await callAll("/fixture/500bytes.txt", { fs: basicFS }), 57 | 500, 58 | "should return the correct file size", 59 | ); 60 | tap.equal( 61 | await callAll("/fixture/6000bytes.txt", { fs: basicFS }), 62 | 6000, 63 | "should return the correct file size", 64 | ); 65 | }); 66 | 67 | tap.test("get folder size", async () => { 68 | tap.equal( 69 | await callAll("/fixture", { fs: basicFS }), 70 | 6508, 71 | "should return the correct folder size", 72 | ); 73 | }); 74 | }); 75 | 76 | tap.test("basic folder - with bigint", async () => { 77 | tap.test("get file sizes", async () => { 78 | tap.equal( 79 | await callAll("/fixture/8bytes.txt", { bigint: true, fs: basicFS }), 80 | 8n, 81 | "should return the correct file size", 82 | ); 83 | tap.equal( 84 | await callAll("/fixture/500bytes.txt", { 85 | bigint: true, 86 | fs: basicFS, 87 | }), 88 | 500n, 89 | "should return the correct file size", 90 | ); 91 | tap.equal( 92 | await callAll("/fixture/6000bytes.txt", { 93 | bigint: true, 94 | fs: basicFS, 95 | }), 96 | 6000n, 97 | "should return the correct file size", 98 | ); 99 | }); 100 | 101 | tap.test("get folder size", async () => { 102 | tap.equal( 103 | await callAll("/fixture", { bigint: true, fs: basicFS }), 104 | 6508n, 105 | "should return the correct folder size", 106 | ); 107 | }); 108 | }); 109 | 110 | tap.test("nested folder", async () => { 111 | const nestedFS = Volume.fromJSON( 112 | { 113 | "./8bytes.txt": B.repeat(8), 114 | "./much/empty/path/500bytes.txt": B.repeat(500), 115 | "./much/empty/path/nested/6000bytes.txt": B.repeat(6000), 116 | }, 117 | "/fixture", 118 | ).promisesApi; 119 | 120 | tap.test("get folder size", async () => { 121 | tap.equal( 122 | await callAll("/fixture", { fs: nestedFS }), 123 | 6508, 124 | "should return the correct folder size", 125 | ); 126 | }); 127 | }); 128 | 129 | /** 130 | * Links do not fill anything, so they should not count towards the folder size. 131 | * See this for issue more information: https://github.com/alessioalex/get-folder-size/issues/9 132 | */ 133 | tap.test("is not confused by links", async () => { 134 | const linkedFS = Volume.fromJSON( 135 | { 136 | "./original.txt": B.repeat(50), 137 | }, 138 | "/fixture", 139 | ).promisesApi; 140 | await linkedFS.link("/fixture/original.txt", "/fixture/link.txt"); 141 | await linkedFS.symlink("/fixture/original.txt", "/fixture/symlink.txt"); 142 | 143 | tap.equal( 144 | await callAll("/fixture", { fs: linkedFS }), 145 | 50, 146 | "should only count the size of the original file", 147 | ); 148 | }); 149 | 150 | tap.test("ignore option", async () => { 151 | tap.equal( 152 | await callAll("/fixture", { ignore: /\d{4}bytes/, fs: basicFS }), 153 | 508, 154 | "should not count the size of the 6000 byte file", 155 | ); 156 | }); 157 | 158 | tap.test("handling very large filesystems", async () => { 159 | const largeFSCore = Volume.fromJSON( 160 | { 161 | "./very.txt": B.repeat(200), 162 | "./large.txt": B.repeat(200), 163 | "./files.txt": B.repeat(200), 164 | }, 165 | "/fixture", 166 | ).promisesApi; 167 | 168 | const largeFS = { 169 | lstat: async (itemPath, options) => { 170 | const result = await largeFSCore.lstat(itemPath, options); 171 | result.size = BigInt(Number.MAX_SAFE_INTEGER); 172 | return result; 173 | }, 174 | readdir: largeFSCore.readdir, 175 | }; 176 | 177 | tap.test("returning Number", async () => { 178 | tap.equal( 179 | await getFolderSize.loose("/fixture", { fs: largeFS }), 180 | Number.MAX_SAFE_INTEGER, 181 | "should return the largest safe number", 182 | ); 183 | 184 | tap.rejects( 185 | async () => { 186 | await getFolderSize.strict("/fixture", { fs: largeFS }); 187 | }, 188 | /The folder size is too large to return as a Number. You can instruct this package to return a BigInt instead./, 189 | "should throw appropriate error", 190 | ); 191 | 192 | const { size, errors } = await getFolderSize("/fixture", { 193 | fs: largeFS, 194 | }); 195 | tap.equal( 196 | size, 197 | Number.MAX_SAFE_INTEGER, 198 | "should return the largest safe number", 199 | ); 200 | tap.type(errors, Array, "should return Array of errors"); 201 | tap.equal(errors.length, 1, "should return one error"); 202 | tap.equal( 203 | errors[0].message, 204 | "The folder size is too large to return as a Number. You can instruct this package to return a BigInt instead.", 205 | "should return appropriate error", 206 | ); 207 | }); 208 | 209 | tap.test("returning BigInt", async () => { 210 | tap.equal( 211 | await getFolderSize.loose("/fixture", { 212 | bigint: true, 213 | fs: largeFS, 214 | }), 215 | BigInt(Number.MAX_SAFE_INTEGER) * 4n, 216 | "should return size of 4 times max safe Number", 217 | ); 218 | 219 | tap.equal( 220 | await getFolderSize.strict("/fixture", { 221 | bigint: true, 222 | fs: largeFS, 223 | }), 224 | BigInt(Number.MAX_SAFE_INTEGER) * 4n, 225 | "should return size of 4 times max safe Number", 226 | ); 227 | 228 | const { size, errors } = await getFolderSize("/fixture", { 229 | bigint: true, 230 | fs: largeFS, 231 | }); 232 | tap.equal( 233 | size, 234 | BigInt(Number.MAX_SAFE_INTEGER) * 4n, 235 | "should return size of 4 times max safe Number", 236 | ); 237 | tap.equal(errors, null, "should return no errors"); 238 | }); 239 | }); 240 | 241 | tap.test("error handling", async () => { 242 | const badFSCore = Volume.fromJSON( 243 | { 244 | "./pass/pass.md": B.repeat(200), 245 | "./pass/pass.txt": B.repeat(200), 246 | "./pass/failFile.js": B.repeat(200), 247 | "./pass/failFile.md": B.repeat(200), 248 | "./pass/pass.js": B.repeat(200), 249 | "./pass/failDir/pass.txt": B.repeat(200), 250 | "./failDir/pass.txt": B.repeat(200), 251 | "./failDir/pass.js": B.repeat(200), 252 | }, 253 | "/fixture", 254 | ).promisesApi; 255 | 256 | const badFS = { 257 | lstat: async (itemPath, options) => { 258 | if (itemPath.includes("failFile")) { 259 | throw Error("Nah - File"); 260 | } else { 261 | return await badFSCore.lstat(itemPath, options); 262 | } 263 | }, 264 | readdir: async (itemPath, options) => { 265 | if (itemPath.includes("failDir")) { 266 | throw Error("Nah - Directory"); 267 | } else { 268 | return await badFSCore.readdir(itemPath, options); 269 | } 270 | }, 271 | }; 272 | 273 | tap.test("missing folder", async () => { 274 | tap.equal( 275 | await getFolderSize.loose("/doesnotexist", { fs: basicFS }), 276 | 0, 277 | "should return size of 0", 278 | ); 279 | 280 | tap.rejects( 281 | async () => { 282 | await getFolderSize.strict("/doesnotexist", { fs: basicFS }); 283 | }, 284 | /ENOENT: no such file or directory, lstat '\/doesnotexist'/, 285 | "should throw appropriate error", 286 | ); 287 | 288 | const { size, errors } = await getFolderSize("/doesnotexist", { 289 | fs: basicFS, 290 | }); 291 | tap.equal(size, 0, "should return size of 0"); 292 | tap.type(errors, Array, "should return Array of errors"); 293 | tap.equal(errors.length, 1, "should return one error"); 294 | tap.equal( 295 | errors[0].message, 296 | `ENOENT: no such file or directory, lstat '/doesnotexist'`, 297 | "should return appropriate error", 298 | ); 299 | }); 300 | 301 | tap.test("read errors on files and folders", async () => { 302 | tap.equal( 303 | await getFolderSize.loose("/fixture", { fs: badFS }), 304 | 600, 305 | `should return size of files that didn't fail`, 306 | ); 307 | 308 | tap.rejects( 309 | async () => { 310 | await getFolderSize.strict("/fixture", { fs: badFS }); 311 | }, 312 | /^Nah - /, 313 | "should return appropriate error", 314 | ); 315 | 316 | const { size, errors } = await getFolderSize("/fixture", { fs: badFS }); 317 | tap.equal(size, 600, `should return size of files that didn't fail`); 318 | tap.type(errors, Array, "should return Array of errors"); 319 | tap.equal(errors.length, 4, "should return four errors"); 320 | 321 | let dirErrors = 0, 322 | fileErrors = 0; 323 | for (const error of errors) { 324 | switch (error.message) { 325 | case "Nah - File": 326 | fileErrors++; 327 | break; 328 | case "Nah - Directory": 329 | dirErrors++; 330 | break; 331 | } 332 | } 333 | tap.equal(dirErrors, 2, "should return two directory read errors"); 334 | tap.equal(fileErrors, 2, "should return two file read errors"); 335 | }); 336 | }); 337 | -------------------------------------------------------------------------------- /test/native.js: -------------------------------------------------------------------------------- 1 | import fs from "node:fs"; 2 | import tap from "tap"; 3 | import getSize from "../index.js"; 4 | 5 | /** 6 | * @file 7 | * This is just a sanity check to make sure the package actually works with the native filesystem. 8 | * The native filesystem is not suitable for strict testing because it is prone to random read errors and because the folder and file sizes can vary depending on the underlying OS. 9 | */ 10 | 11 | tap.test("get file sizes", async () => { 12 | const _8 = await getSize.strict("./test/fixture/8bytes.txt"), 13 | _500 = await getSize.strict("./test/fixture/500bytes.txt"), 14 | _6000 = await getSize.strict("./test/fixture/6000bytes.txt"); 15 | 16 | //The slightly larger allowed size is for file systems that might convert LF to CRLF (Windows) 17 | tap.ok(_8 === 8 || _8 === 9, "should return correct size of the file"); 18 | tap.ok( 19 | _500 === 500 || _500 === 510, 20 | "should return correct size of the file", 21 | ); 22 | tap.ok( 23 | _6000 === 6000 || _6000 === 6020, 24 | "should return correct size of the file", 25 | ); 26 | }); 27 | 28 | tap.test("get folder sizes", async () => { 29 | const fixture = await getSize.strict("./test/fixture"); 30 | 31 | //The returned size must be at least 1 byte larger than the size of the individual files, because the directory itself should use some space as well 32 | tap.ok( 33 | 6508 < fixture && fixture < 1000000000, 34 | "should return approximately correct size of the folder", 35 | ); 36 | 37 | //The node_modules folder offers a convenient opportunity to test the package on a complex folder structure. 38 | //If the folder is not present, this test is skipped. Theoretically speaking, anything that could go wrong in this test should also be covered by other tests. 39 | const node_modules = await getSize.loose("./node_modules"); 40 | tap.ok( 41 | 100000 < node_modules, 42 | "should return approximately correct size of the node_modules folder", 43 | { skip: !fs.existsSync("./node_modules") }, 44 | ); 45 | }); 46 | -------------------------------------------------------------------------------- /test/stress.js: -------------------------------------------------------------------------------- 1 | import tap from "tap"; 2 | import { Volume } from "memfs"; 3 | import getSize from "../index.js"; 4 | 5 | /** 6 | * @file 7 | * This test makes sure that jobs which require many recursions won't exceed any V8 limits. 8 | * This is mainly to make sure that the following bug isn't reintroduced: https://github.com/alessioalex/get-folder-size/issues/12 9 | */ 10 | 11 | //NOTE: Folder sizes are always 0 in memfs. This is not true in native filesystems. 12 | 13 | tap.test("folder with many files", async () => { 14 | const files = {}; 15 | for (let index = 100000; index--; ) { 16 | files[`./${index}`] = "#"; 17 | } 18 | const largeFS = Volume.fromJSON(files, "/fixture").promisesApi; 19 | 20 | tap.equal( 21 | await getSize.strict("/fixture", { fs: largeFS }), 22 | 100000, 23 | "should return correct size of the folder without throwing an error", 24 | ); 25 | }); 26 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "ESNext" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 26 | 27 | /* Modules */ 28 | "module": "NodeNext" /* Specify what module code is generated. */, 29 | // "rootDir": "./", /* Specify the root folder within your source files. */ 30 | // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ 31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 38 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ 39 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ 40 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ 41 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ 42 | // "resolveJsonModule": true, /* Enable importing .json files. */ 43 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ 44 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 45 | 46 | /* JavaScript Support */ 47 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 48 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 49 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 50 | 51 | /* Emit */ 52 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 53 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 54 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 55 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 56 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 57 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 58 | // "outDir": "./", /* Specify an output folder for all emitted files. */ 59 | // "removeComments": true, /* Disable emitting comments. */ 60 | "noEmit": true /* Disable emitting files from a compilation. */, 61 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 62 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 63 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 64 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 65 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 66 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 67 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 68 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 69 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 70 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 71 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 72 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 73 | 74 | /* Interop Constraints */ 75 | "isolatedModules": true /* Ensure that each file can be safely transpiled without relying on other imports. */, 76 | // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ 77 | // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ 78 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 79 | // "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ 80 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 81 | "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, 82 | 83 | /* Type Checking */ 84 | "strict": true /* Enable all strict type-checking options. */ 85 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 86 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 87 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 88 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 89 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 90 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 91 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 92 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 93 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 94 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 95 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 96 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 97 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 98 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 99 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 100 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 101 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 102 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 103 | 104 | /* Completeness */ 105 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 106 | // "skipLibCheck": true /* Skip type checking all .d.ts files. */ 107 | } 108 | } 109 | --------------------------------------------------------------------------------