Repository: svtslv/webdav-cli Branch: master Commit: df1c73ce5ba8 Files: 21 Total size: 19.1 KB Directory structure: gitextract_2f2cjv2a/ ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .prettierrc ├── README.md ├── certs/ │ ├── self-signed.cert.pem │ └── self-signed.key.pem ├── index.d.ts ├── index.js ├── index.ts ├── package.json ├── src/ │ ├── index.ts │ ├── webdav-cli.cli.ts │ ├── webdav-cli.constants.ts │ ├── webdav-cli.interfaces.ts │ ├── webdav-cli.server.ts │ └── webdav-cli.utils.ts ├── test/ │ ├── index.spec.ts │ └── jest.config.json ├── tsconfig.build.json └── tsconfig.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .eslintignore ================================================ index.js index.ts index.d.ts ================================================ FILE: .eslintrc.js ================================================ module.exports = { parser: '@typescript-eslint/parser', parserOptions: { project: 'tsconfig.json', sourceType: 'module', }, plugins: ['@typescript-eslint/eslint-plugin'], extends: [ 'plugin:@typescript-eslint/eslint-recommended', 'plugin:@typescript-eslint/recommended', 'prettier', 'prettier/@typescript-eslint', ], root: true, env: { node: true, jest: true, }, rules: { '@typescript-eslint/interface-name-prefix': 'off', '@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/no-explicit-any': 'off', 'semi': ['error', 'always'], }, }; ================================================ FILE: .gitignore ================================================ # compiled output /dist /node_modules # Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* lerna-debug.log* # OS .DS_Store # Tests /coverage /.nyc_output # IDEs and editors /.idea .project .classpath .c9/ *.launch .settings/ *.sublime-workspace # IDE - VSCode .vscode/* !.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json ================================================ FILE: .prettierrc ================================================ { "singleQuote": true, "trailingComma": "all" } ================================================ FILE: README.md ================================================ # WebDAV CLI NPM Version Package License ## Table of Contents - [Description](#description) - [Installation](#installation) - [Examples](#examples) - [TLS/SSL](#tlsssl) - [License](#license) ## Description A simple zero-configuration command-line webdav server ## Installation #### Globally via `npm` ```bash npm install --global webdav-cli ``` #### Running on-demand: ```bash npx webdav-cli [options] ``` ## Examples ```bash npx webdav-cli --help ``` ```bash 'usage: webdav-cli [options]', '', 'options:', ' --path Path to folder [process.cwd()]', ' --host Host to use [127.0.0.1]', ' --port Port to use [1900]', ' --digest Enable digest authentication [basic]', ' --username Username for basic/digest authentication [random]', ' --password Password for basic/digest authentication [random]', ' --directory Show directory listings [false]', ' --autoIndex Display autoIndex [false]', ' --ssl Enable https [false]', ' --sslKey Path to ssl key file [self-signed]', ' --sslCert Path to ssl cert file [self-signed]', ' --help Print this list and exit', ' --version Print the version and exit.', ' --rights Comma separated values without spaces [all]', ` 'all', 'canCreate', 'canDelete', 'canMove', 'canRename', 'canAppend', 'canWrite', 'canRead', 'canSource', 'canGetMimeType', 'canGetSize', 'canListLocks', 'canSetLock', 'canRemoveLock', 'canGetAvailableLocks', 'canGetLock', 'canAddChild', 'canRemoveChild', 'canGetChildren', 'canSetProperty', 'canGetProperty', 'canGetProperties', 'canRemoveProperty', 'canGetCreationDate', 'canGetLastModifiedDate', 'canGetWebName', 'canGetType'`, 'env:', ' WEBDAV_CLI_PATH, WEBDAV_CLI_HOST, WEBDAV_CLI_PORT,', ' WEBDAV_CLI_USERNAME, WEBDAV_CLI_PASSWORD, WEBDAV_CLI_DIGEST,', ' WEBDAV_CLI_SSL, WEBDAV_CLI_SSL_KEY, WEBDAV_CLI_SSL_CERT,', ' WEBDAV_CLI_DIRECTORY, WEBDAV_CLI_AUTO_INDEX, WEBDAV_CLI_RIGHTS', ' WEBDAV_CLI_DISABLE_AUTHENTICATION', ``` ## TLS/SSL First, you need to make sure that openssl is installed correctly, and you have `key.pem` and `cert.pem` files. You can generate them using this command: ```bash openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem ``` Use `127.0.0.1` as value for `Common name` if you want to be able to install the certificate in your OS's root certificate store or browser so that it is trusted. Then you need to run the server with `--ssl` for enabling SSL and `--sslKey=key.pem --sslCert=cert.pem` for your certificate files. ## License MIT ================================================ FILE: certs/self-signed.cert.pem ================================================ -----BEGIN CERTIFICATE----- MIIDOzCCAiOgAwIBAgIUMeTYKq547CQcDyNj5Sj5ZwcxDN8wDQYJKoZIhvcNAQEL BQAwLTELMAkGA1UEBhMCVUExDTALBgNVBAgMBEt5aXYxDzANBgNVBAoMBnN2dHNs djAeFw0yMDAzMDIyMjUxNDBaFw0zMDAyMjgyMjUxNDBaMC0xCzAJBgNVBAYTAlVB MQ0wCwYDVQQIDARLeWl2MQ8wDQYDVQQKDAZzdnRzbHYwggEiMA0GCSqGSIb3DQEB AQUAA4IBDwAwggEKAoIBAQDBxLjsrteSkjSsT+NnlDM8hJxDI7YGEMOwyJodTNT1 8raXt3iD0LKViqDCxHn5szuwdPo/YlY9o2g5z1xJn7QlzVdRAqtMoxFz9sj8vAqY sAv/jvkJYlcwIamgJhYYmAZM0Lban2x2bDo5oeyUGjk8gtk0V6Y4sfgPm7uJpoE4 pNoFfTA7fN+JQZetaKLfsXazYvUjUn9QFS0AsLZX7mhx7t5ASDCuOmlVRqmD9xiX x6oo8/qGC/sMTEnWeJzpGzyIKXpwMrN/oKxn3/JCgFcDKt+iIEhDQ6YJN23DVBIp mayZ/PWuQ5g1cCWXqZQ7nEMGgW3cSo7xzKb4QNwDLgm/AgMBAAGjUzBRMB0GA1Ud DgQWBBQz4DMPb30ovUO0zd+ECY4M5r1T9zAfBgNVHSMEGDAWgBQz4DMPb30ovUO0 zd+ECY4M5r1T9zAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBN pE0Z3Jf3TSVCxygjh/ylrVLnXuUi3QbrXgKhXVA6a4qHIUnmcAzZCF2YKwZb2p4p 27+DDPGEvVd9nulN8hDQ561B4mggch1KuTZTW7X028AEFIns/+BQJj9v2YnAwn8L IVnmhcqxaerLgKq4KRobLIPIxKeIPBcEcgBlDL244cMDnwOnYp7v5BYxN/s1L5OU 5wCGs6FEt6Nzcw8x777xvVxvAe6TRen0Y0PheCHkoELsJ1Q0UGZHFnXxUP3c3THD WgGG3DuSoc4VNbSGz3yr+08YY2VgNJpYhSQUrBpNEjgeKHTtht1Vi20pb9inSxLj kYXUCOt+RRoAqiulwFLy -----END CERTIFICATE----- ================================================ FILE: certs/self-signed.key.pem ================================================ -----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDBxLjsrteSkjSs T+NnlDM8hJxDI7YGEMOwyJodTNT18raXt3iD0LKViqDCxHn5szuwdPo/YlY9o2g5 z1xJn7QlzVdRAqtMoxFz9sj8vAqYsAv/jvkJYlcwIamgJhYYmAZM0Lban2x2bDo5 oeyUGjk8gtk0V6Y4sfgPm7uJpoE4pNoFfTA7fN+JQZetaKLfsXazYvUjUn9QFS0A sLZX7mhx7t5ASDCuOmlVRqmD9xiXx6oo8/qGC/sMTEnWeJzpGzyIKXpwMrN/oKxn 3/JCgFcDKt+iIEhDQ6YJN23DVBIpmayZ/PWuQ5g1cCWXqZQ7nEMGgW3cSo7xzKb4 QNwDLgm/AgMBAAECggEAbQFCFsP1OdtODnGSuD5C5JSlY4+/YoIj1FvFdx4133Z/ CbKI9X5+OGoYLflhtPsDZS0pambjpSE8DOl+PVy+d1Wg/U3HGAHUW6xFPQh73ZGL 7mR77K+J5OXLCvDiFUvQn336n9p3pdcUmj9hW5+0+zmQ/0UfmV1k80LkqXcl0rrP wEWp8jY5+SzbM6btuPF2JF4vVtGp4sEBDO4ypCC2bypUbdM4FkoNzP9+rBoHFk1q TqXa2o1eh3+Qmw3y+a/AXUR6pzYIxB3jLj6DOaHhz/BaKTccm+1PMEFyMIvx3Uy2 BzHD/db5V4gsIyMMiIeYjmBXc3aCfmNRpHg1Ywf6AQKBgQDmY4zfxZKAmYG2kud6 vT4k1iY2joesi4ei1n4BW50TjLOIus9NW1n5GAPdnCSOuCzn1Pyhqf11EqVW6nhf mDHVmSDGSgj6gX2WuL1EWtBj7AAj30xVcL2VK23ZANpCvSEvkEaxxiKiQNdK3UZa NuYAWTRXHqXdv1HJuv9BYsXQwQKBgQDXTwVvfGLF7fPJqHltBFINTarRYLUnczxw UiS2ItFpOjeddPn4yHzru4QY5maqwajrhHzSe4KWKXAe7Tup1af6cDyBEsyYEI+i I+OJfcZBrjDpolKWulipCI5gR4CK80V/pkCBg5BCinWOExP8zkXD3xhU9SbGjLw+ 7LJUMe/6fwKBgQDOfb0+twMW1f8nl0V3gfQX6gR384lwweJAtcRcDTOc2Qf07ZJt wAnFM5wLXS566GH/K6t+bjCoZJziaOaYr31C96sjbinb9IGOvGeOw2JxnI2HmVT+ YzzYXQNoctYs6Py8d7CVF4PlLv6HsAmlQ/0jpNA/oU2CkT6J81tizFeGQQKBgGFx JeiaxqkFU/vD/5BTED9tEw3HUrUT9hpvUqYLg/K3okvkkO0C72ZQayxJudU16BkO 0N8Bfswu3MtiWko2o9s3yGox894uQJME4wlqnrtC9mgGSpJkq5N0h9sTAR3hk2Z9 +1uiCzvSJfmysK0NPY2z/fMVMANT1i40OVDZeN5JAoGBAMgeJgeP8+K7Z0ecd4TL QONJ9j27mLsHCjSpxdaM98xM7Dw82KxQ4SJ74ZB0LPbSLtkhJhorRmXsAMCDih4Q BGyGnC11c8h1qRCuu2evXkXn6gK8OLcZxZJGTe/3vNR/hn1HCYlAX/sjEyaVVCbL bluIUqnVB577qS3yfxP9dWhu -----END PRIVATE KEY----- ================================================ FILE: index.d.ts ================================================ export * from './dist'; ================================================ FILE: index.js ================================================ "use strict"; function __export(m) { for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; } exports.__esModule = true; __export(require("./dist")); ================================================ FILE: index.ts ================================================ export * from './dist'; ================================================ FILE: package.json ================================================ { "name": "webdav-cli", "version": "2.0.0", "description": "A simple zero-configuration command-line webdav server", "author": "Sviatoslav H", "license": "MIT", "repository": { "type": "git", "url": "https://github.com/svtslv/webdav-cli" }, "keywords": [ "cli", "command", "webdav", "server" ], "files": [ "dist", "certs", "index.js", "index.d.ts" ], "bin": { "webdav-cli": "./dist/webdav-cli.cli.js" }, "preferGlobal": true, "main": "dist/index.js", "scripts": { "fix": "rm -rf node_modules && rm package-lock.json && npm install", "build": "rm -rf dist && tsc -p tsconfig.build.json", "format": "prettier --write \"**/*.ts\"", "lint": "eslint 'lib/**/*.ts' --fix", "test": "jest --config ./test/jest.config.json --runInBand", "prepublish:npm": "npm run build", "publish:npm": "npm publish --access public", "prepublish:test": "npm run build", "publish:test": "npm publish --access public --tag test", "prerelease": "npm run build", "release": "release-it" }, "dependencies": { "chalk": "^4.0.0", "figlet": "^1.3.0", "minimist": "^1.2.5", "webdav-server": "^2.6.2" }, "devDependencies": { "@types/figlet": "^1.2.0", "@types/jest": "^26.0.5", "@types/minimist": "^1.2.0", "@types/node": "^13.9.1", "@types/supertest": "^2.0.8", "@typescript-eslint/eslint-plugin": "^2.24.0", "@typescript-eslint/parser": "^2.24.0", "eslint": "^6.8.0", "eslint-config-prettier": "^6.10.0", "eslint-plugin-import": "^2.20.1", "jest": "^26.1.0", "prettier": "^1.19.1", "reflect-metadata": "^0.1.13", "release-it": "^15.5.0", "supertest": "^4.0.2", "ts-jest": "^26.1.3", "ts-loader": "^9.4.2", "ts-node": "^8.6.2", "tsconfig-paths": "^3.9.0", "typescript": "^3.8.3" } } ================================================ FILE: src/index.ts ================================================ export * from './webdav-cli.constants'; export * from './webdav-cli.interfaces'; export * from './webdav-cli.server'; export * from './webdav-cli.utils'; ================================================ FILE: src/webdav-cli.cli.ts ================================================ #!/usr/bin/env node import * as chalk from 'chalk'; import * as figlet from 'figlet'; import * as minimist from 'minimist'; import { WebdavCli } from './webdav-cli.server'; import { HOMEPAGE } from './webdav-cli.constants'; const argv = minimist(process.argv.slice(2)); console.log(chalk.green(figlet.textSync('webdav-cli', { horizontalLayout: 'full' }))); console.log(chalk.green(`Homepage: ${ HOMEPAGE }\n`)); if (argv.help) { console.log([ 'usage: webdav-cli [options]', '', 'options:', ' --path Path to folder [process.cwd()]', ' --host Host to use [127.0.0.1]', ' --port Port to use [1900]', ' --digest Enable digest authentication [basic]', ' --username Username for basic/digest authentication [random]', ' --password Password for basic/digest authentication [random]', ' --directory Show directory listings [false]', ' --autoIndex Display autoIndex [false]', ' --ssl Enable https [false]', ' --sslKey Path to ssl key file [self-signed]', ' --sslCert Path to ssl cert file [self-signed]', ' --help Print this list and exit', ' --version Print the version and exit.', ' --rights Comma separated values without spaces [all]', ` 'all', 'canCreate', 'canDelete', 'canMove', 'canRename', 'canAppend', 'canWrite', 'canRead', 'canSource', 'canGetMimeType', 'canGetSize', 'canListLocks', 'canSetLock', 'canRemoveLock', 'canGetAvailableLocks', 'canGetLock', 'canAddChild', 'canRemoveChild', 'canGetChildren', 'canSetProperty', 'canGetProperty', 'canGetProperties', 'canRemoveProperty', 'canGetCreationDate', 'canGetLastModifiedDate', 'canGetWebName', 'canGetType'`, '', 'env:', ' WEBDAV_CLI_PATH, WEBDAV_CLI_HOST, WEBDAV_CLI_PORT,', ' WEBDAV_CLI_USERNAME, WEBDAV_CLI_PASSWORD, WEBDAV_CLI_DIGEST,', ' WEBDAV_CLI_SSL, WEBDAV_CLI_SSL_KEY, WEBDAV_CLI_SSL_CERT,', ' WEBDAV_CLI_DIRECTORY, WEBDAV_CLI_AUTO_INDEX, WEBDAV_CLI_RIGHTS', ' WEBDAV_CLI_DISABLE_AUTHENTICATION', '', ].join('\n')); process.exit(); } if (argv.version) { console.log('Version: ' + require('../package.json').version, '\n'); process.exit(); } const argvRights = argv.rights && typeof argv.rights === 'string' ? argv.rights.split(',') : undefined; const envRights = process.env.WEBDAV_CLI_RIGHTS ? process.env.WEBDAV_CLI_RIGHTS.split(',') : undefined; const config = { path: argv.path || process.env.WEBDAV_CLI_PATH, host: argv.host || process.env.WEBDAV_CLI_HOST, port: argv.port || parseInt(process.env.WEBDAV_CLI_PORT), digest: argv.digest || Boolean(process.env.WEBDAV_CLI_DIGEST), username: argv.username || process.env.WEBDAV_CLI_USERNAME, password: argv.password || process.env.WEBDAV_CLI_PASSWORD, directory: argv.directory || process.env.WEBDAV_CLI_DIRECTORY, autoIndex: argv.autoIndex || process.env.WEBDAV_CLI_AUTO_INDEX, ssl: argv.ssl || Boolean(process.env.WEBDAV_CLI_SSL), sslKey: argv.sslKey || process.env.WEBDAV_CLI_SSL_KEY, sslCert: argv.sslCert || process.env.WEBDAV_CLI_SSL_CERT, disableAuthentication: argv.disableAuthentication || process.env.WEBDAV_CLI_DISABLE_AUTHENTICATION, rights: (argvRights || envRights) as any, }; const run = async() => { const webdavCli = new WebdavCli(config); const webdavCliServer = await webdavCli.start(); webdavCliServer.on('log', (ctx, fs, path, log) => console.log(log)); }; run(); ================================================ FILE: src/webdav-cli.constants.ts ================================================ import { WebdavCliRights } from './webdav-cli.interfaces'; export const HOMEPAGE = 'https://github.com/svtslv/webdav-cli'; export const RIGHTS: WebdavCliRights = [ 'all', 'canCreate', 'canDelete', 'canMove', 'canRename', 'canAppend', 'canWrite', 'canRead', 'canSource', 'canGetMimeType', 'canGetSize', 'canListLocks', 'canSetLock', 'canRemoveLock', 'canGetAvailableLocks', 'canGetLock', 'canAddChild', 'canRemoveChild', 'canGetChildren', 'canSetProperty', 'canGetProperty', 'canGetProperties', 'canRemoveProperty', 'canGetCreationDate', 'canGetLastModifiedDate', 'canGetWebName', 'canGetType', ]; ================================================ FILE: src/webdav-cli.interfaces.ts ================================================ import { BasicPrivilege, v2 as webdav } from 'webdav-server'; export type WebdavCliRights = BasicPrivilege[]; export interface WebdavCliConfig { path: string, host: string, port: number, digest: boolean, username: string, password: string, ssl: boolean, sslKey: string, sslCert: string, rights: WebdavCliRights, disableAuthentication?: boolean, url?: string, directory?: boolean, autoIndex?: boolean, } export interface WebdavCliServer extends webdav.WebDAVServer { config: WebdavCliConfig, } ================================================ FILE: src/webdav-cli.server.ts ================================================ import * as fs from 'fs'; import { join } from 'path'; import { v2 as webdav } from 'webdav-server'; import { getRandomString } from './webdav-cli.utils'; import { RIGHTS } from './webdav-cli.constants'; import { WebdavCliServer, WebdavCliConfig, WebdavCliRights } from './webdav-cli.interfaces'; export class WebdavCli { config: WebdavCliConfig; constructor(config: Partial) { this.config = this.getConfig(config); } getConfig(config: Partial): WebdavCliConfig { const selfSignedKey = join(__dirname, '/../certs/self-signed.key.pem'); const selfSignedCert = join(__dirname, '/../certs/self-signed.cert.pem'); const path = config.path || process.cwd(); const host = config.host || '127.0.0.1'; const port = config.port || 1900; const digest = Boolean(config.digest); let username = (config.username || getRandomString(16)).toString(); let password = (config.password || getRandomString(16)).toString(); const ssl = Boolean(config.ssl); const sslKey = ssl ? fs.readFileSync(config.sslKey || selfSignedKey).toString() : ''; const sslCert = ssl ? fs.readFileSync(config.sslCert || selfSignedCert).toString() : ''; const disableAuthentication = Boolean(config.disableAuthentication); if(disableAuthentication) { config.rights = config.rights || ['canRead']; username = ''; password = ''; } const rights = (config.rights || ['all']).filter((item: WebdavCliRights[number]) => RIGHTS.includes(item)); const url = `${ ssl ? 'https' : 'http' }://${ host }:${ port }`; const directory = Boolean(config.directory); const autoIndex = Boolean(config.autoIndex); return { host, path, port, username, digest, password, ssl, sslCert, sslKey, rights, url, disableAuthentication, directory, autoIndex, }; } async start(): Promise { const config = this.config; const userManager = new webdav.SimpleUserManager(); const user = userManager.addUser(config.username, config.password, false); const privilegeManager = new webdav.SimplePathPrivilegeManager(); privilegeManager.setRights(user, '/', config.rights); const authentication = config.digest ? 'HTTPDigestAuthentication' : 'HTTPBasicAuthentication'; const server = new webdav.WebDAVServer({ httpAuthentication: config.disableAuthentication ? { askForAuthentication: () => ({}), getUser: (ctx, gotUserCallback) => { userManager.getDefaultUser((defaultUser) => { privilegeManager.setRights(defaultUser, '/', config.rights); gotUserCallback(null, defaultUser); }); } } : new webdav[authentication](userManager, 'Default realm'), privilegeManager: privilegeManager, https: config.ssl ? { cert: config.sslCert, key: config.sslKey } : null, port: config.port, hostname: config.host, }) as WebdavCliServer; server.config = config; server.beforeRequest(async (ctx, next) => { if (config.directory) { const isBrowser = ctx.request.headers['user-agent'].search('Mozilla/5.0') !== -1; if(isBrowser) { try { const resource = await server.getResourceAsync(ctx, ctx.requested.uri); const list = await resource.readDirAsync(); const uri = ctx.requested.uri.slice(-1) === '/' ? ctx.requested.uri : ctx.requested.uri + '/'; if(config.autoIndex && list.includes('index.html')) { ctx.requested.path = `${uri}index.html` as any; } else { const up = `..
`; const html = up + list.map(item => `${ item }
`).join(''); // ctx.response.setHeader('Content-Type', 'text/html;charset=UTF-8'); ctx.response.end(`${html}`); } } catch {} } } next(); }); server.afterRequest((arg, next) => { const log = `>> ${ arg.request.method } ${ arg.requested.uri } > ${ arg.response.statusCode } ${ arg.response.statusMessage }`; server.emit('log', null, null, '/', log); next(); }); await server.setFileSystemAsync('/', new webdav.PhysicalFileSystem(config.path)); await server.startAsync(config.port); const logs = [ `Server running at ${ config.url }`, `[rights]: ${ config.rights }`, `[digest]: ${ config.digest }`, `username: ${ config.username }`, `password: ${ config.password }`, 'Hit CTRL-C to stop the server', 'Run with --help to print help' ]; console.log(logs.join('\n')); return server; } } ================================================ FILE: src/webdav-cli.utils.ts ================================================ export function getRandomString(length: number) { return [...Array(Math.ceil(length / 8))].map(() => Math.random().toString(36).slice(-8)).join('').slice(-length); } ================================================ FILE: test/index.spec.ts ================================================ import * as index from '../src/index'; describe('Index', () => { test('should return 4 exports', () => { expect(Object.keys(index)).toHaveLength(4); }); }); ================================================ FILE: test/jest.config.json ================================================ { "moduleFileExtensions": ["js", "json", "ts"], "rootDir": ".", "testEnvironment": "node", "testRegex": ".spec.ts$", "transform": { "^.+\\.(t|j)s$": "ts-jest" } } ================================================ FILE: tsconfig.build.json ================================================ { "extends": "./tsconfig.json", "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] } ================================================ FILE: tsconfig.json ================================================ { "compilerOptions": { "module": "commonjs", "declaration": true, "removeComments": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "target": "es2017", "sourceMap": false, "outDir": "./dist", "baseUrl": "./", "skipLibCheck": true }, "include": ["src/**/*", "test/**/*"], "exclude": ["node_modules", "dist"] }