diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index a141ce3..b5920a4 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -20,9 +20,14 @@ jobs: - name: Install dependencies run: npm install + + - name: Transpile code + run: npm run build + - name: Automatic GitHub Release uses: justincy/github-action-npm-release@2.0.1 id: release + - name: Publish to NPM Registry run: npm publish --access public if: steps.release.outputs.released == 'true' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 949df6f..d798833 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,9 +27,13 @@ jobs: - name: Install dependencies run: npm install + - name: Run tests run: npm run test:coverage + - name: Test code transpilation + run: npm run build + windows: runs-on: windows-latest strategy: @@ -46,5 +50,9 @@ jobs: - name: Install dependencies run: npm install + - name: Run tests run: npm run test:coverage + + - name: Test code transpilation + run: npm run build diff --git a/.gitignore b/.gitignore index c446e8d..fb8511b 100644 --- a/.gitignore +++ b/.gitignore @@ -114,8 +114,13 @@ out .yarn/install-state.gz .pnp.* +# Transpiled code path +dist +build + # IDE .idea +.fleet .vscode # Environment variables file diff --git a/bin/japaTypes.ts b/bin/japaTypes.ts new file mode 100644 index 0000000..aac0993 --- /dev/null +++ b/bin/japaTypes.ts @@ -0,0 +1,25 @@ +/** + * @athenna/common + * + * (c) João Lenon + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare module '@japa/assert' { + export interface Assert { + throws(fn: () => void, errType: any, message?: string): void + doesNotThrows(fn: () => void, errType: any, message?: string): void + rejects( + fn: () => void | Promise, + errType: any, + message?: string, + ): Promise + doesNotRejects( + fn: () => void | Promise, + errType: any, + message?: string, + ): Promise + } +} diff --git a/tests/index.js b/bin/test.ts similarity index 79% rename from tests/index.js rename to bin/test.ts index 7dc26d1..56ef367 100644 --- a/tests/index.js +++ b/bin/test.ts @@ -1,8 +1,19 @@ +/** + * @athenna/common + * + * (c) João Lenon + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + import { pathToFileURL } from 'url' import { assert } from '@japa/assert' import { specReporter } from '@japa/spec-reporter' import { processCliArgs, configure, run } from '@japa/runner' +import('./japaTypes.js') + /* |-------------------------------------------------------------------------- | Configure tests @@ -17,10 +28,12 @@ import { processCliArgs, configure, run } from '@japa/runner' | Please consult japa.dev/runner-config for the config docs. */ +process.env.IS_TS = 'true' + configure({ ...processCliArgs(process.argv.slice(2)), ...{ - files: ['tests/**/*Test.js'], + files: ['tests/**/*Test.ts'], plugins: [assert()], reporters: [specReporter()], importer: filePath => import(pathToFileURL(filePath).href), diff --git a/package-lock.json b/package-lock.json index 215e0f3..ea9263a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@athenna/common", - "version": "3.1.0", + "version": "3.2.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@athenna/common", - "version": "3.1.0", + "version": "3.2.0", "license": "MIT", "dependencies": { "@fastify/formbody": "^7.4.0", @@ -38,6 +38,18 @@ "@japa/run-failed-tests": "^1.1.0", "@japa/runner": "^2.2.2", "@japa/spec-reporter": "^1.3.2", + "@swc/cli": "^0.1.57", + "@swc/core": "^1.3.27", + "@types/bytes": "^3.1.1", + "@types/callsite": "^1.0.31", + "@types/debug": "^4.1.7", + "@types/kind-of": "^6.0.0", + "@types/lodash": "^4.14.191", + "@types/ms": "^0.7.31", + "@types/pluralize": "^0.0.29", + "@types/uuid": "^9.0.0", + "@typescript-eslint/eslint-plugin": "^5.48.1", + "@typescript-eslint/parser": "^5.48.1", "c8": "^7.12.0", "commitizen": "^4.2.6", "cross-env": "^7.0.3", @@ -54,6 +66,8 @@ "minimist": "^1.2.7", "prettier": "^2.8.3", "rimraf": "^3.0.2", + "ts-node": "^10.9.1", + "tsup": "^6.5.0", "typescript": "^4.9.4" } }, @@ -375,25 +389,46 @@ "dev": true, "optional": true }, - "node_modules/@cspotcode/source-map-consumer": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", - "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz", + "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==", + "cpu": [ + "arm" + ], "dev": true, "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">= 12" + "node": ">=12" } }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", - "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "node_modules/@esbuild/linux-loong64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz", + "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==", + "cpu": [ + "loong64" + ], "dev": true, "optional": true, - "dependencies": { - "@cspotcode/source-map-consumer": "0.8.0" - }, + "os": [ + "linux" + ], "engines": { "node": ">=12" } @@ -799,6 +834,238 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, + "node_modules/@swc/cli": { + "version": "0.1.57", + "resolved": "https://registry.npmjs.org/@swc/cli/-/cli-0.1.57.tgz", + "integrity": "sha512-HxM8TqYHhAg+zp7+RdTU69bnkl4MWdt1ygyp6BDIPjTiaJVH6Dizn2ezbgDS8mnFZI1FyhKvxU/bbaUs8XhzQg==", + "dev": true, + "dependencies": { + "commander": "^7.1.0", + "fast-glob": "^3.2.5", + "slash": "3.0.0", + "source-map": "^0.7.3" + }, + "bin": { + "spack": "bin/spack.js", + "swc": "bin/swc.js" + }, + "engines": { + "node": ">= 12.13" + }, + "peerDependencies": { + "@swc/core": "^1.2.66", + "chokidar": "^3.5.1" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@swc/cli/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@swc/cli/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@swc/core": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.27.tgz", + "integrity": "sha512-praRNgpeYGvwDIm/Cl6JU+yHMvwVraL0U6ejMgGyzvpcm1FVsZd1/EYXGqzbBJ0ALv7Gx4eK56h4GnwV6d4L0w==", + "dev": true, + "hasInstallScript": true, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.3.27", + "@swc/core-darwin-x64": "1.3.27", + "@swc/core-linux-arm-gnueabihf": "1.3.27", + "@swc/core-linux-arm64-gnu": "1.3.27", + "@swc/core-linux-arm64-musl": "1.3.27", + "@swc/core-linux-x64-gnu": "1.3.27", + "@swc/core-linux-x64-musl": "1.3.27", + "@swc/core-win32-arm64-msvc": "1.3.27", + "@swc/core-win32-ia32-msvc": "1.3.27", + "@swc/core-win32-x64-msvc": "1.3.27" + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.27.tgz", + "integrity": "sha512-IKlxkhEy99CnP9nduaf5IJWIFcr6D5cZCjYmCs7nWkjMV+aAieyDO9AX4LT8AcHy6CF7ByOX7SKoqk+gVMAaKw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.27.tgz", + "integrity": "sha512-MtabZIhFf/dL3vs6UMbd+vJsjIkm2NaFqulGV0Jofy2bfVZPTj/b5pXeOlUsTWy7JcH1uixjdx4RvJRyvqJxQA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.27.tgz", + "integrity": "sha512-XELMoGcUTAkk+G4buwIIhu6AIr1U418Odt22HUW8+ZvV+Wty2ICgR/myOIhM3xMb6U2L8ay+evMqoVNMQ0RRTg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.27.tgz", + "integrity": "sha512-O6vtT6bnrVR9PzEIuA5U7tIfYo7bv97H9K9Vqy2oyHNeGN0H36DKwS4UqPreHtziXNF5+7ubdUYUkrG/j8UnUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.27.tgz", + "integrity": "sha512-Oa0E1i7dOTWpaEZumKoNbTE/Ap+da6nlhqKVUdYrFDrOBi25tz76SdxZIyvAszzmgY89b5yd1naourKmkPXpww==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.27.tgz", + "integrity": "sha512-S3v9H8oL2a8Ur6AjQyhkC6HfBVPOxKMdBhcZmdNuVgEUHbHdbf/Lka85F9IOYXEarMn0FtQw3ywowS22O9L5Uw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.27.tgz", + "integrity": "sha512-6DDkdXlOADpwICFZTRphCR+cIeS8aEYh4NlyzBito0mOWwIIdfCgALzhkTQOzTOkcD42bP97CIoZ97hqV/puOg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.27.tgz", + "integrity": "sha512-baxfH4AbEcaTNo08wxV0W6hiMXwVCxPS4qc0amHpXPti92unvSqeDR1W3C9GjHqzXlWtmCRsq8Ww1pal6ZVLrw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.27.tgz", + "integrity": "sha512-7iLJnH71k5qCwxv9NcM/P7nIEzTsC7r1sIiQW6bu+CpC8qZvwl0PS+XvQRlLly2gCZM+Le98tksYG14MEh+Hrw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.27.tgz", + "integrity": "sha512-mFM907PDw/jrQ44+TRjIVGEOy2Mu06mMMz0HPMFuRsBzl5t0Kajp3vmn8FkkpS9wH5982VPi6hPYVTb7QJo5Qg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, "node_modules/@szmarczak/http-timer": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", @@ -814,29 +1081,37 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", - "dev": true, - "optional": true + "dev": true }, "node_modules/@tsconfig/node12": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", - "dev": true, - "optional": true + "dev": true }, "node_modules/@tsconfig/node14": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", - "dev": true, - "optional": true + "dev": true }, "node_modules/@tsconfig/node16": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", - "dev": true, - "optional": true + "dev": true + }, + "node_modules/@types/bytes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/bytes/-/bytes-3.1.1.tgz", + "integrity": "sha512-lOGyCnw+2JVPKU3wIV0srU0NyALwTBJlVSx5DfMQOFuuohA8y9S8orImpuIQikZ0uIQ8gehrRjxgQC1rLRi11w==", + "dev": true + }, + "node_modules/@types/callsite": { + "version": "1.0.31", + "resolved": "https://registry.npmjs.org/@types/callsite/-/callsite-1.0.31.tgz", + "integrity": "sha512-jrKmIHhuZVGUpOR1s4TgY9BTt/Eh9CFCjHVZ2FsrKmHSo3J/vpl6EpK08SfMLrX2IY1ZEFA+BPRTJQGg4xIHsA==", + "dev": true }, "node_modules/@types/chai": { "version": "4.3.4", @@ -844,6 +1119,15 @@ "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", "dev": true }, + "node_modules/@types/debug": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", + "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", + "dev": true, + "dependencies": { + "@types/ms": "*" + } + }, "node_modules/@types/http-cache-semantics": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", @@ -876,12 +1160,32 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "node_modules/@types/kind-of": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@types/kind-of/-/kind-of-6.0.0.tgz", + "integrity": "sha512-OBts6MHCrq558cvND5nsWhoThwJaNu5lmGnSp3H0gFzQQc5QYM9p7HajIdS+2bgDquGX1qLZCPlyuYSxMDffAg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/lodash": { + "version": "4.14.191", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz", + "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==", + "dev": true + }, + "node_modules/@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", + "dev": true + }, "node_modules/@types/node": { "version": "17.0.29", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.29.tgz", "integrity": "sha512-tx5jMmMFwx7wBwq/V7OohKDVb/JwJU5qCVkeLMh1//xycAJ/ESuw9aJ9SEtlCZDYi2pBfe4JkisSoAtbOsBNAA==", - "dev": true, - "optional": true + "dev": true }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", @@ -896,12 +1200,284 @@ "dev": true, "optional": true }, + "node_modules/@types/pluralize": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/pluralize/-/pluralize-0.0.29.tgz", + "integrity": "sha512-BYOID+l2Aco2nBik+iYS4SZX0Lf20KPILP5RGmM1IgzdwNdTs0eebiFriOPcej1sX9mLnSoiNte5zcFxssgpGA==", + "dev": true + }, + "node_modules/@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true + }, + "node_modules/@types/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-kr90f+ERiQtKWMz5rP32ltJ/BtULDI5RVO0uavn1HQUOwjx0R1h0rnDYNL0CepF1zL5bSY6FISAfd9tOdDhU5Q==", + "dev": true + }, "node_modules/@types/yargs-parser": { "version": "21.0.0", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", "dev": true }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.48.2.tgz", + "integrity": "sha512-sR0Gja9Ky1teIq4qJOl0nC+Tk64/uYdX+mi+5iB//MH8gwyx8e3SOyhEzeLZEFEEfCaLf8KJq+Bd/6je1t+CAg==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.48.2", + "@typescript-eslint/type-utils": "5.48.2", + "@typescript-eslint/utils": "5.48.2", + "debug": "^4.3.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.48.2.tgz", + "integrity": "sha512-38zMsKsG2sIuM5Oi/olurGwYJXzmtdsHhn5mI/pQogP+BjYVkK5iRazCQ8RGS0V+YLk282uWElN70zAAUmaYHw==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.48.2", + "@typescript-eslint/types": "5.48.2", + "@typescript-eslint/typescript-estree": "5.48.2", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.48.2.tgz", + "integrity": "sha512-zEUFfonQid5KRDKoI3O+uP1GnrFd4tIHlvs+sTJXiWuypUWMuDaottkJuR612wQfOkjYbsaskSIURV9xo4f+Fw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.48.2", + "@typescript-eslint/visitor-keys": "5.48.2" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.48.2.tgz", + "integrity": "sha512-QVWx7J5sPMRiOMJp5dYshPxABRoZV1xbRirqSk8yuIIsu0nvMTZesKErEA3Oix1k+uvsk8Cs8TGJ6kQ0ndAcew==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.48.2", + "@typescript-eslint/utils": "5.48.2", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.2.tgz", + "integrity": "sha512-hE7dA77xxu7ByBc6KCzikgfRyBCTst6dZQpwaTy25iMYOnbNljDT4hjhrGEJJ0QoMjrfqrx+j1l1B9/LtKeuqA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.48.2.tgz", + "integrity": "sha512-bibvD3z6ilnoVxUBFEgkO0k0aFvUc4Cttt0dAreEr+nrAHhWzkO83PEVVuieK3DqcgL6VAK5dkzK8XUVja5Zcg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.48.2", + "@typescript-eslint/visitor-keys": "5.48.2", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.48.2.tgz", + "integrity": "sha512-2h18c0d7jgkw6tdKTlNaM7wyopbLRBiit8oAxoP89YnuBOzCZ8g8aBCaCqq7h208qUTroL7Whgzam7UY3HVLow==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.48.2", + "@typescript-eslint/types": "5.48.2", + "@typescript-eslint/typescript-estree": "5.48.2", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.2.tgz", + "integrity": "sha512-z9njZLSkwmjFWUelGEwEbdf4NwKvfHxvGC0OcGN1Hp/XNDIcJ7D5DpPNPv6x6/mFvc1tQHsaWmpD/a4gOvvCJQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.48.2", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -1052,6 +1628,25 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/api-contract-validator": { "version": "2.2.8", "resolved": "https://registry.npmjs.org/api-contract-validator/-/api-contract-validator-2.2.8.tgz", @@ -1271,8 +1866,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, - "optional": true + "dev": true }, "node_modules/argparse": { "version": "2.0.1", @@ -1299,6 +1893,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/array.prototype.flat": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", @@ -1433,6 +2036,15 @@ } ] }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -1512,6 +2124,21 @@ "node": ">=10" } }, + "node_modules/bundle-require": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-3.1.2.tgz", + "integrity": "sha512-Of6l6JBAxiyQ5axFxUM6dYeP/W7X2Sozeo/4EYB9sJhL+dqL7TKjg+shwxp6jlu/6ZSERfsYtIpSJ1/x3XkAEA==", + "dev": true, + "dependencies": { + "load-tsconfig": "^0.2.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "esbuild": ">=0.13" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -1593,6 +2220,15 @@ "node": ">=10" } }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/cacheable-lookup": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", @@ -1798,6 +2434,45 @@ "node": "*" } }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", @@ -2152,8 +2827,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true, - "optional": true + "dev": true }, "node_modules/cross-env": { "version": "7.0.3", @@ -2424,7 +3098,6 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, - "optional": true, "engines": { "node": ">=0.3.1" } @@ -2438,6 +3111,18 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -2588,6 +3273,363 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/esbuild": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", + "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.15.18", + "@esbuild/linux-loong64": "0.15.18", + "esbuild-android-64": "0.15.18", + "esbuild-android-arm64": "0.15.18", + "esbuild-darwin-64": "0.15.18", + "esbuild-darwin-arm64": "0.15.18", + "esbuild-freebsd-64": "0.15.18", + "esbuild-freebsd-arm64": "0.15.18", + "esbuild-linux-32": "0.15.18", + "esbuild-linux-64": "0.15.18", + "esbuild-linux-arm": "0.15.18", + "esbuild-linux-arm64": "0.15.18", + "esbuild-linux-mips64le": "0.15.18", + "esbuild-linux-ppc64le": "0.15.18", + "esbuild-linux-riscv64": "0.15.18", + "esbuild-linux-s390x": "0.15.18", + "esbuild-netbsd-64": "0.15.18", + "esbuild-openbsd-64": "0.15.18", + "esbuild-sunos-64": "0.15.18", + "esbuild-windows-32": "0.15.18", + "esbuild-windows-64": "0.15.18", + "esbuild-windows-arm64": "0.15.18" + } + }, + "node_modules/esbuild-android-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz", + "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-android-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz", + "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz", + "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz", + "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz", + "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz", + "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-32": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz", + "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz", + "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz", + "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz", + "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz", + "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz", + "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-riscv64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz", + "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-s390x": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz", + "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz", + "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz", + "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-sunos-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz", + "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-32": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz", + "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz", + "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", + "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -3640,6 +4682,20 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -3896,6 +4952,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -4519,10 +5595,22 @@ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dev": true, "dependencies": { - "has-bigints": "^1.0.1" + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=8" } }, "node_modules/is-boolean-object": { @@ -5013,6 +6101,15 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/js-sdsl": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.2.0.tgz", @@ -5376,6 +6473,15 @@ "node": ">=8" } }, + "node_modules/load-tsconfig": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.3.tgz", + "integrity": "sha512-iyT2MXws+dc2Wi6o3grCFtGXpeMvHmJqS27sMPGtV2eUu4PeFnG+33I8BlFK1t1NWMjOpcx9bridn5yxLDX2gQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -5432,6 +6538,12 @@ "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=", "dev": true }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -5660,8 +6772,7 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true, - "optional": true + "dev": true }, "node_modules/md5": { "version": "2.2.1", @@ -5792,12 +6903,29 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "node_modules/nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -5875,6 +7003,15 @@ "node": ">=4" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.12.3", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", @@ -6261,7 +7398,6 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, - "optional": true, "engines": { "node": ">=8" } @@ -6371,6 +7507,15 @@ "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.0.0.tgz", "integrity": "sha512-mMMOwSKrmyl+Y12Ri2xhH1lbzQxwwpuru9VjyJpgFIH4asSj88F2csdMwN6+M5g1Ll4rmsYghHLQJw81tgZ7LQ==" }, + "node_modules/pirates": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -6461,6 +7606,35 @@ "node": ">=4" } }, + "node_modules/postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dev": true, + "dependencies": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -6659,6 +7833,18 @@ "node": ">= 6" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/real-require": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", @@ -6753,7 +7939,6 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, - "optional": true, "engines": { "node": ">=8" } @@ -6844,6 +8029,22 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rollup": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.10.0.tgz", + "integrity": "sha512-JmRYz44NjC1MjVF2VKxc0M1a97vn+cDxeqWmnwyAF4FvpjK8YFdHpaqvQB+3IxCvX05vJxKZkoMDU8TShhmJVA==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, "node_modules/run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", @@ -7289,6 +8490,78 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/sucrase": { + "version": "3.29.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.29.0.tgz", + "integrity": "sha512-bZPAuGA5SdFHuzqIhTAqt9fvNEo9rESqXIG3oiKdF8K4UmkQxC4KlNL3lVyAErXp+mPvUqZ5l13qx6TrDIGf3A==", + "dev": true, + "dependencies": { + "commander": "^4.0.0", + "glob": "7.1.6", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sucrase/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sucrase/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -7440,6 +8713,27 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/thread-stream": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.2.0.tgz", @@ -7501,20 +8795,43 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/traverse": { "version": "0.6.6", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", "dev": true }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true + }, "node_modules/ts-node": { - "version": "10.7.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz", - "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==", + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, - "optional": true, "dependencies": { - "@cspotcode/source-map-support": "0.7.0", + "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", @@ -7525,7 +8842,7 @@ "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.0", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "bin": { @@ -7556,36 +8873,172 @@ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", "dev": true, - "optional": true, "engines": { - "node": ">=0.4.0" + "node": ">=0.4.0" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", + "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "node_modules/tsup": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/tsup/-/tsup-6.5.0.tgz", + "integrity": "sha512-36u82r7rYqRHFkD15R20Cd4ercPkbYmuvRkz3Q1LCm5BsiFNUgpo36zbjVhCOgvjyxNBWNKHsaD5Rl8SykfzNA==", + "dev": true, + "dependencies": { + "bundle-require": "^3.1.2", + "cac": "^6.7.12", + "chokidar": "^3.5.1", + "debug": "^4.3.1", + "esbuild": "^0.15.1", + "execa": "^5.0.0", + "globby": "^11.0.3", + "joycon": "^3.0.1", + "postcss-load-config": "^3.0.1", + "resolve-from": "^5.0.0", + "rollup": "^3.2.5", + "source-map": "0.8.0-beta.0", + "sucrase": "^3.20.3", + "tree-kill": "^1.2.2" + }, + "bin": { + "tsup": "dist/cli-default.js", + "tsup-node": "dist/cli-node.js" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@swc/core": "^1", + "postcss": "^8.4.12", + "typescript": "^4.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "postcss": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/tsup/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/tsup/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tsup/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tsup/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/tsconfig-paths": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", - "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "node_modules/tsup/node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", "dev": true, "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, "engines": { - "node": ">=4" + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, - "node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true }, "node_modules/type-check": { "version": "0.4.0", @@ -7713,8 +9166,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true, - "optional": true + "dev": true }, "node_modules/v8-to-istanbul": { "version": "9.0.0", @@ -7769,6 +9221,23 @@ "defaults": "^1.0.3" } }, + "node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -7904,7 +9373,6 @@ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, - "optional": true, "engines": { "node": ">=6" } @@ -8217,23 +9685,29 @@ } } }, - "@cspotcode/source-map-consumer": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", - "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", - "dev": true, - "optional": true - }, "@cspotcode/source-map-support": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", - "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, - "optional": true, "requires": { - "@cspotcode/source-map-consumer": "0.8.0" + "@jridgewell/trace-mapping": "0.3.9" } }, + "@esbuild/android-arm": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz", + "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz", + "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==", + "dev": true, + "optional": true + }, "@eslint/eslintrc": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", @@ -8581,6 +10055,120 @@ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.3.0.tgz", "integrity": "sha512-CX6t4SYQ37lzxicAqsBtxA3OseeoVrh9cSJ5PFYam0GksYlupRfy1A+Q4aYD3zvcfECLc0zO2u+ZnR2UYKvCrw==" }, + "@swc/cli": { + "version": "0.1.57", + "resolved": "https://registry.npmjs.org/@swc/cli/-/cli-0.1.57.tgz", + "integrity": "sha512-HxM8TqYHhAg+zp7+RdTU69bnkl4MWdt1ygyp6BDIPjTiaJVH6Dizn2ezbgDS8mnFZI1FyhKvxU/bbaUs8XhzQg==", + "dev": true, + "requires": { + "commander": "^7.1.0", + "fast-glob": "^3.2.5", + "slash": "3.0.0", + "source-map": "^0.7.3" + }, + "dependencies": { + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true + }, + "source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true + } + } + }, + "@swc/core": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.27.tgz", + "integrity": "sha512-praRNgpeYGvwDIm/Cl6JU+yHMvwVraL0U6ejMgGyzvpcm1FVsZd1/EYXGqzbBJ0ALv7Gx4eK56h4GnwV6d4L0w==", + "dev": true, + "requires": { + "@swc/core-darwin-arm64": "1.3.27", + "@swc/core-darwin-x64": "1.3.27", + "@swc/core-linux-arm-gnueabihf": "1.3.27", + "@swc/core-linux-arm64-gnu": "1.3.27", + "@swc/core-linux-arm64-musl": "1.3.27", + "@swc/core-linux-x64-gnu": "1.3.27", + "@swc/core-linux-x64-musl": "1.3.27", + "@swc/core-win32-arm64-msvc": "1.3.27", + "@swc/core-win32-ia32-msvc": "1.3.27", + "@swc/core-win32-x64-msvc": "1.3.27" + } + }, + "@swc/core-darwin-arm64": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.27.tgz", + "integrity": "sha512-IKlxkhEy99CnP9nduaf5IJWIFcr6D5cZCjYmCs7nWkjMV+aAieyDO9AX4LT8AcHy6CF7ByOX7SKoqk+gVMAaKw==", + "dev": true, + "optional": true + }, + "@swc/core-darwin-x64": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.27.tgz", + "integrity": "sha512-MtabZIhFf/dL3vs6UMbd+vJsjIkm2NaFqulGV0Jofy2bfVZPTj/b5pXeOlUsTWy7JcH1uixjdx4RvJRyvqJxQA==", + "dev": true, + "optional": true + }, + "@swc/core-linux-arm-gnueabihf": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.27.tgz", + "integrity": "sha512-XELMoGcUTAkk+G4buwIIhu6AIr1U418Odt22HUW8+ZvV+Wty2ICgR/myOIhM3xMb6U2L8ay+evMqoVNMQ0RRTg==", + "dev": true, + "optional": true + }, + "@swc/core-linux-arm64-gnu": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.27.tgz", + "integrity": "sha512-O6vtT6bnrVR9PzEIuA5U7tIfYo7bv97H9K9Vqy2oyHNeGN0H36DKwS4UqPreHtziXNF5+7ubdUYUkrG/j8UnUQ==", + "dev": true, + "optional": true + }, + "@swc/core-linux-arm64-musl": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.27.tgz", + "integrity": "sha512-Oa0E1i7dOTWpaEZumKoNbTE/Ap+da6nlhqKVUdYrFDrOBi25tz76SdxZIyvAszzmgY89b5yd1naourKmkPXpww==", + "dev": true, + "optional": true + }, + "@swc/core-linux-x64-gnu": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.27.tgz", + "integrity": "sha512-S3v9H8oL2a8Ur6AjQyhkC6HfBVPOxKMdBhcZmdNuVgEUHbHdbf/Lka85F9IOYXEarMn0FtQw3ywowS22O9L5Uw==", + "dev": true, + "optional": true + }, + "@swc/core-linux-x64-musl": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.27.tgz", + "integrity": "sha512-6DDkdXlOADpwICFZTRphCR+cIeS8aEYh4NlyzBito0mOWwIIdfCgALzhkTQOzTOkcD42bP97CIoZ97hqV/puOg==", + "dev": true, + "optional": true + }, + "@swc/core-win32-arm64-msvc": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.27.tgz", + "integrity": "sha512-baxfH4AbEcaTNo08wxV0W6hiMXwVCxPS4qc0amHpXPti92unvSqeDR1W3C9GjHqzXlWtmCRsq8Ww1pal6ZVLrw==", + "dev": true, + "optional": true + }, + "@swc/core-win32-ia32-msvc": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.27.tgz", + "integrity": "sha512-7iLJnH71k5qCwxv9NcM/P7nIEzTsC7r1sIiQW6bu+CpC8qZvwl0PS+XvQRlLly2gCZM+Le98tksYG14MEh+Hrw==", + "dev": true, + "optional": true + }, + "@swc/core-win32-x64-msvc": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.27.tgz", + "integrity": "sha512-mFM907PDw/jrQ44+TRjIVGEOy2Mu06mMMz0HPMFuRsBzl5t0Kajp3vmn8FkkpS9wH5982VPi6hPYVTb7QJo5Qg==", + "dev": true, + "optional": true + }, "@szmarczak/http-timer": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", @@ -8593,29 +10181,37 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", - "dev": true, - "optional": true + "dev": true }, "@tsconfig/node12": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", - "dev": true, - "optional": true + "dev": true }, "@tsconfig/node14": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", - "dev": true, - "optional": true + "dev": true }, "@tsconfig/node16": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", - "dev": true, - "optional": true + "dev": true + }, + "@types/bytes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/bytes/-/bytes-3.1.1.tgz", + "integrity": "sha512-lOGyCnw+2JVPKU3wIV0srU0NyALwTBJlVSx5DfMQOFuuohA8y9S8orImpuIQikZ0uIQ8gehrRjxgQC1rLRi11w==", + "dev": true + }, + "@types/callsite": { + "version": "1.0.31", + "resolved": "https://registry.npmjs.org/@types/callsite/-/callsite-1.0.31.tgz", + "integrity": "sha512-jrKmIHhuZVGUpOR1s4TgY9BTt/Eh9CFCjHVZ2FsrKmHSo3J/vpl6EpK08SfMLrX2IY1ZEFA+BPRTJQGg4xIHsA==", + "dev": true }, "@types/chai": { "version": "4.3.4", @@ -8623,6 +10219,15 @@ "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", "dev": true }, + "@types/debug": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", + "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", + "dev": true, + "requires": { + "@types/ms": "*" + } + }, "@types/http-cache-semantics": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", @@ -8655,12 +10260,32 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "@types/kind-of": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@types/kind-of/-/kind-of-6.0.0.tgz", + "integrity": "sha512-OBts6MHCrq558cvND5nsWhoThwJaNu5lmGnSp3H0gFzQQc5QYM9p7HajIdS+2bgDquGX1qLZCPlyuYSxMDffAg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/lodash": { + "version": "4.14.191", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz", + "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==", + "dev": true + }, + "@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", + "dev": true + }, "@types/node": { "version": "17.0.29", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.29.tgz", "integrity": "sha512-tx5jMmMFwx7wBwq/V7OohKDVb/JwJU5qCVkeLMh1//xycAJ/ESuw9aJ9SEtlCZDYi2pBfe4JkisSoAtbOsBNAA==", - "dev": true, - "optional": true + "dev": true }, "@types/normalize-package-data": { "version": "2.4.1", @@ -8675,12 +10300,177 @@ "dev": true, "optional": true }, + "@types/pluralize": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/pluralize/-/pluralize-0.0.29.tgz", + "integrity": "sha512-BYOID+l2Aco2nBik+iYS4SZX0Lf20KPILP5RGmM1IgzdwNdTs0eebiFriOPcej1sX9mLnSoiNte5zcFxssgpGA==", + "dev": true + }, + "@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true + }, + "@types/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-kr90f+ERiQtKWMz5rP32ltJ/BtULDI5RVO0uavn1HQUOwjx0R1h0rnDYNL0CepF1zL5bSY6FISAfd9tOdDhU5Q==", + "dev": true + }, "@types/yargs-parser": { "version": "21.0.0", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", "dev": true }, + "@typescript-eslint/eslint-plugin": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.48.2.tgz", + "integrity": "sha512-sR0Gja9Ky1teIq4qJOl0nC+Tk64/uYdX+mi+5iB//MH8gwyx8e3SOyhEzeLZEFEEfCaLf8KJq+Bd/6je1t+CAg==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.48.2", + "@typescript-eslint/type-utils": "5.48.2", + "@typescript-eslint/utils": "5.48.2", + "debug": "^4.3.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "dependencies": { + "semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.48.2.tgz", + "integrity": "sha512-38zMsKsG2sIuM5Oi/olurGwYJXzmtdsHhn5mI/pQogP+BjYVkK5iRazCQ8RGS0V+YLk282uWElN70zAAUmaYHw==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.48.2", + "@typescript-eslint/types": "5.48.2", + "@typescript-eslint/typescript-estree": "5.48.2", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.48.2.tgz", + "integrity": "sha512-zEUFfonQid5KRDKoI3O+uP1GnrFd4tIHlvs+sTJXiWuypUWMuDaottkJuR612wQfOkjYbsaskSIURV9xo4f+Fw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.48.2", + "@typescript-eslint/visitor-keys": "5.48.2" + } + }, + "@typescript-eslint/type-utils": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.48.2.tgz", + "integrity": "sha512-QVWx7J5sPMRiOMJp5dYshPxABRoZV1xbRirqSk8yuIIsu0nvMTZesKErEA3Oix1k+uvsk8Cs8TGJ6kQ0ndAcew==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "5.48.2", + "@typescript-eslint/utils": "5.48.2", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/types": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.2.tgz", + "integrity": "sha512-hE7dA77xxu7ByBc6KCzikgfRyBCTst6dZQpwaTy25iMYOnbNljDT4hjhrGEJJ0QoMjrfqrx+j1l1B9/LtKeuqA==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.48.2.tgz", + "integrity": "sha512-bibvD3z6ilnoVxUBFEgkO0k0aFvUc4Cttt0dAreEr+nrAHhWzkO83PEVVuieK3DqcgL6VAK5dkzK8XUVja5Zcg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.48.2", + "@typescript-eslint/visitor-keys": "5.48.2", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "dependencies": { + "semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/utils": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.48.2.tgz", + "integrity": "sha512-2h18c0d7jgkw6tdKTlNaM7wyopbLRBiit8oAxoP89YnuBOzCZ8g8aBCaCqq7h208qUTroL7Whgzam7UY3HVLow==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.48.2", + "@typescript-eslint/types": "5.48.2", + "@typescript-eslint/typescript-estree": "5.48.2", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" + }, + "dependencies": { + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.48.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.2.tgz", + "integrity": "sha512-z9njZLSkwmjFWUelGEwEbdf4NwKvfHxvGC0OcGN1Hp/XNDIcJ7D5DpPNPv6x6/mFvc1tQHsaWmpD/a4gOvvCJQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.48.2", + "eslint-visitor-keys": "^3.3.0" + } + }, "abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -8784,6 +10574,22 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, "api-contract-validator": { "version": "2.2.8", "resolved": "https://registry.npmjs.org/api-contract-validator/-/api-contract-validator-2.2.8.tgz", @@ -8968,8 +10774,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, - "optional": true + "dev": true }, "argparse": { "version": "2.0.1", @@ -8990,6 +10795,12 @@ "is-string": "^1.0.7" } }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, "array.prototype.flat": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", @@ -9080,6 +10891,12 @@ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, "bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -9138,6 +10955,15 @@ } } }, + "bundle-require": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-3.1.2.tgz", + "integrity": "sha512-Of6l6JBAxiyQ5axFxUM6dYeP/W7X2Sozeo/4EYB9sJhL+dqL7TKjg+shwxp6jlu/6ZSERfsYtIpSJ1/x3XkAEA==", + "dev": true, + "requires": { + "load-tsconfig": "^0.2.0" + } + }, "bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -9203,6 +11029,12 @@ } } }, + "cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true + }, "cacheable-lookup": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", @@ -9364,6 +11196,33 @@ "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", "dev": true }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, "ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", @@ -9628,8 +11487,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true, - "optional": true + "dev": true }, "cross-env": { "version": "7.0.3", @@ -9831,8 +11689,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "optional": true + "dev": true }, "diff-sequences": { "version": "29.3.1", @@ -9840,6 +11697,15 @@ "integrity": "sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==", "dev": true }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -9966,6 +11832,176 @@ "is-symbol": "^1.0.2" } }, + "esbuild": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", + "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.15.18", + "@esbuild/linux-loong64": "0.15.18", + "esbuild-android-64": "0.15.18", + "esbuild-android-arm64": "0.15.18", + "esbuild-darwin-64": "0.15.18", + "esbuild-darwin-arm64": "0.15.18", + "esbuild-freebsd-64": "0.15.18", + "esbuild-freebsd-arm64": "0.15.18", + "esbuild-linux-32": "0.15.18", + "esbuild-linux-64": "0.15.18", + "esbuild-linux-arm": "0.15.18", + "esbuild-linux-arm64": "0.15.18", + "esbuild-linux-mips64le": "0.15.18", + "esbuild-linux-ppc64le": "0.15.18", + "esbuild-linux-riscv64": "0.15.18", + "esbuild-linux-s390x": "0.15.18", + "esbuild-netbsd-64": "0.15.18", + "esbuild-openbsd-64": "0.15.18", + "esbuild-sunos-64": "0.15.18", + "esbuild-windows-32": "0.15.18", + "esbuild-windows-64": "0.15.18", + "esbuild-windows-arm64": "0.15.18" + } + }, + "esbuild-android-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz", + "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==", + "dev": true, + "optional": true + }, + "esbuild-android-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz", + "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==", + "dev": true, + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz", + "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==", + "dev": true, + "optional": true + }, + "esbuild-darwin-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz", + "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz", + "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz", + "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==", + "dev": true, + "optional": true + }, + "esbuild-linux-32": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz", + "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==", + "dev": true, + "optional": true + }, + "esbuild-linux-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz", + "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz", + "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz", + "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==", + "dev": true, + "optional": true + }, + "esbuild-linux-mips64le": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz", + "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-ppc64le": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz", + "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==", + "dev": true, + "optional": true + }, + "esbuild-linux-riscv64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz", + "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==", + "dev": true, + "optional": true + }, + "esbuild-linux-s390x": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz", + "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==", + "dev": true, + "optional": true + }, + "esbuild-netbsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz", + "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==", + "dev": true, + "optional": true + }, + "esbuild-openbsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz", + "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==", + "dev": true, + "optional": true + }, + "esbuild-sunos-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz", + "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==", + "dev": true, + "optional": true + }, + "esbuild-windows-32": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz", + "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==", + "dev": true, + "optional": true + }, + "esbuild-windows-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz", + "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==", + "dev": true, + "optional": true + }, + "esbuild-windows-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", + "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", + "dev": true, + "optional": true + }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -10766,6 +12802,13 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -10960,6 +13003,20 @@ "define-properties": "^1.1.3" } }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, "gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -11432,6 +13489,15 @@ "has-bigints": "^1.0.1" } }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, "is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", @@ -11765,6 +13831,12 @@ "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", "dev": true }, + "joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true + }, "js-sdsl": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.2.0.tgz", @@ -12037,6 +14109,12 @@ } } }, + "load-tsconfig": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.3.tgz", + "integrity": "sha512-iyT2MXws+dc2Wi6o3grCFtGXpeMvHmJqS27sMPGtV2eUu4PeFnG+33I8BlFK1t1NWMjOpcx9bridn5yxLDX2gQ==", + "dev": true + }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -12087,6 +14165,12 @@ "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=", "dev": true }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true + }, "log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -12253,8 +14337,7 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true, - "optional": true + "dev": true }, "md5": { "version": "2.2.1", @@ -12355,12 +14438,29 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -12424,6 +14524,12 @@ } } }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true + }, "object-inspect": { "version": "1.12.3", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", @@ -12705,8 +14811,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "optional": true + "dev": true }, "pathval": { "version": "1.1.1", @@ -12780,6 +14885,12 @@ "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.0.0.tgz", "integrity": "sha512-mMMOwSKrmyl+Y12Ri2xhH1lbzQxwwpuru9VjyJpgFIH4asSj88F2csdMwN6+M5g1Ll4rmsYghHLQJw81tgZ7LQ==" }, + "pirates": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "dev": true + }, "pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -12848,6 +14959,16 @@ "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==" }, + "postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dev": true, + "requires": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + } + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -12986,6 +15107,15 @@ "util-deprecate": "^1.0.1" } }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, "real-require": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", @@ -13049,8 +15179,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "optional": true + "dev": true }, "resolve-global": { "version": "1.0.0", @@ -13110,6 +15239,15 @@ "glob": "^7.1.3" } }, + "rollup": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.10.0.tgz", + "integrity": "sha512-JmRYz44NjC1MjVF2VKxc0M1a97vn+cDxeqWmnwyAF4FvpjK8YFdHpaqvQB+3IxCvX05vJxKZkoMDU8TShhmJVA==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, "run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", @@ -13449,6 +15587,61 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, + "sucrase": { + "version": "3.29.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.29.0.tgz", + "integrity": "sha512-bZPAuGA5SdFHuzqIhTAqt9fvNEo9rESqXIG3oiKdF8K4UmkQxC4KlNL3lVyAErXp+mPvUqZ5l13qx6TrDIGf3A==", + "dev": true, + "requires": { + "commander": "^4.0.0", + "glob": "7.1.6", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -13569,6 +15762,24 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, "thread-stream": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.2.0.tgz", @@ -13615,20 +15826,40 @@ "is-number": "^7.0.0" } }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, "traverse": { "version": "0.6.6", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", "dev": true }, + "tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true + }, + "ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true + }, "ts-node": { - "version": "10.7.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz", - "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==", + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, - "optional": true, "requires": { - "@cspotcode/source-map-support": "0.7.0", + "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", @@ -13639,7 +15870,7 @@ "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.0", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "dependencies": { @@ -13647,8 +15878,7 @@ "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, - "optional": true + "dev": true } } }, @@ -13677,6 +15907,94 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, + "tsup": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/tsup/-/tsup-6.5.0.tgz", + "integrity": "sha512-36u82r7rYqRHFkD15R20Cd4ercPkbYmuvRkz3Q1LCm5BsiFNUgpo36zbjVhCOgvjyxNBWNKHsaD5Rl8SykfzNA==", + "dev": true, + "requires": { + "bundle-require": "^3.1.2", + "cac": "^6.7.12", + "chokidar": "^3.5.1", + "debug": "^4.3.1", + "esbuild": "^0.15.1", + "execa": "^5.0.0", + "globby": "^11.0.3", + "joycon": "^3.0.1", + "postcss-load-config": "^3.0.1", + "resolve-from": "^5.0.0", + "rollup": "^3.2.5", + "source-map": "0.8.0-beta.0", + "sucrase": "^3.20.3", + "tree-kill": "^1.2.2" + }, + "dependencies": { + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dev": true, + "requires": { + "whatwg-url": "^7.0.0" + } + } + } + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -13772,8 +16090,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true, - "optional": true + "dev": true }, "v8-to-istanbul": { "version": "9.0.0", @@ -13822,6 +16139,23 @@ "defaults": "^1.0.3" } }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -13922,8 +16256,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "optional": true + "dev": true }, "yocto-queue": { "version": "0.1.0", diff --git a/package.json b/package.json index 6d02eef..1d72f13 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@athenna/common", - "version": "3.1.0", + "version": "3.2.0", "description": "The Athenna common helpers to use in any Node.js ESM project.", "license": "MIT", "author": "João Lenon ", @@ -17,17 +17,17 @@ "standalone" ], "scripts": { - "lint:fix": "eslint \"{src,tests}/**/*.js\" --fix", - "test": "npm run --silent lint:fix && node ./tests/index.js", - "test:debug": "cross-env DEBUG=api:* && npm run --silent test", - "test:coverage": "c8 npm run --silent test", - "gen:types": "tsc src/*.js --declaration --allowJs --emitDeclarationOnly --out src/index.js" + "build": "rimraf build && tsup", + "lint:fix": "eslint \"{src,tests}/**/*.ts\" --fix", + "test": "npm run --silent lint:fix && ts-node ./bin/test.ts", + "test:debug": "cross-env DEBUG=api:* ts-node ./bin/test.ts --inspect", + "test:coverage": "c8 npm run --silent test" }, "files": [ - "src/*.js", - "src/*.d.ts", - "src/**/*.js", - "src/**/*.d.ts", + "build/*.js", + "build/*.d.ts", + "build/**/*.js", + "build/**/*.d.ts", "templates/**" ], "type": "module", @@ -37,8 +37,14 @@ ".": "./src/index.js" }, "imports": { - "#src/*": "./src/*.js", - "#tests/*": "./tests/*.js" + "#src/*": [ + "./src/*.ts", + "./src/*.js" + ], + "#tests/*": [ + "./tests/*.ts", + "./tests/*.js" + ] }, "dependencies": { "@fastify/formbody": "^7.4.0", @@ -70,6 +76,18 @@ "@japa/run-failed-tests": "^1.1.0", "@japa/runner": "^2.2.2", "@japa/spec-reporter": "^1.3.2", + "@swc/cli": "^0.1.57", + "@swc/core": "^1.3.27", + "@types/bytes": "^3.1.1", + "@types/callsite": "^1.0.31", + "@types/debug": "^4.1.7", + "@types/kind-of": "^6.0.0", + "@types/lodash": "^4.14.191", + "@types/ms": "^0.7.31", + "@types/pluralize": "^0.0.29", + "@types/uuid": "^9.0.0", + "@typescript-eslint/eslint-plugin": "^5.48.1", + "@typescript-eslint/parser": "^5.48.1", "c8": "^7.12.0", "commitizen": "^4.2.6", "cross-env": "^7.0.3", @@ -86,12 +104,14 @@ "minimist": "^1.2.7", "prettier": "^2.8.3", "rimraf": "^3.0.2", + "ts-node": "^10.9.1", + "tsup": "^6.5.0", "typescript": "^4.9.4" }, "c8": { "all": true, "include": [ - "src/**/*.js" + "src/**/*.ts" ], "exclude": [], "reporter": [ @@ -137,34 +157,58 @@ } ] }, + "eslintIgnore": [ + "build/**/*" + ], "eslintConfig": { "env": { "es2021": true, "node": true }, "globals": { - "Path": true + "ioc": true, + "Env": true, + "Path": true, + "Config": true }, "plugins": [ - "prettier" + "prettier", + "@typescript-eslint" ], "extends": [ "standard", "eslint:recommended", - "plugin:prettier/recommended" - ], - "ignorePatterns": [ - "**/*.d.ts" + "plugin:prettier/recommended", + "plugin:@typescript-eslint/recommended", + "plugin:@typescript-eslint/eslint-recommended" ], - "parserOptions": { - "ecmaVersion": "latest", - "sourceType": "module" - }, + "parser": "@typescript-eslint/parser", "rules": { "camelcase": "off", "dot-notation": "off", "prettier/prettier": "error", - "no-useless-constructor": "off" + "no-useless-constructor": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/no-unused-vars": [ + "error", + { + "argsIgnorePattern": "^_", + "varsIgnorePattern": "^_", + "caughtErrorsIgnorePattern": "^_" + } + ] } + }, + "tsup": { + "entry": [ + "src" + ], + "dts": true, + "clean": true, + "format": "esm", + "outDir": "build", + "sourcemap": false, + "splitting": false } } diff --git a/src/Exceptions/InvalidNumberException.js b/src/Exceptions/InvalidNumberException.js deleted file mode 100644 index d464f9c..0000000 --- a/src/Exceptions/InvalidNumberException.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @athenna/common - * - * (c) João Lenon - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -import { Exception } from '#src/Helpers/Exception' - -export class InvalidNumberException extends Exception { - /** - * Creates a new instance of InvalidNumberException. - * - * @param {string} number - * @return {InvalidNumberException} - */ - constructor(number) { - const content = `The number ${number} is not a valid string number.` - - super( - content, - 500, - 'E_INVALID_NUMBER', - 'Use a valid string number instead.', - ) - } -} diff --git a/src/Exceptions/InvalidNumberException.ts b/src/Exceptions/InvalidNumberException.ts new file mode 100644 index 0000000..85ac4ff --- /dev/null +++ b/src/Exceptions/InvalidNumberException.ts @@ -0,0 +1,20 @@ +/** + * @athenna/common + * + * (c) João Lenon + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import { Exception } from '#src/Helpers/Exception' + +export class InvalidNumberException extends Exception { + constructor(number: string) { + super({ + code: 'E_INVALID_NUMBER', + help: 'Use a valid string number instead.', + message: `The number ${number} is not a valid string number.`, + }) + } +} diff --git a/src/Exceptions/InvalidUuidException.js b/src/Exceptions/InvalidUuidException.ts similarity index 51% rename from src/Exceptions/InvalidUuidException.js rename to src/Exceptions/InvalidUuidException.ts index 05c50dc..7665e49 100644 --- a/src/Exceptions/InvalidUuidException.js +++ b/src/Exceptions/InvalidUuidException.ts @@ -10,15 +10,11 @@ import { Exception } from '#src/Helpers/Exception' export class InvalidUuidException extends Exception { - /** - * Creates a new instance of InvalidUuidException. - * - * @param {string} value - * @return {InvalidUuidException} - */ - constructor(value) { - const content = `The value ${value} is not a valid uuid.` - - super(content, 500, 'E_INVALID_UUID', 'Use a valid uuid instead.') + constructor(value: string) { + super({ + code: 'E_INVALID_UUID', + help: 'Use a valid uuid instead.', + message: `The value ${value} is not a valid uuid.`, + }) } } diff --git a/src/Exceptions/NodeCommandException.js b/src/Exceptions/NodeCommandException.ts similarity index 66% rename from src/Exceptions/NodeCommandException.js rename to src/Exceptions/NodeCommandException.ts index 101420c..4e9624a 100644 --- a/src/Exceptions/NodeCommandException.js +++ b/src/Exceptions/NodeCommandException.ts @@ -10,16 +10,7 @@ import { Exception } from '#src/Helpers/Exception' export class NodeCommandException extends Exception { - /** - * Creates a new instance of NodeCommandException. - * - * @param {string} command - * @param {any} error - * @return {NodeCommandException} - */ - constructor(command, error) { - const content = `Error has occurred when executing the command "${command}"` - + constructor(command: string, error: any) { let help = '' if (error.stdout) { @@ -34,6 +25,10 @@ export class NodeCommandException extends Exception { help = `Command error:\n\n${JSON.stringify(error)}\n\n` } - super(content, 500, 'E_NODE_EXEC', help) + super({ + help, + code: 'E_NODE_EXEC', + message: `Error has occurred when executing the command "${command}"`, + }) } } diff --git a/src/Exceptions/NotFoundFileException.js b/src/Exceptions/NotFoundFileException.js deleted file mode 100644 index bd0c81b..0000000 --- a/src/Exceptions/NotFoundFileException.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @athenna/common - * - * (c) João Lenon - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -import { Exception } from '#src/Helpers/Exception' - -export class NotFoundFileException extends Exception { - /** - * Creates a new instance of NotFoundFileException. - * - * @param {string} filePath - * @return {NotFoundFileException} - */ - constructor(filePath) { - const content = `The file ${filePath} doesnt exist.` - - super( - content, - 500, - 'E_NOT_FOUND_FILE', - 'Try using File.create method to create the file.', - ) - } -} diff --git a/src/Exceptions/NotFoundFileException.ts b/src/Exceptions/NotFoundFileException.ts new file mode 100644 index 0000000..a124e2f --- /dev/null +++ b/src/Exceptions/NotFoundFileException.ts @@ -0,0 +1,20 @@ +/** + * @athenna/common + * + * (c) João Lenon + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import { Exception } from '#src/Helpers/Exception' + +export class NotFoundFileException extends Exception { + constructor(filePath: string) { + super({ + code: 'E_NOT_FOUND_FILE', + message: `The file ${filePath} doesnt exist.`, + help: 'Try using File.create method to create the file.', + }) + } +} diff --git a/src/Exceptions/NotFoundFolderException.js b/src/Exceptions/NotFoundFolderException.js deleted file mode 100644 index d87eee8..0000000 --- a/src/Exceptions/NotFoundFolderException.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @athenna/common - * - * (c) João Lenon - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -import { Exception } from '#src/Helpers/Exception' - -export class NotFoundFolderException extends Exception { - /** - * Creates a new instance of NotFoundFolderException. - * - * @param {string} filePath - * @return {NotFoundFolderException} - */ - constructor(filePath) { - const content = `The folder ${filePath} doesnt exist.` - - super( - content, - 500, - 'E_NOT_FOUND_FILE', - 'Try using Folder.create method to create the folder.', - ) - } -} diff --git a/src/Exceptions/NotFoundFolderException.ts b/src/Exceptions/NotFoundFolderException.ts new file mode 100644 index 0000000..22d8322 --- /dev/null +++ b/src/Exceptions/NotFoundFolderException.ts @@ -0,0 +1,20 @@ +/** + * @athenna/common + * + * (c) João Lenon + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import { Exception } from '#src/Helpers/Exception' + +export class NotFoundFolderException extends Exception { + constructor(filePath: string) { + super({ + code: 'E_NOT_FOUND_FILE', + message: `The folder ${filePath} doesnt exist.`, + help: 'Try using Folder.create method to create the folder.', + }) + } +} diff --git a/src/Exceptions/OrdinalNanException.js b/src/Exceptions/OrdinalNanException.ts similarity index 53% rename from src/Exceptions/OrdinalNanException.js rename to src/Exceptions/OrdinalNanException.ts index 9d00145..6a2ca59 100644 --- a/src/Exceptions/OrdinalNanException.js +++ b/src/Exceptions/OrdinalNanException.ts @@ -10,19 +10,11 @@ import { Exception } from '#src/Helpers/Exception' export class OrdinalNanException extends Exception { - /** - * Creates a new instance of OrdinalNanException. - * - * @return {OrdinalNanException} - */ constructor() { - const content = 'Cannot ordinal NaN or infinite numbers.' - - super( - content, - 500, - 'E_ORDINAL_NAN', - 'Use a valid number instead of NaN or infinite.', - ) + super({ + code: 'E_ORDINAL_NAN', + message: 'Cannot ordinal NaN or infinite numbers.', + help: 'Use a valid number instead of NaN or infinite.', + }) } } diff --git a/src/Exceptions/RouteMatchException.js b/src/Exceptions/RouteMatchException.js deleted file mode 100644 index e7d3339..0000000 --- a/src/Exceptions/RouteMatchException.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @athenna/common - * - * (c) João Lenon - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -import { Exception } from '#src/Helpers/Exception' - -export class RouteMatchException extends Exception { - /** - * Creates a new instance of RouteMatchException. - * - * @param {string} routeWithParams - * @param {string} routeWithValues - * @return {RouteMatchException} - */ - constructor(routeWithParams, routeWithValues) { - const content = `The route ${routeWithParams} does not match ${routeWithValues}` - - super( - content, - 500, - 'E_ROUTE_MATCH', - 'Please open an issue in https://github.com/SecJS/Utils.git', - ) - } -} diff --git a/src/Exceptions/RouteMatchException.ts b/src/Exceptions/RouteMatchException.ts new file mode 100644 index 0000000..45d1248 --- /dev/null +++ b/src/Exceptions/RouteMatchException.ts @@ -0,0 +1,20 @@ +/** + * @athenna/common + * + * (c) João Lenon + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import { Exception } from '#src/Helpers/Exception' + +export class RouteMatchException extends Exception { + constructor(routeWithParams: string, routeWithValues: string) { + super({ + code: 'E_ROUTE_MATCH', + message: `The route ${routeWithParams} does not match ${routeWithValues}`, + help: 'Please open an issue in https://github.com/AthennaIO/Common/issues', + }) + } +} diff --git a/src/Globals/Array.ts b/src/Globals/Array.ts new file mode 100644 index 0000000..ab3b231 --- /dev/null +++ b/src/Globals/Array.ts @@ -0,0 +1,37 @@ +/** + * @athenna/common + * + * (c) João Lenon + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import { Collection } from '#src/Helpers/Collection' + +export {} + +declare global { + interface Array { + /** + * Call the toResource method of each item + * inside the array. + */ + toResource(criterias?: any): T[] + + /** + * Transform the array to an Athenna collection. + */ + toCollection(): Collection + } +} + +// eslint-disable-next-line no-extend-native +Array.prototype.toResource = function (criterias = {}) { + return this.map(model => model.toResource(criterias)) +} + +// eslint-disable-next-line no-extend-native +Array.prototype.toCollection = function () { + return new Collection(this) +} diff --git a/src/Globals/Error.ts b/src/Globals/Error.ts new file mode 100644 index 0000000..19a5a29 --- /dev/null +++ b/src/Globals/Error.ts @@ -0,0 +1,31 @@ +/** + * @athenna/common + * + * (c) João Lenon + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import { Exception, ExceptionJSON } from '#src/Helpers/Exception' + +export {} + +declare global { + interface Error { + /** + * Transform your error to an instance of + * the Athenna exception. + */ + toAthennaException(options?: ExceptionJSON): Exception + } +} + +// eslint-disable-next-line no-extend-native +Error.prototype.toAthennaException = function (options: ExceptionJSON = {}) { + options.name = options.name || this.name + options.stack = options.stack || this.stack + options.message = options.message || this.message + + return new Exception(options) +} diff --git a/src/Globals/Path.ts b/src/Globals/Path.ts new file mode 100644 index 0000000..b293855 --- /dev/null +++ b/src/Globals/Path.ts @@ -0,0 +1,22 @@ +/** + * @athenna/common + * + * (c) João Lenon + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import { Path as PathImpl } from '#src/Helpers/Path' + +export {} + +declare global { + export class Path extends PathImpl {} +} + +const __global: any = global + +if (!__global.Path) { + __global.Path = PathImpl +} diff --git a/src/Helpers/Clean.js b/src/Helpers/Clean.ts similarity index 73% rename from src/Helpers/Clean.js rename to src/Helpers/Clean.ts index 0fd265d..030bb94 100644 --- a/src/Helpers/Clean.js +++ b/src/Helpers/Clean.ts @@ -12,13 +12,12 @@ import { Is } from '#src/Helpers/Is' export class Clean { /** * Remove all falsy values from array. - * - * @param {any[]} array - * @param {boolean} [removeEmpty] - * @param {boolean} [cleanInsideObjects] - * @return {any[]} */ - static cleanArray(array, removeEmpty = false, cleanInsideObjects = false) { + public static cleanArray( + array: any[], + removeEmpty = false, + cleanInsideObjects = false, + ): any[] { return array.filter((item, i) => { let returnItem = !!item @@ -45,13 +44,12 @@ export class Clean { /** * Remove all falsy values from object. - * - * @param {any} object - * @param {boolean} [removeEmpty] - * @param {boolean} [cleanInsideArrays] - * @return {any} */ - static cleanObject(object, removeEmpty = false, cleanInsideArrays = false) { + public static cleanObject( + object: any, + removeEmpty = false, + cleanInsideArrays = false, + ): any { Object.keys(object).forEach(prop => { if (removeEmpty && Is.Empty(object[prop])) { delete object[prop] diff --git a/src/Helpers/Collection.js b/src/Helpers/Collection.ts similarity index 63% rename from src/Helpers/Collection.js rename to src/Helpers/Collection.ts index b69ae48..9ac93c7 100644 --- a/src/Helpers/Collection.js +++ b/src/Helpers/Collection.ts @@ -9,49 +9,36 @@ import { Collection as CollectJS } from 'collect.js' -export class Collection extends CollectJS { +export class Collection extends CollectJS { /** * An alias for macro instance method: * * @example - * new Collection().macro() - * @param {string} name - * @param {Function} fn + * Collection.macro('upperAndTrim', (value) => { + * return value.trim().toUpperCase() + * }) */ - static macro(name, fn) { + public static macro(name: string, fn: any): void { return new Collection().macro(name, fn) } /** * Remove all duplicated values from the array. - * - * @return {any[]} */ - removeDuplicated() { + public removeDuplicated(): T[] { return [...new Set(this.all())] } /** * Execute the toResource method inside objects if exists. - * - * @param {any} [criterias] - * @return {any[]} */ - toResource(criterias = {}) { + public toResource(criterias = {}): T[] { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore return this.all().map(item => item.toResource(criterias)) } } -// eslint-disable-next-line no-extend-native -Array.prototype.toResource = function (criterias = {}) { - return this.map(model => model.toResource(criterias)) -} - -// eslint-disable-next-line no-extend-native -Array.prototype.toCollection = function () { - return new Collection(this) -} - Collection.prototype.order = Collection.prototype.sort Collection.prototype.orderBy = Collection.prototype.sortBy Collection.prototype.orderByDesc = Collection.prototype.sortByDesc diff --git a/src/Helpers/Debug.js b/src/Helpers/Debug.ts similarity index 73% rename from src/Helpers/Debug.js rename to src/Helpers/Debug.ts index 821060d..5810229 100644 --- a/src/Helpers/Debug.js +++ b/src/Helpers/Debug.ts @@ -15,12 +15,9 @@ import { Is } from '#src/Helpers/Is' export class Debug { /** * Get the timestamp ms. - * - * @private - * @return {string} */ - static #getTimestamp() { - const localeStringOptions = { + private static getTimestamp() { + const localeStringOptions: Intl.DateTimeFormatOptions = { year: 'numeric', hour: 'numeric', minute: 'numeric', @@ -34,17 +31,14 @@ export class Debug { /** * Format the message using Chalk API. - * - * @param {string} message - * @return {string} */ - static format(message) { + public static format(message: string) { if (Is.Object(message)) { message = JSON.stringify(message) } const pid = chalk.yellow(`PID: ${process.pid}`) - const timestamp = Debug.#getTimestamp() + const timestamp = Debug.getTimestamp() return `${chalk.yellow(`[Debug]`)} - ${pid} - ${timestamp} ${chalk.yellow( message, @@ -53,12 +47,8 @@ export class Debug { /** * Format and throw the message in the stdout accordingly to the namespace. - * - * @param {string|any} message - * @param {string} [namespace] - * @return {void} */ - static log(message, namespace = 'api:main') { + public static log(message: any, namespace = 'api:main'): void { debug(namespace)(Debug.format(message)) } } diff --git a/src/Helpers/Exception.js b/src/Helpers/Exception.js deleted file mode 100644 index 267c5fb..0000000 --- a/src/Helpers/Exception.js +++ /dev/null @@ -1,170 +0,0 @@ -/* eslint-disable no-extend-native */ -/** - * @athenna/common - * - * (c) João Lenon - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -import Youch from 'youch' -import chalk from 'chalk' -import changeCase from 'change-case' -import YouchTerminal from 'youch-terminal' - -import { Options } from '#src/Helpers/Options' - -export class Exception extends Error { - /** - * Creates a new instance of Exception. - * - * @param {string} [content] - * @param {number} [status] - * @param {string} [code] - * @param {string} [help] - * @return {Exception} - */ - constructor(content, status = 500, code, help) { - super(content) - - Object.defineProperty(this, 'name', { - configurable: true, - enumerable: false, - value: this.constructor.name, - writable: true, - }) - - Object.defineProperty(this, 'status', { - configurable: true, - enumerable: false, - value: status, - writable: true, - }) - - Object.defineProperty(this, 'code', { - configurable: true, - enumerable: false, - value: code || changeCase.constantCase(this.constructor.name), - writable: true, - }) - - Object.defineProperty(this, 'content', { - configurable: true, - enumerable: false, - value: content, - writable: true, - }) - - if (help) { - Object.defineProperty(this, 'help', { - configurable: true, - enumerable: false, - value: help, - writable: true, - }) - } - - Error.captureStackTrace(this, this.constructor) - } - - /** - * Transform the exception to a valid JSON Object. - * - * @param [stack] {boolean} - * @return {{ - * code: string, - * name: string, - * status: number, - * content: string, - * help?: string, - * stack?: string - * }} - */ - toJSON(stack = true) { - const json = {} - - json.code = this.code - json.name = this.name - json.status = this.status - json.content = this.content - - if (this.help) json.help = this.help - if (stack) json.stack = this.stack - - return json - } - - /** - * Prettify the error using Youch API. - * - * @param {any} [options] - * @param {string} [options.prefix] - * @param {boolean} [options.hideMessage] - * @param {boolean} [options.hideErrorTitle] - * @param {boolean} [options.displayShortPath] - * @param {boolean} [options.displayMainFrameOnly] - * @return {Promise} - */ - async prettify(options) { - options = Options.create(options, { - displayShortPath: false, - prefix: '', - hideErrorTitle: false, - hideMessage: false, - displayMainFrameOnly: false, - }) - - this.name = this.code - const helpKey = chalk.green.bold('HELP') - const messageKey = chalk.yellow.bold('MESSAGE') - - if (this.message && this.message !== '') { - this.message = `${messageKey}\n ${this.message}` - } - - if (this.help && this.help !== '') { - this.message = `${this.message}\n\n ${helpKey}\n ${this.help}` - } - - const pretty = await new Youch(this, {}).toJSON() - - if (!pretty.error.frames.find(frame => frame.isApp)) { - pretty.error.frames = pretty.error.frames.map(frame => { - frame.isApp = true - return frame - }) - } - - return YouchTerminal(pretty, options).concat('\n') - } -} - -/** - * Transform your error to an instance of - * the Athenna exception. - * - * @param options {{ - * code?: string, - * status?: number, - * content?: string, - * help?: string, - * stack?: any - * }} - * @return {Exception} - */ -Error.prototype.toAthennaException = function (options) { - const { content, status, code, help, stack } = Options.create(options, { - content: this.message, - status: 0, - code: this.name, - help: undefined, - stack: this.stack, - }) - - const exception = new Exception(content, status, code, help) - - exception.stack = stack - - return exception -} diff --git a/src/Helpers/Exception.ts b/src/Helpers/Exception.ts new file mode 100644 index 0000000..083ee27 --- /dev/null +++ b/src/Helpers/Exception.ts @@ -0,0 +1,120 @@ +/** + * @athenna/common + * + * (c) João Lenon + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import Youch from 'youch' +import chalk from 'chalk' +import changeCase from 'change-case' +import YouchTerminal from 'youch-terminal' + +import { Options } from '#src/Helpers/Options' + +export interface ExceptionJSON { + code?: string + name?: string + status?: number + message?: string + help?: any + stack?: string +} + +export class Exception extends Error { + public code?: string + public help?: any + public status?: number + + /** + * Creates a new instance of Exception. + */ + public constructor(options?: ExceptionJSON) { + super(options?.message || '') + + options = Options.create(options, { + message: '', + status: 500, + help: null, + stack: null, + name: this.constructor.name, + code: changeCase.constantCase(this.constructor.name), + }) + + this.name = options.name + this.code = options.code + this.status = options.status + this.message = options.message + + if (options.help) { + this.help = options.help + } + + if (options.stack) { + this.stack = options.stack + } else { + Exception.captureStackTrace(this, this.constructor) + } + } + + /** + * Transform the exception to a valid JSON Object. + */ + public toJSON(stack = true): ExceptionJSON { + const json: ExceptionJSON = {} + + json.code = this.code + json.name = this.name + json.status = this.status + json.message = this.message + + if (this.help) json.help = this.help + if (stack) json.stack = this.stack + + return json + } + + /** + * Prettify the error using Youch API. + */ + public async prettify(options?: { + prefix?: string + hideMessage?: boolean + hideErrorTitle?: boolean + displayShortPath?: boolean + displayMainFrameOnly?: boolean + }): Promise { + options = Options.create(options, { + displayShortPath: false, + prefix: '', + hideErrorTitle: false, + hideMessage: false, + displayMainFrameOnly: false, + }) + + this.name = this.code + const helpKey = chalk.green.bold('HELP') + const messageKey = chalk.yellow.bold('MESSAGE') + + if (this.message && this.message !== '') { + this.message = `${messageKey}\n ${this.message}` + } + + if (this.help && this.help !== '') { + this.message = `${this.message}\n\n ${helpKey}\n ${this.help}` + } + + const pretty = await new Youch(this, {}).toJSON() + + if (!pretty.error.frames.find(frame => frame.isApp)) { + pretty.error.frames = pretty.error.frames.map(frame => { + frame.isApp = true + return frame + }) + } + + return YouchTerminal(pretty, options).concat('\n') + } +} diff --git a/src/Helpers/Exec.js b/src/Helpers/Exec.ts similarity index 70% rename from src/Helpers/Exec.js rename to src/Helpers/Exec.ts index 6b25b64..ecfb71f 100644 --- a/src/Helpers/Exec.js +++ b/src/Helpers/Exec.ts @@ -9,47 +9,61 @@ import { promisify } from 'node:util' import { Transform } from 'node:stream' -import { request as requestHttp } from 'node:http' -import { request as requestHttps } from 'node:https' -import { exec as childProcessExec } from 'node:child_process' - import { File } from '#src/Helpers/File' import { Uuid } from '#src/Helpers/Uuid' import { Options } from '#src/Helpers/Options' +import { request as requestHttp } from 'node:http' +import { request as requestHttps } from 'node:https' +import { exec as childProcessExec, ExecOptions } from 'node:child_process' import { NodeCommandException } from '#src/Exceptions/NodeCommandException' const exec = promisify(childProcessExec) +export interface PaginationOptions { + page?: number + limit?: number + resourceUrl?: string +} + +export interface PaginatedResponse { + data?: T[] + meta?: { + totalItems: number + itemsPerPage: number + totalPages: number + currentPage: number + itemCount: number + } + links?: { + next: string + previous: string + last: string + first: string + } +} + export class Exec { /** * Sleep the code in the line that this function * is being called. - * - * @param {number} ms - * @return {Promise} */ - static async sleep(ms) { + public static async sleep(ms: number): Promise { return new Promise(resolve => setTimeout(resolve, ms)) } /** * Execute a command of child process exec as promise. - * - * @param {string} command - * @param {{ - * ignoreErrors?: boolean - * }} [options] - * @throws {NodeCommandException} - * @return {Promise<{ stdout: string, stderr: string }>} */ - static async command(command, options) { + public static async command( + command: string, + options?: { ignoreErrors?: boolean }, + ): Promise<{ stdout: string; stderr: string }> { options = Options.create(options, { - withContent: true, - mockedValues: false, + ignoreErrors: false, }) try { - const execOptions = {} + const execOptions: ExecOptions = {} if (process.platform === 'win32' && Uuid.verify(process.env.WT_SESSION)) { execOptions.shell = 'powershell' @@ -68,13 +82,12 @@ export class Exec { /** * Download an archive to determined path. - * - * @param {string} name - * @param {string} path - * @param {string} url - * @return {Promise} */ - static async download(name, path, url) { + public static async download( + name: string, + path: string, + url: string, + ): Promise { return new Promise((resolve, reject) => { const callback = response => { const data = new Transform() @@ -100,32 +113,18 @@ export class Exec { /** * Paginate a collection of data. - * - * @param {any[]} data - * @param {number} total - * @param {{ - * page?: number, - * limit?: number, - * resourceUrl?: string - * }} pagination - * @return {{ - * data: any[], - * meta: { - * totalItems: number, - * itemsPerPage: number, - * totalPages: number, - * currentPage: number, - * itemCount: number - * }, - * links: { - * next: string, - * previous: string, - * last: string, - * first: string - * } - * }} */ - static pagination(data, total, pagination) { + public static pagination( + data: any[], + total: number, + pagination?: PaginationOptions, + ): PaginatedResponse { + pagination = Options.create(pagination, { + page: 0, + limit: 10, + resourceUrl: '/', + }) + const totalPages = Math.ceil(total / pagination.limit) const meta = { diff --git a/src/Helpers/FakeApi.js b/src/Helpers/FakeApi.ts similarity index 56% rename from src/Helpers/FakeApi.js rename to src/Helpers/FakeApi.ts index dab73ba..ec57902 100644 --- a/src/Helpers/FakeApi.js +++ b/src/Helpers/FakeApi.ts @@ -7,30 +7,27 @@ * file that was distributed with this source code. */ -import fastify from 'fastify' import fastifyFormbody from '@fastify/formbody' +import { File } from '#src/Helpers/File' import { Path } from '#src/Helpers/Path' import { Json } from '#src/Helpers/Json' import { Debug } from '#src/Helpers/Debug' import { Folder } from '#src/Helpers/Folder' +import { fastify, FastifyInstance, HTTPMethods, RouteOptions } from 'fastify' export class FakeApi { /** * Set if the FakeApi server is running. - * - * @type {boolean} */ - static #isRunning = false + private static _isRunning = false /** * Create the fastify server with plugins. * * This method is already called when you import FakeApi module. - * - * @return {import('fastify').FastifyInstance} */ - static recreate() { + public static recreate(): FastifyInstance { const app = fastify() app.register(fastifyFormbody) @@ -40,10 +37,8 @@ export class FakeApi { /** * Creates a new instance of FakeApiBuilder - * - * @return {FakeApiBuilder} */ - static build() { + public static build(): FakeApiBuilder { return new FakeApiBuilder() } @@ -52,59 +47,51 @@ export class FakeApi { * * @return {string} */ - static listRoutes() { + public static listRoutes(): string { return app.printRoutes() } /** - * List the routes registered in the fake server. - * - * @return {boolean} + * Verify if the FakeApi server is running. */ - static isRunning() { - return this.#isRunning + public static isRunning(): boolean { + return this._isRunning } /** * Register all routes inside folder path * and start the fake api server at port 8989. - * - * @param [port] {number} - * @param [folderPath] {string | null} - * @return {Promise} */ - static async start(port = 8989, folderPath = Path.resources('fake-api')) { + public static async start( + port = 8989, + folderPath = Path.resources('fake-api'), + ): Promise { if (folderPath) { - await this.#registerFolder(folderPath) + await this.registerFolder(folderPath) } await app.listen({ port }) - this.#isRunning = true + this._isRunning = true } /** * Stop the fake api server. - * - * @return {Promise} */ - static async stop() { + public static async stop(): Promise { await app.close() app = FakeApi.recreate() - this.#isRunning = false + this._isRunning = false } /** * Register all file routes found in folder path. - * - * @param path {string} - * @return {Promise} */ - static async #registerFolder(path) { + public static async registerFolder(path: string): Promise { const files = new Folder(path).getFilesByPattern('*/**/*.json', true) const promises = files.map(file => - file.load().then(fileLoaded => this.#registerFile(fileLoaded)), + file.load().then(fileLoaded => this.registerFile(fileLoaded)), ) await Promise.all(promises) @@ -112,11 +99,8 @@ export class FakeApi { /** * Register a route file. - * - * @param file {File} - * @return {void} */ - static #registerFile(file) { + public static registerFile(file: File): void { const object = Json.parse(file.content.toString()) if (!object) { @@ -142,134 +126,101 @@ export class FakeApi { export class FakeApiBuilder { /** * The route path. - * - * @type {string | undefined} */ - #path + private _path?: string /** * The redirect path. - * - * @type {string | undefined} */ - #redirectTo + private _redirectTo?: string /** * The route method. - * - * @type {import('fastify').HTTPMethods | undefined} */ - #method + private _method?: HTTPMethods /** * The route response body. - * - * @type {any | any[] | undefined} */ - #body + private _body?: any | any[] /** * The route response headers. - * - * @type {any | undefined} */ - #headers + private _headers?: any /** * The route response status code. - * - * @type {number | undefined} */ - #statusCode + private _statusCode?: number /** * Set the route path. - * - * @param path {string} - * @return {FakeApiBuilder} */ - path(path) { - this.#path = path + public path(path: string): FakeApiBuilder { + this._path = path return this } /** * Set the redirect path. - * - * @param redirectTo {string} - * @return {FakeApiBuilder} */ - redirectTo(redirectTo) { - this.#redirectTo = redirectTo + public redirectTo(redirectTo: string): FakeApiBuilder { + this._redirectTo = redirectTo return this } /** * Set the route method. - * - * @param method {import('fastify').HTTPMethods} - * @return {FakeApiBuilder} */ - method(method) { - this.#method = method + public method(method: HTTPMethods): FakeApiBuilder { + this._method = method return this } /** * Set the response body of the route. - * - * @param body {any | any[]} - * @return {FakeApiBuilder} */ - body(body) { - this.#body = body + public body(body: any | any[]): FakeApiBuilder { + this._body = body return this } /** * Set the response headers of the route. - * - * @param headers {any} - * @return {FakeApiBuilder} */ - headers(headers) { - this.#headers = headers + public headers(headers: any): FakeApiBuilder { + this._headers = headers return this } /** * Set the response status code of the route. - * - * @param statusCode {number} - * @return {FakeApiBuilder} */ - statusCode(statusCode) { - this.#statusCode = statusCode + public statusCode(statusCode: number): FakeApiBuilder { + this._statusCode = statusCode return this } /** * Register the route. - * - * @param [options] {import('fastify').RouteOptions} - * @return void */ - register(options = {}) { - let body = this.#body || {} - let statusCode = this.#statusCode || 200 + public register(options: Partial = {}): void { + let body = this._body || {} + let statusCode = this._statusCode || 200 - const url = this.#path || '/' - const headers = this.#headers || {} - const method = this.#method || 'GET' + const url = this._path || '/' + const headers = this._headers || {} + const method = this._method || 'GET' - if (this.#redirectTo) { - statusCode = this.#statusCode || 302 + if (this._redirectTo) { + statusCode = this._statusCode || 302 } if (statusCode === 204) { @@ -286,8 +237,8 @@ export class FakeApiBuilder { url, method, handler: (_, response) => { - if (this.#redirectTo) { - return response.redirect(statusCode, this.#redirectTo) + if (this._redirectTo) { + return response.redirect(statusCode, this._redirectTo) } return response.status(statusCode).headers(headers).send(body) diff --git a/src/Helpers/File.js b/src/Helpers/File.ts similarity index 70% rename from src/Helpers/File.js rename to src/Helpers/File.ts index 47dd655..39d864d 100644 --- a/src/Helpers/File.js +++ b/src/Helpers/File.ts @@ -20,68 +20,163 @@ import { rmSync, statSync, writeFileSync, + ReadStream, + WriteStream, } from 'node:fs' import { lookup } from 'mime-types' import { pathToFileURL } from 'node:url' -import { randomBytes } from 'node:crypto' -import { isAbsolute, parse, sep } from 'node:path' - import { Path } from '#src/Helpers/Path' import { Json } from '#src/Helpers/Json' +import { randomBytes } from 'node:crypto' import { Debug } from '#src/Helpers/Debug' +import { StreamOptions } from 'node:stream' import { Parser } from '#src/Helpers/Parser' import { Options } from '#src/Helpers/Options' +import { isAbsolute, parse, sep } from 'node:path' import { NotFoundFileException } from '#src/Exceptions/NotFoundFileException' +export interface FileJSON { + dir: string + name: string + base: string + path: string + mime: string + createdAt: Date + accessedAt: Date + modifiedAt: Date + fileSize: string + extension: string + isCopy: boolean + originalDir: string + originalName: string + originalPath: string + originalHref: string + originalFileExists: boolean + content: string +} + export class File { /** - * Creates a new instance of File. - * - * @param {string} filePath - * @param {Buffer} [content] - * @param {boolean} [mockedValues] - * @param {boolean} [isCopy] - * @return {File} - */ - constructor( - filePath, - content = undefined, + * The original or faked file directory. + */ + public dir: string + + /** + * The original or faked file name. + */ + public name: string + + /** + * The original or faked file base. + */ + public base: string + + /** + * The original or faked file path. + */ + public path: string + + /** + * The original or faked href path. + */ + public href: string + + /** + * The file mime type. + */ + public mime: string + + /** + * Set if original or fake file exists. + */ + public fileExists: boolean + + /** + * Date when the file was created. + */ + public createdAt: Date + + /** + * Date when the file was last accessed. + */ + public accessedAt: Date + + /** + * Date when the file was last modified. + */ + public modifiedAt: Date + + /** + * The file size. + */ + public fileSize: string + + /** + * The file extension. + */ + public extension: string + + /** + * Set if file is a copy or not. + */ + public isCopy: boolean + + /** + * Original file directory. + */ + public originalDir: string + + /** + * Original file name. + */ + public originalName: string + + /** + * Original file base. + */ + public originalBase: string + + /** + * Original file path. + */ + public originalPath: string + + /** + * Original file href. + */ + public originalHref: string + + /** + * Set if original file exists. + */ + public originalFileExists: boolean + + /** + * The file content as Buffer. + */ + public content: Buffer + + public constructor( + filePath: string, + content: Buffer = undefined, mockedValues = false, isCopy = false, ) { - const { ext, dir, name, base, mime, path } = File.#parsePath(filePath) + const { ext, dir, name, base, mime, path } = File.parsePath(filePath) - /** @type {string} */ this.originalDir = dir - - /** @type {string} */ this.originalName = name - - /** @type {string} */ this.originalBase = base - - /** @type {string} */ this.originalPath = path - - /** @type {boolean} */ + this.originalHref = pathToFileURL(path).href this.isCopy = isCopy - - /** @type {boolean} */ this.originalFileExists = File.existsSync(this.originalPath) && !this.isCopy - - /** @type {boolean} */ this.fileExists = this.originalFileExists - - /** @type {Buffer} */ this.content = content - - /** @type {string} */ this.mime = mime - - /** @type {string} */ this.extension = ext - this.#createFileValues(mockedValues) + this.createFileValues(mockedValues) if (!this.originalFileExists && !this.content) { throw new NotFoundFileException(this.originalPath) @@ -90,12 +185,9 @@ export class File { /** * Remove the file it's existing or not. - * - * @param {string} filePath - * @return {Promise} */ - static async safeRemove(filePath) { - const { path } = File.#parsePath(filePath) + public static async safeRemove(filePath: string): Promise { + const { path } = File.parsePath(filePath) if (!(await File.exists(path))) { return @@ -106,24 +198,18 @@ export class File { /** * Verify if file exists. - * - * @param {string} filePath - * @return {boolean} */ - static existsSync(filePath) { - const { path } = File.#parsePath(filePath) + public static existsSync(filePath: string): boolean { + const { path } = File.parsePath(filePath) return existsSync(path) } /** * Verify if file exists. - * - * @param {string} filePath - * @return {Promise} */ - static async exists(filePath) { - const { path } = File.#parsePath(filePath) + public static async exists(filePath: string): Promise { + const { path } = File.parsePath(filePath) return promises .access(path) @@ -133,37 +219,30 @@ export class File { /** * Verify if path is from file or directory. - * - * @param {string} path - * @return {boolean} */ - static isFileSync(path) { - const { path: parsedPath } = File.#parsePath(path) + public static isFileSync(path: string): boolean { + const { path: parsedPath } = File.parsePath(path) return statSync(parsedPath).isFile() } /** * Verify if path is from file or directory. - * - * @param {string} path - * @return {Promise} */ - static async isFile(path) { - const { path: parsedPath } = File.#parsePath(path) + public static async isFile(path: string): Promise { + const { path: parsedPath } = File.parsePath(path) return promises.stat(parsedPath).then(stat => stat.isFile()) } /** * Create fake file with determined size. - * - * @param {string} filePath - * @param {number} size - * @return {Promise} */ - static async createFileOfSize(filePath, size) { - const { dir, path } = File.#parsePath(filePath) + public static async createFileOfSize( + filePath: string, + size: number, + ): Promise { + const { dir, path } = File.parsePath(filePath) await promises.mkdir(dir, { recursive: true }) @@ -179,20 +258,16 @@ export class File { /** * Parse the file path. - * - * @private - * @param {string} filePath - * @return {{ - * ext: string, - * path: string, - * root: string, - * mime: string, - * name: string, - * dir: string, - * base: string - * }} - */ - static #parsePath(filePath) { + */ + private static parsePath(filePath: string): { + ext: string + path: string + root: string + mime: string + name: string + dir: string + base: string + } { if (!isAbsolute(filePath)) { filePath = Path.this(filePath, 3) } @@ -213,27 +288,8 @@ export class File { /** * Returns the file as a JSON object. - * - * @return {{ - * dir: string, - * name: string, - * base: string, - * path: string, - * mime: string, - * createdAt: Date, - * accessedAt: Date, - * modifiedAt: Date, - * fileSize: number, - * extension: string, - * isCopy: boolean, - * originalDir: string, - * originalName: string, - * originalPath: string, - * originalFileExists: boolean, - * content: string, - * }} - */ - toJSON() { + */ + public toJSON(): FileJSON { return Json.copy({ dir: this.dir, name: this.name, @@ -251,6 +307,7 @@ export class File { originalDir: this.originalDir, originalName: this.originalName, originalPath: this.originalPath, + originalHref: this.originalHref, originalFileExists: this.originalFileExists, content: this.content, }) @@ -258,14 +315,11 @@ export class File { /** * Load or create the file. - * - * @param {{ - * withContent?: boolean, - * isInternalLoad?: boolean - * }} [options] - * @return {File} - */ - loadSync(options) { + */ + public loadSync(options?: { + withContent?: boolean + isInternalLoad?: boolean + }): File { options = Options.create(options, { withContent: true, isInternalLoad: false, @@ -309,14 +363,11 @@ export class File { /** * Load or create the file. - * - * @param {{ - * withContent?: boolean, - * isInternalLoad?: boolean - * }} [options] - * @return {Promise} - */ - async load(options) { + */ + public async load(options?: { + withContent?: boolean + isInternalLoad?: boolean + }): Promise { options = Options.create(options, { withContent: true, isInternalLoad: false, @@ -383,10 +434,8 @@ export class File { /** * Remove the file. - * - * @return {void} */ - removeSync() { + public removeSync(): void { if (!this.fileExists) { throw new NotFoundFileException(this.path) } @@ -404,10 +453,8 @@ export class File { /** * Remove the file. - * - * @return {Promise} */ - async remove() { + public async remove(): Promise { if (!this.fileExists) { throw new NotFoundFileException(this.path) } @@ -425,16 +472,12 @@ export class File { /** * Create a copy of the file. - * - * @param {string} path - * @param {{ - * withContent?: boolean, - * mockedValues?: boolean - * }} [options] - * @return {File} */ - copySync(path, options) { - path = File.#parsePath(path).path + public copySync( + path: string, + options?: { withContent?: boolean; mockedValues?: boolean }, + ): File { + path = File.parsePath(path).path options = Options.create(options, { withContent: true, @@ -453,16 +496,12 @@ export class File { /** * Create a copy of the file. - * - * @param {string} path - * @param {{ - * withContent?: boolean, - * mockedValues?: boolean - * }} [options] - * @return {Promise} */ - async copy(path, options) { - path = File.#parsePath(path).path + public async copy( + path: string, + options?: { withContent?: boolean; mockedValues?: boolean }, + ): Promise { + path = File.parsePath(path).path options = Options.create(options, { withContent: true, @@ -481,16 +520,12 @@ export class File { /** * Move the file to other path. - * - * @param {string} path - * @param {{ - * withContent?: boolean, - * mockedValues?: boolean - * }} [options] - * @return {File} */ - moveSync(path, options) { - path = File.#parsePath(path).path + public moveSync( + path: string, + options?: { withContent?: boolean; mockedValues?: boolean }, + ): File { + path = File.parsePath(path).path options = Options.create(options, { withContent: true, @@ -513,16 +548,12 @@ export class File { /** * Move the file to other path. - * - * @param {string} path - * @param {{ - * withContent?: boolean, - * mockedValues?: boolean - * }} [options] - * @return {Promise} */ - async move(path, options) { - path = File.#parsePath(path).path + public async move( + path: string, + options?: { withContent?: boolean; mockedValues?: boolean }, + ): Promise { + path = File.parsePath(path).path options = Options.create(options, { withContent: true, @@ -545,11 +576,8 @@ export class File { /** * Append any data to the file. - * - * @param {string|Buffer} data - * @return {File} */ - appendSync(data) { + public appendSync(data: string | Buffer): File { this.loadSync({ isInternalLoad: true, withContent: false }) appendFileSync(this.path, data) @@ -560,11 +588,8 @@ export class File { /** * Append any data to the file. - * - * @param {string|Buffer} data - * @return {Promise} */ - async append(data) { + public async append(data: string | Buffer): Promise { await this.load({ isInternalLoad: true, withContent: false }) const writeStream = createWriteStream(this.path, { flags: 'a' }) @@ -581,11 +606,8 @@ export class File { /** * Prepend any data to the file. - * - * @param {string|Buffer} data - * @return {File} */ - prependSync(data) { + public prependSync(data: string | Buffer): File { this.loadSync({ isInternalLoad: true, withContent: false }) prependFile.sync(this.path, data) @@ -596,11 +618,8 @@ export class File { /** * Prepend any data to the file. - * - * @param {string|Buffer} data - * @return {Promise} */ - async prepend(data) { + public async prepend(data: string | Buffer): Promise { await this.load({ isInternalLoad: true, withContent: false }) await prependFile(this.path, data) @@ -611,13 +630,8 @@ export class File { /** * Get only the content of the file. - * - * @param {{ - * saveContent?: boolean - * }} [options] - * @return {Buffer} */ - getContentSync(options) { + public getContentSync(options?: { saveContent?: boolean }): Buffer { this.loadSync({ isInternalLoad: true, withContent: false }) options = Options.create(options, { saveContent: false }) @@ -633,13 +647,10 @@ export class File { /** * Get only the content of the file. - * - * @param {{ - * saveContent?: boolean - * }} [options] - * @return {Promise} */ - async getContent(options) { + public async getContent(options?: { + saveContent?: boolean + }): Promise { await this.load({ isInternalLoad: true, withContent: false }) options = Options.create(options, { saveContent: false }) @@ -670,21 +681,19 @@ export class File { /** * Create a readable stream of the file. - * - * @param [options] {BufferEncoding | import('node:stream').StreamOptions} - * @return {import('node:fs').ReadStream} */ - createReadStream(options) { + public createReadStream( + options?: BufferEncoding | StreamOptions, + ): ReadStream { return createReadStream(this.originalPath, options) } /** * Create a writable stream of the file. - * - * @param [options] {BufferEncoding | import('node:stream').StreamOptions} - * @return {import('node:fs').WriteStream} */ - createWriteStream(options) { + public createWriteStream( + options?: BufferEncoding | StreamOptions, + ): WriteStream { if (!this.fileExists) { this.loadSync() } @@ -694,12 +703,8 @@ export class File { /** * Create file values. - * - * @private - * @param {boolean?} mockedValues - * @return {void} */ - #createFileValues(mockedValues) { + private createFileValues(mockedValues?: boolean): void { if (mockedValues && !this.originalFileExists) { const bytes = randomBytes(30) const buffer = Buffer.from(bytes) @@ -707,7 +712,7 @@ export class File { this.dir = this.originalDir this.name = buffer.toString('base64').replace(/[^a-zA-Z0-9]/g, '') this.base = this.name + this.extension - this.path = this.dir + '/' + this.base + this.path = this.dir + sep + this.base this.href = pathToFileURL(this.path).href return @@ -717,6 +722,6 @@ export class File { this.name = this.originalName this.base = this.originalBase this.path = this.originalPath - this.href = pathToFileURL(this.path).href + this.href = this.originalHref } } diff --git a/src/Helpers/Folder.js b/src/Helpers/Folder.ts similarity index 67% rename from src/Helpers/Folder.js rename to src/Helpers/Folder.ts index 4045a88..f2de595 100644 --- a/src/Helpers/Folder.js +++ b/src/Helpers/Folder.ts @@ -16,65 +16,144 @@ import { readdirSync, rmSync, statSync, + Dirent, } from 'node:fs' -import { randomBytes } from 'node:crypto' -import { isAbsolute, join, parse, resolve, sep } from 'node:path' - import { Json } from '#src/Helpers/Json' import { File } from '#src/Helpers/File' +import { Path } from '#src/Helpers/Path' +import { randomBytes } from 'node:crypto' import { Parser } from '#src/Helpers/Parser' import { Options } from '#src/Helpers/Options' +import { isAbsolute, join, parse, resolve, sep } from 'node:path' import { NotFoundFolderException } from '#src/Exceptions/NotFoundFolderException' -import { Path } from '#src/Helpers/Path' + +export interface FolderJSON { + dir: string + name: string + base: string + path: string + files: File[] + // eslint-disable-next-line no-use-before-define + folders: Folder[] + createdAt: Date + accessedAt: Date + modifiedAt: Date + folderSize: string + isCopy: boolean + originalDir: string + originalName: string + originalPath: string + originalFolderExists: boolean +} export class Folder { /** - * Creates a new instance of Folder. - * - * @param {string} folderPath - * @param {boolean} [mockedValues] - * @param {boolean} [isCopy] - * @return {Folder} + * The original or faked folder directory. */ - constructor(folderPath, mockedValues = false, isCopy = false) { - const { dir, name, path } = Folder.#parsePath(folderPath) + public dir: string - /** @type {File[]} */ - this.files = [] + /** + * The original or faked folder name. + */ + public name: string - /** @type {Folder[]} */ - this.folders = [] + /** + * The original or faked folder base. + */ + public base: string - /** @type {string} */ - this.originalDir = dir + /** + * The original or faked folder path. + */ + public path: string - /** @type {string} */ - this.originalName = name + /** + * All the files inside of the folder. + */ + public files: File[] - /** @type {string} */ - this.originalPath = path + /** + * All the folders inside of the folder. + */ + // eslint-disable-next-line no-use-before-define + public folders: Folder[] - /** @type {boolean} */ - this.isCopy = isCopy + /** + * Set if original or fake folder exists. + */ + public folderExists: boolean + + /** + * Date when the folder was created. + */ + public createdAt: Date + + /** + * Date when the folder was last accessed. + */ + public accessedAt: Date + + /** + * Date when the folder was last modified. + */ + public modifiedAt: Date + + /** + * The folder size. + */ + public folderSize: string + + /** + * Set if folder is a copy or not. + */ + public isCopy: boolean + + /** + * Original folder directory. + */ + public originalDir: string + + /** + * Original folder name. + */ + public originalName: string + + /** + * Original folder base. + */ + public originalBase: string - /** @type {boolean} */ + /** + * Original folder path. + */ + public originalPath: string + + /** + * Set if original folder exists. + */ + public originalFolderExists: boolean + + public constructor(folderPath: string, mockedValues = false, isCopy = false) { + const { dir, name, path } = Folder.parsePath(folderPath) + + this.files = [] + this.folders = [] + this.originalDir = dir + this.originalName = name + this.originalPath = path + this.isCopy = isCopy this.originalFolderExists = Folder.existsSync(this.originalPath) && !this.isCopy - - /** @type {boolean} */ this.folderExists = this.originalFolderExists - this.#createFolderValues(mockedValues) + this.createFolderValues(mockedValues) } /** * Get the size of the folder. - * - * @param {string} folderPath - * @return {number} */ - static folderSizeSync(folderPath) { + public static folderSizeSync(folderPath: string): number { const files = readdirSync(folderPath) const stats = files.map(file => statSync(join(folderPath, file))) @@ -83,11 +162,8 @@ export class Folder { /** * Get the size of the folder. - * - * @param {string} folderPath - * @return {Promise} */ - static async folderSize(folderPath) { + public static async folderSize(folderPath: string): Promise { const files = await promises.readdir(folderPath) const stats = files.map(file => promises.stat(join(folderPath, file))) @@ -99,12 +175,9 @@ export class Folder { /** * Remove the folder it's existing or not. - * - * @param {string} folderPath - * @return {Promise} */ - static async safeRemove(folderPath) { - const { path } = Folder.#parsePath(folderPath) + public static async safeRemove(folderPath: string): Promise { + const { path } = Folder.parsePath(folderPath) if (!(await Folder.exists(path))) { return @@ -115,24 +188,18 @@ export class Folder { /** * Verify if folder exists. - * - * @param {string} folderPath - * @return {boolean} */ - static existsSync(folderPath) { - const { path } = Folder.#parsePath(folderPath) + public static existsSync(folderPath: string): boolean { + const { path } = Folder.parsePath(folderPath) return existsSync(path) } /** * Verify if folder exists. - * - * @param {string} folderPath - * @return {Promise} */ - static async exists(folderPath) { - const { path } = Folder.#parsePath(folderPath) + public static async exists(folderPath: string): Promise { + const { path } = Folder.parsePath(folderPath) return promises .access(path) @@ -142,12 +209,9 @@ export class Folder { /** * Verify if path is from folder or file. - * - * @param {string} path - * @return {boolean} */ - static isFolderSync(path) { - const { path: parsedPath } = Folder.#parsePath(path) + public static isFolderSync(path: string): boolean { + const { path: parsedPath } = Folder.parsePath(path) return statSync(parsedPath).isDirectory() } @@ -158,20 +222,16 @@ export class Folder { * @param {string} path * @return {Promise} */ - static async isFolder(path) { - const { path: parsedPath } = Folder.#parsePath(path) + public static async isFolder(path: string): Promise { + const { path: parsedPath } = Folder.parsePath(path) return promises.stat(parsedPath).then(stat => stat.isDirectory()) } /** * Get sub files of folder. - * - * @param {Folder[]} folders - * @param {string} [pattern] - * @return {File[]} */ - static #getSubFiles(folders, pattern) { + private static getSubFiles(folders: Folder[], pattern?: string): File[] { const files = [] folders.forEach(folder => { @@ -188,7 +248,7 @@ export class Folder { }) if (folder.folders.length) { - files.push(...this.#getSubFiles(folder.folders, pattern)) + files.push(...this.getSubFiles(folder.folders, pattern)) } }) @@ -197,13 +257,12 @@ export class Folder { /** * Get sub folders of folder. - * - * @param {Folder} folder - * @param {boolean} recursive - * @param {string} [pattern] - * @return {Folder[]} */ - static #getSubFolders(folder, recursive, pattern) { + private static getSubFolders( + folder: Folder, + recursive: boolean, + pattern?: string, + ): Folder[] { const subFolders = [] folder.folders.forEach(f => { @@ -212,7 +271,7 @@ export class Folder { } if (recursive && f.folders.length) { - subFolders.push(...this.#getSubFolders(f, recursive, pattern)) + subFolders.push(...this.getSubFolders(f, recursive, pattern)) } if (pattern && minimatch(f.path, pattern)) { @@ -225,12 +284,12 @@ export class Folder { /** * Parse the folder path. - * - * @private - * @param {string} folderPath - * @return {{path: string, name: string, dir: string}} */ - static #parsePath(folderPath) { + private static parsePath(folderPath: string): { + path: string + name: string + dir: string + } { if (!isAbsolute(folderPath)) { folderPath = Path.this(folderPath, 3) } @@ -248,26 +307,8 @@ export class Folder { /** * Returns the file as a JSON object. - * - * @return {{ - * dir: string, - * name: string, - * base: string, - * path: string, - * files: File[], - * folders: Folder[], - * createdAt: Date, - * accessedAt: Date, - * modifiedAt: Date, - * folderSize: number, - * isCopy: boolean, - * originalDir: string, - * originalName: string, - * originalPath: string, - * originalFolderExists: boolean - * }} - */ - toJSON() { + */ + public toJSON(): FolderJSON { return Json.copy({ dir: this.dir, name: this.name, @@ -289,18 +330,15 @@ export class Folder { /** * Load or create the folder. - * - * @param {{ - * withSub?: boolean, - * withFileContent?: boolean, - * isInternalLoad?: boolean, - * }} [options] - * @return {Folder} - */ - loadSync(options) { + */ + public loadSync(options?: { + withSub?: boolean + withContent?: boolean + isInternalLoad?: boolean + }): Folder { options = Options.create(options, { withSub: true, - withFileContent: false, + withContent: false, isInternalLoad: false, }) @@ -325,10 +363,10 @@ export class Folder { return this } - this.#loadSubSync( + this.loadSubSync( this.path, readdirSync(this.path, { withFileTypes: true }), - options.withFileContent, + options.withContent, ) return this @@ -336,18 +374,15 @@ export class Folder { /** * Load or create the folder. - * - * @param {{ - * withSub?: boolean, - * withFileContent?: boolean, - * isInternalLoad?: boolean, - * }} [options] - * @return {Promise} - */ - async load(options) { + */ + public async load(options?: { + withSub?: boolean + withContent?: boolean + isInternalLoad?: boolean + }): Promise { options = Options.create(options, { withSub: true, - withFileContent: false, + withContent: false, isInternalLoad: false, }) @@ -372,10 +407,10 @@ export class Folder { return this } - await this.#loadSub( + await this.loadSub( this.path, await promises.readdir(this.path, { withFileTypes: true }), - options.withFileContent, + options.withContent, ) return this @@ -383,10 +418,8 @@ export class Folder { /** * Remove the folder. - * - * @return {void} */ - removeSync() { + public removeSync(): void { if (!this.folderExists) { throw new NotFoundFolderException(this.name) } @@ -405,10 +438,8 @@ export class Folder { /** * Remove the folder. - * - * @return {Promise} */ - async remove() { + public async remove(): Promise { if (!this.folderExists) { throw new NotFoundFolderException(this.name) } @@ -427,27 +458,26 @@ export class Folder { /** * Create a copy of the folder. - * - * @param {string} path - * @param {{ - * withSub?: boolean, - * withFileContent?: boolean, - * mockedValues?: boolean - * }} [options] - * @return {Folder} */ - copySync(path, options) { - path = Folder.#parsePath(path).path + public copySync( + path: string, + options?: { + withSub?: boolean + withContent?: boolean + mockedValues?: boolean + }, + ): Folder { + path = Folder.parsePath(path).path options = Options.create(options, { withSub: true, - withFileContent: false, + withContent: false, mockedValues: false, }) this.loadSync({ withSub: options.withSub, - withContent: options.withFileContent, + withContent: options.withContent, isInternalLoad: true, }) @@ -458,15 +488,15 @@ export class Folder { folder.files = this.files.map(f => { return f.copySync(`${folder.path}/${f.base}`, { mockedValues: options.mockedValues, - withContent: options.withFileContent, + withContent: options.withContent, }) }) folder.folders = this.folders.map(f => { return f.copySync(`${folder.path}/${f.base}`, { withSub: options.withSub, + withContent: options.withContent, mockedValues: options.mockedValues, - withContent: options.withFileContent, }) }) @@ -475,27 +505,26 @@ export class Folder { /** * Create a copy of the folder. - * - * @param {string} path - * @param {{ - * withSub?: boolean, - * withFileContent?: boolean, - * mockedValues?: boolean - * }} [options] - * @return {Promise} */ - async copy(path, options) { - path = Folder.#parsePath(path).path + public async copy( + path: string, + options?: { + withSub?: boolean + withContent?: boolean + mockedValues?: boolean + }, + ): Promise { + path = Folder.parsePath(path).path options = Options.create(options, { withSub: true, - withFileContent: false, + withContent: false, mockedValues: false, }) await this.load({ withSub: options.withSub, - withContent: options.withFileContent, + withContent: options.withContent, isInternalLoad: true, }) @@ -507,7 +536,7 @@ export class Folder { this.files.map(f => { return f.copy(`${folder.path}/${f.base}`, { mockedValues: options.mockedValues, - withContent: options.withFileContent, + withContent: options.withContent, }) }), ) @@ -517,7 +546,7 @@ export class Folder { return f.copy(`${folder.path}/${f.name}`, { withSub: options.withSub, mockedValues: options.mockedValues, - withContent: options.withFileContent, + withContent: options.withContent, }) }), ) @@ -527,27 +556,26 @@ export class Folder { /** * Move the folder to other path. - * - * @param {string} path - * @param {{ - * withSub?: boolean, - * withFileContent?: boolean, - * mockedValues?: boolean - * }} [options] - * @return {Folder} */ - moveSync(path, options) { - path = Folder.#parsePath(path).path + public moveSync( + path: string, + options?: { + withSub?: boolean + withContent?: boolean + mockedValues?: boolean + }, + ): Folder { + path = Folder.parsePath(path).path options = Options.create(options, { withSub: true, - withFileContent: false, + withContent: false, mockedValues: false, }) this.loadSync({ withSub: options.withSub, - withContent: options.withFileContent, + withContent: options.withContent, isInternalLoad: true, }) @@ -558,7 +586,7 @@ export class Folder { folder.files = this.files.map(f => { return f.moveSync(`${folder.path}/${f.base}`, { mockedValues: options.mockedValues, - withContent: options.withFileContent, + withContent: options.withContent, }) }) @@ -566,7 +594,7 @@ export class Folder { return f.moveSync(`${folder.path}/${f.name}`, { withSub: options.withSub, mockedValues: options.mockedValues, - withContent: options.withFileContent, + withContent: options.withContent, }) }) @@ -577,27 +605,26 @@ export class Folder { /** * Move the folder to other path. - * - * @param {string} path - * @param {{ - * withSub?: boolean, - * withFileContent?: boolean, - * mockedValues?: boolean - * }} [options] - * @return {Promise} */ - async move(path, options) { - path = Folder.#parsePath(path).path + public async move( + path: string, + options?: { + withSub?: boolean + withContent?: boolean + mockedValues?: boolean + }, + ): Promise { + path = Folder.parsePath(path).path options = Options.create(options, { withSub: true, - withFileContent: false, + withContent: false, mockedValues: false, }) await this.load({ withSub: options.withSub, - withContent: options.withFileContent, + withContent: options.withContent, isInternalLoad: true, }) @@ -609,7 +636,7 @@ export class Folder { this.files.map(f => { return f.move(`${folder.path}/${f.base}`, { mockedValues: options.mockedValues, - withContent: options.withFileContent, + withContent: options.withContent, }) }), ) @@ -619,7 +646,7 @@ export class Folder { return f.move(`${folder.path}/${f.name}`, { withSub: options.withSub, mockedValues: options.mockedValues, - withContent: options.withFileContent, + withContent: options.withContent, }) }), ) @@ -631,12 +658,8 @@ export class Folder { /** * Get all the files of folder using glob pattern. - * - * @param {string} [pattern] - * @param {boolean} [recursive] - * @return {File[]} */ - getFilesByPattern(pattern, recursive = false) { + public getFilesByPattern(pattern?: string, recursive = false): File[] { this.loadSync({ withSub: true, isInternalLoad: true }) if (pattern) { @@ -656,7 +679,7 @@ export class Folder { }) if (recursive) { - files.push(...Folder.#getSubFiles(this.folders, pattern)) + files.push(...Folder.getSubFiles(this.folders, pattern)) } return files @@ -664,12 +687,8 @@ export class Folder { /** * Get all the folders of folder using glob pattern. - * - * @param {string} [pattern] - * @param {boolean} [recursive] - * @return {Folder[]} */ - getFoldersByPattern(pattern, recursive = false) { + public getFoldersByPattern(pattern?: string, recursive = false): Folder[] { this.loadSync({ withSub: true, isInternalLoad: true }) if (pattern) { @@ -680,7 +699,7 @@ export class Folder { this.folders.forEach(folder => { if (recursive && folder.folders.length) { - folders.push(...Folder.#getSubFolders(folder, recursive, pattern)) + folders.push(...Folder.getSubFolders(folder, recursive, pattern)) } if (pattern && minimatch(folder.path, pattern)) { @@ -697,11 +716,8 @@ export class Folder { /** * Create folder values. - * - * @param {boolean?} mockedValues - * @return {void} */ - #createFolderValues(mockedValues) { + private createFolderValues(mockedValues?: boolean): void { if (mockedValues && !this.originalFolderExists) { const bytes = randomBytes(8) const buffer = Buffer.from(bytes) @@ -720,20 +736,19 @@ export class Folder { /** * Load sub files/folder of folder. - * - * @param {string} path - * @param {Dirent[]} dirents - * @param {boolean} withFileContent - * @return {void} */ - #loadSubSync(path, dirents, withFileContent) { + private loadSubSync( + path: string, + dirents: Dirent[], + withContent: boolean, + ): void { dirents.forEach(dirent => { const name = resolve(path, dirent.name) if (dirent.isDirectory()) { const folder = new Folder(name).loadSync({ withSub: true, - withFileContent, + withContent, isInternalLoad: true, }) @@ -743,7 +758,7 @@ export class Folder { } const file = new File(name).loadSync({ - withContent: withFileContent, + withContent, isInternalLoad: true, }) @@ -753,13 +768,12 @@ export class Folder { /** * Load sub files/folder of folder. - * - * @param {string} path - * @param {Dirent[]} dirents - * @param {boolean} withFileContent - * @return {Promise} */ - async #loadSub(path, dirents, withFileContent) { + private async loadSub( + path: string, + dirents: Dirent[], + withContent?: boolean, + ): Promise { const files = [] const folders = [] @@ -769,7 +783,7 @@ export class Folder { if (dirent.isDirectory()) { const folder = new Folder(name).load({ withSub: true, - withFileContent, + withContent, isInternalLoad: true, }) @@ -779,7 +793,7 @@ export class Folder { } const file = new File(name).load({ - withContent: withFileContent, + withContent, isInternalLoad: true, }) diff --git a/src/Helpers/HttpClient.js b/src/Helpers/HttpClient.ts similarity index 59% rename from src/Helpers/HttpClient.js rename to src/Helpers/HttpClient.ts index 4b3f5c7..5c296d8 100644 --- a/src/Helpers/HttpClient.js +++ b/src/Helpers/HttpClient.ts @@ -7,44 +7,63 @@ * file that was distributed with this source code. */ -import got from 'got' +import CacheableLookup from 'cacheable-lookup' +import got, { + Hooks, + Delays, + Agents, + Method, + Request, + InitHook, + RetryOptions, + ResponseType, + HttpsOptions, + CacheOptions, + ToughCookieJar, + BeforeRetryHook, + BeforeErrorHook, + PromiseCookieJar, + PaginationOptions, + AfterResponseHook, + BeforeRequestHook, + ParseJsonFunction, + DnsLookupIpVersion, + BeforeRedirectHook, + StringifyJsonFunction, + CreateConnectionFunction, +} from 'got' + +import { Store } from 'keyv' import { Is } from '#src/Helpers/Is' import { Json } from '#src/Helpers/Json' +import { ClientHttp2Session } from 'http2' +import { Body } from '#src/Types/HttpClient/Body' +import { Query } from '#src/Types/HttpClient/Query' +import { ReqOptions } from '#src/Types/HttpClient/ReqOptions' +import { RetryStrategyCallback } from '#src/Types/HttpClient/RetryStrategyCallback' export class HttpClientBuilder { /** * Got options used to make the request. - * - * @type {import('got').OptionsInit} */ - #options + private options: ReqOptions - /** - * Creates a new instance of HttpClientBuilder. - * - * @param options {import('got').OptionsInit} - */ - constructor(options = {}) { - this.#options = options + public constructor(options: ReqOptions = {}) { + this.options = options } /** * Return the options of the client builder. - * - * @return {import('got').OptionsInit} */ - getOptions() { - return Json.copy(this.#options) + public getOptions(): ReqOptions { + return Json.copy(this.options) } /** * From `http-cache-semantics` - * - * @param cacheOptions {import('got').CacheOptions} - * @return {HttpClientBuilder} */ - cacheOptions(cacheOptions) { - this.#options.cacheOptions = cacheOptions + public cacheOptions(cacheOptions: CacheOptions): HttpClientBuilder { + this.options.cacheOptions = cacheOptions return this } @@ -89,20 +108,17 @@ export class HttpClientBuilder { * // There is no option named `followRedirects` in got, but we correct it * // in an `init` hook. * ``` - * - * @param initHook {import('got').InitHook} - * @return {HttpClientBuilder} */ - setInitHook(initHook) { - if (!this.#options.hooks) { - this.#options.hooks = {} + public setInitHook(initHook: InitHook): HttpClientBuilder { + if (!this.options.hooks) { + this.options.hooks = {} } - if (!this.#options.hooks.init) { - this.#options.hooks.init = [] + if (!this.options.hooks.init) { + this.options.hooks.init = [] } - this.#options.hooks.init.push(initHook) + this.options.hooks.init.push(initHook) return this } @@ -127,20 +143,17 @@ export class HttpClientBuilder { * }) * .post('https://httpbin.org/anything', { payload: 'old' }) * ``` - * - * @param beforeRequestHook {import('got').BeforeRequestHook} - * @return {HttpClientBuilder} */ - setBeforeRequestHook(beforeRequestHook) { - if (!this.#options.hooks) { - this.#options.hooks = {} + public setBeforeRequestHook(hook: BeforeRequestHook): HttpClientBuilder { + if (!this.options.hooks) { + this.options.hooks = {} } - if (!this.#options.hooks.beforeRequest) { - this.#options.hooks.beforeRequest = [] + if (!this.options.hooks.beforeRequest) { + this.options.hooks.beforeRequest = [] } - this.#options.hooks.beforeRequest.push(beforeRequestHook) + this.options.hooks.beforeRequest.push(hook) return this } @@ -161,20 +174,17 @@ export class HttpClientBuilder { * }) * .get('https://example.com') * ``` - * - * @param beforeRedirectHook {import('got').BeforeRedirectHook} - * @return {HttpClientBuilder} */ - setBeforeRedirectHook(beforeRedirectHook) { - if (!this.#options.hooks) { - this.#options.hooks = {} + public setBeforeRedirectHook(hook: BeforeRedirectHook): HttpClientBuilder { + if (!this.options.hooks) { + this.options.hooks = {} } - if (!this.#options.hooks.beforeRedirect) { - this.#options.hooks.beforeRedirect = [] + if (!this.options.hooks.beforeRedirect) { + this.options.hooks.beforeRedirect = [] } - this.#options.hooks.beforeRedirect.push(beforeRedirectHook) + this.options.hooks.beforeRedirect.push(hook) return this } @@ -200,20 +210,17 @@ export class HttpClientBuilder { * }) * .get('https://api.github.com/repos/AthennaIO/Common/commits') * ``` - * - * @param beforeErrorHook {import('got').BeforeErrorHook} - * @return {HttpClientBuilder} */ - setBeforeErrorHook(beforeErrorHook) { - if (!this.#options.hooks) { - this.#options.hooks = {} + public setBeforeErrorHook(hook: BeforeErrorHook): HttpClientBuilder { + if (!this.options.hooks) { + this.options.hooks = {} } - if (!this.#options.hooks.beforeError) { - this.#options.hooks.beforeError = [] + if (!this.options.hooks.beforeError) { + this.options.hooks.beforeError = [] } - this.#options.hooks.beforeError.push(beforeErrorHook) + this.options.hooks.beforeError.push(hook) return this } @@ -242,20 +249,17 @@ export class HttpClientBuilder { * }) * .get('https://httpbin.org/status/500') * ``` - * - * @param beforeRetryHook {import('got').BeforeRetryHook} - * @return {HttpClientBuilder} */ - setBeforeRetryHook(beforeRetryHook) { - if (!this.#options.hooks) { - this.#options.hooks = {} + public setBeforeRetryHook(hook: BeforeRetryHook): HttpClientBuilder { + if (!this.options.hooks) { + this.options.hooks = {} } - if (!this.#options.hooks.beforeRetry) { - this.#options.hooks.beforeRetry = [] + if (!this.options.hooks.beforeRetry) { + this.options.hooks.beforeRetry = [] } - this.#options.hooks.beforeRetry.push(beforeRetryHook) + this.options.hooks.beforeRetry.push(hook) return this } @@ -298,20 +302,17 @@ export class HttpClientBuilder { * return response * }) * ``` - * - * @param afterResponseHook {import('got').AfterResponseHook} - * @return {HttpClientBuilder} */ - setAfterResponseHook(afterResponseHook) { - if (!this.#options.hooks) { - this.#options.hooks = {} + public setAfterResponseHook(hook: AfterResponseHook): HttpClientBuilder { + if (!this.options.hooks) { + this.options.hooks = {} } - if (!this.#options.hooks.afterResponse) { - this.#options.hooks.afterResponse = [] + if (!this.options.hooks.afterResponse) { + this.options.hooks.afterResponse = [] } - this.#options.hooks.afterResponse.push(afterResponseHook) + this.options.hooks.afterResponse.push(hook) return this } @@ -333,24 +334,18 @@ export class HttpClientBuilder { * .agent({ http: new HttpAgent(), https: new HttpsAgent() } * .get('https://sindresorhus.com') * ``` - * - * @param agents {import('got').Agents} - * @return {HttpClientBuilder} */ - agent(agents) { - this.#options.agent = agents + public agent(agents: Agents): HttpClientBuilder { + this.options.agent = agents return this } /** * Set the http2 session. - * - * @param h2session {ClientHttp2Session} - * @return {HttpClientBuilder} */ - h2session(h2session) { - this.#options.h2session = h2session + public h2session(h2session: ClientHttp2Session): HttpClientBuilder { + this.options.h2session = h2session return this } @@ -362,11 +357,9 @@ export class HttpClientBuilder { * * If this is disabled, a compressed response is returned as a `Buffer`. * This may be useful if you want to handle decompression yourself or stream the raw compressed data. - * - * @param decompress {boolean} */ - decompress(decompress) { - this.#options.decompress = decompress + public decompress(decompress: boolean): HttpClientBuilder { + this.options.decompress = decompress return this } @@ -386,67 +379,56 @@ export class HttpClientBuilder { * - `response` starts when the request has been written to the socket and ends when the response headers are received. * - `send` starts when the socket is connected and ends with the request has been written to the socket. * - `request` starts when the request is initiated and ends when the response's end event fires. - * @param delays {number | Partial} */ - timeout(delays) { - if (!this.#options.timeout) { - this.#options.timeout = {} + public timeout(delays: number | Delays): HttpClientBuilder { + if (!this.options.timeout) { + this.options.timeout = {} } if (Is.Number(delays)) { - this.#options.timeout.request = delays + this.options.timeout.request = delays as number return this } - this.#options.timeout = delays + this.options.timeout = delays as Delays return this } /** * Set the request body. - * - * @param body {Record | string | ReadableStream | Generator | AsyncGenerator | import('form-data-encoder').FormDataLike} - * @return {HttpClientBuilder} */ - body(body) { + public body(body: Body): HttpClientBuilder { if (Is.Object(body)) { - this.#options.json = body + this.options.json = body return this } - this.#options.body = body + this.options.body = body as any return this } /** * Set the request form. - * - * @param form {any} - * @return {HttpClientBuilder} */ - form(form) { - this.#options.form = form + public form(form: any | Record): HttpClientBuilder { + this.options.form = form return this } /** * Set a header at the request. - * - * @param key {string} - * @param value {string} - * @return {HttpClientBuilder} */ - header(key, value) { - if (!this.#options.headers) { - this.#options.headers = {} + public header(key: string, value: string): HttpClientBuilder { + if (!this.options.headers) { + this.options.headers = {} } - this.#options.headers[key] = value + this.options.headers[key] = value return this } @@ -454,41 +436,34 @@ export class HttpClientBuilder { /** * Set a header at the request only if is not already * defined. - * - * @param key {string} - * @param value {string} - * @return {HttpClientBuilder} */ - safeHeader(key, value) { - if (!this.#options.headers) { - this.#options.headers = {} + public safeHeader(key: string, value: string): HttpClientBuilder { + if (!this.options.headers) { + this.options.headers = {} } - if (this.#options.headers[key]) { + if (this.options.headers[key]) { return this } - this.#options.headers[key] = value + this.options.headers[key] = value return this } /** * Remove a header from the request. - * - * @param key {string} - * @return {HttpClientBuilder} */ - removeHeader(key) { - if (!this.#options.headers) { - this.#options.headers = {} + public removeHeader(key: string): HttpClientBuilder { + if (!this.options.headers) { + this.options.headers = {} } - if (!this.#options.headers[key]) { + if (!this.options.headers[key]) { return this } - delete this.#options.headers[key] + delete this.options.headers[key] return this } @@ -517,39 +492,37 @@ export class HttpClientBuilder { * .json() * //=> 'https://cats.com/unicorn' * ``` - * @param prefixUrl {string} - * @return {HttpClientBuilder} */ - prefixUrl(prefixUrl) { - this.#options.prefixUrl = prefixUrl + public prefixUrl(prefixUrl: string): HttpClientBuilder { + this.options.prefixUrl = prefixUrl return this } /** * Set the request method. - * - * @param method {import('got').Method} - * @return {HttpClientBuilder} */ - method(method) { - this.#options.method = method + public method(method: Method): HttpClientBuilder { + this.options.method = method return this } /** * Set the request url. - * - * @param url {string} - * @return {HttpClientBuilder} */ - url(url) { + public url(url: string | URL): HttpClientBuilder { + if (url instanceof URL) { + this.options.url = url + + return this + } + if (url.startsWith('/')) { url = url.replace('/', '') } - this.#options.url = url + this.options.url = url return this } @@ -558,12 +531,9 @@ export class HttpClientBuilder { * Cookie support. You don't have to care about parsing or how to store them. * * __Note__: If you provide this option, `options.headers.cookie` will be overridden. - * - * @param jar {import('got').PromiseCookieJar | import('got').ToughCookieJar} - * @return {HttpClientBuilder} */ - cookieJar(jar) { - this.#options.cookieJar = jar + public cookieJar(jar: PromiseCookieJar | ToughCookieJar): HttpClientBuilder { + this.options.cookieJar = jar return this } @@ -585,12 +555,9 @@ export class HttpClientBuilder { * abortController.abort(); * }, 100); * ``` - * - * @param signal {any} - * @return {HttpClientBuilder} */ - signal(signal) { - this.#options.signal = signal + public signal(signal: any): HttpClientBuilder { + this.options.signal = signal return this } @@ -598,12 +565,9 @@ export class HttpClientBuilder { /** * Ignore invalid cookies instead of throwing an error. * Only useful when the `cookieJar` option has been set. Not recommended. - * - * @param ignore {boolean} - * @return {HttpClientBuilder} */ - ignoreInvalidCookies(ignore) { - this.#options.ignoreInvalidCookies = ignore + public ignoreInvalidCookies(ignore: boolean): HttpClientBuilder { + this.options.ignoreInvalidCookies = ignore return this } @@ -623,34 +587,25 @@ export class HttpClientBuilder { * console.log(searchParams.toString()); * //=> 'key=a&key=b' * ``` - * - * @param value { string | import('got').SearchParameters | URLSearchParams } - * @return {HttpClientBuilder} */ - searchParams(value) { - this.#options.searchParams = value + public searchParams(value: Query): HttpClientBuilder { + this.options.searchParams = value return this } /** * Alias for the searchParams method. - * - * @param value { string | import('got').SearchParameters | URLSearchParams } - * @return {HttpClientBuilder} */ - queryParams(value) { + public queryParams(value: Query): HttpClientBuilder { return this.searchParams(value) } /** * Set the dnsLookup parameter. - * - * @param lookup {import('cacheable-lookup').default.lookup} - * @return {HttpClientBuilder} */ - dnsLookup(lookup) { - this.#options.dnsLookup = lookup + public dnsLookup(lookup: CacheableLookup['lookup']): HttpClientBuilder { + this.options.dnsLookup = lookup return this } @@ -662,12 +617,9 @@ export class HttpClientBuilder { * `CacheableLookup` uses `dns.resolver4(..)` and `dns.resolver6(...)` under the hood and fall backs to `dns.lookup(...)` when the first two fail, which may lead to additional delay. * * __Note__: This should stay disabled when making requests to internal hostnames such as `localhost`, `database.local` etc. - * - * @param cache {import('cacheable-lookup').default | boolean} - * @return {HttpClientBuilder} */ - dnsCache(cache) { - this.#options.dnsCache = cache + public dnsCache(cache: CacheableLookup | boolean): HttpClientBuilder { + this.options.dnsCache = cache return this } @@ -693,12 +645,9 @@ export class HttpClientBuilder { * // Let's see the headers * console.log(response.body) * ``` - * - * @param context {Record} - * @return {HttpClientBuilder} */ - context(context) { - this.#options.context = context + public context(context: any | Record): HttpClientBuilder { + this.options.context = context return this } @@ -706,12 +655,9 @@ export class HttpClientBuilder { /** * Hooks allow modifications during the request lifecycle. * Hook functions may be async and are run serially. - * - * @param hooks {import('got').Hooks} - * @return {HttpClientBuilder} */ - hooks(hooks) { - this.#options.hooks = hooks + public hooks(hooks: Hooks): HttpClientBuilder { + this.options.hooks = hooks return this } @@ -721,12 +667,9 @@ export class HttpClientBuilder { * * Note that if a `303` is sent by the server in response to any request type (`POST`, `DELETE`, etc.), Got will automatically request the resource pointed to in the location header via `GET`. * This is in accordance with [the spec](https://tools.ietf.org/html/rfc7231#section-6.4.4). You can optionally turn on this behavior also for other redirect codes - see `methodRewriting`. - * - * @param followRedirect {boolean} - * @return {HttpClientBuilder} */ - followRedirect(followRedirect) { - this.#options.followRedirect = followRedirect + public followRedirect(followRedirect: boolean): HttpClientBuilder { + this.options.followRedirect = followRedirect return this } @@ -736,36 +679,27 @@ export class HttpClientBuilder { * * Note that if a `303` is sent by the server in response to any request type (`POST`, `DELETE`, etc.), Got will automatically request the resource pointed to in the location header via `GET`. * This is in accordance with [the spec](https://tools.ietf.org/html/rfc7231#section-6.4.4). You can optionally turn on this behavior also for other redirect codes - see `methodRewriting`. - * - * @param followRedirect {boolean} - * @return {HttpClientBuilder} */ - followRedirects(followRedirect) { - this.#options.followRedirect = followRedirect + public followRedirects(followRedirect: boolean): HttpClientBuilder { + this.options.followRedirect = followRedirect return this } /** * If exceeded, the request will be aborted and a `MaxRedirectsError` will be thrown. - * - * @param maxRedirects {number} - * @return {HttpClientBuilder} */ - maxRedirects(maxRedirects) { - this.#options.maxRedirects = maxRedirects + public maxRedirects(maxRedirects: number): HttpClientBuilder { + this.options.maxRedirects = maxRedirects return this } /** * A cache adapter instance for storing cached response data. - * - * @param cache {string | import('keyv').Store | boolean } - * @return {HttpClientBuilder} */ - cache(cache) { - this.#options.cache = cache + public cache(cache: string | Store | boolean): HttpClientBuilder { + this.options.cache = cache return this } @@ -775,34 +709,27 @@ export class HttpClientBuilder { * * If this is disabled, requests that encounter an error status code will be resolved with the `response` instead of throwing. * This may be useful if you are checking for resource availability and are expecting error responses. - * - * @param throwHttpErrors {boolean} - * @return {HttpClientBuilder} */ - throwHttpErrors(throwHttpErrors) { - this.#options.throwHttpErrors = throwHttpErrors + public throwHttpErrors(throwHttpErrors: boolean): HttpClientBuilder { + this.options.throwHttpErrors = throwHttpErrors return this } /** * Set the username. - * - * @param value {string} */ - username(value) { - this.#options.username = value + public username(value: string): HttpClientBuilder { + this.options.username = value return this } /** * Set the password. - * - * @param value {string} */ - password(value) { - this.#options.password = value + public password(value: string): HttpClientBuilder { + this.options.password = value return this } @@ -825,12 +752,9 @@ export class HttpClientBuilder { * console.log(headers.via) * //=> '2 nghttpx' * ``` - * - * @param value {boolean} - * @return {HttpClientBuilder} */ - http2(value) { - this.#options.http2 = value + public http2(value: boolean): HttpClientBuilder { + this.options.http2 = value return this } @@ -841,12 +765,9 @@ export class HttpClientBuilder { * This option is only meant to interact with non-compliant servers when you have no other choice. * * __Note__: The [RFC 7231](https://tools.ietf.org/html/rfc7231#section-4.3.1) doesn't specify any particular behavior for the GET method having a payload, therefore __it's considered an [anti-pattern](https://en.wikipedia.org/wiki/Anti-pattern)__. - * - * @param value {boolean} - * @return {HttpClientBuilder} */ - allowGetBody(value) { - this.#options.allowGetBody = value + public allowGetBody(value: boolean): HttpClientBuilder { + this.options.allowGetBody = value return this } @@ -858,12 +779,9 @@ export class HttpClientBuilder { * Setting `methodRewriting` to `true` will also rewrite `301` and `302` responses, as allowed by the spec. This is the behavior followed by `curl` and browsers. * * __Note__: Got never performs method rewriting on `307` and `308` responses, as this is [explicitly prohibited by the specification](https://www.rfc-editor.org/rfc/rfc7231#section-6.4.7). - * - * @param value {boolean} - * @return {HttpClientBuilder} */ - methodRewriting(value) { - this.#options.methodRewriting = value + public methodRewriting(value: boolean): HttpClientBuilder { + this.options.methodRewriting = value return this } @@ -875,12 +793,9 @@ export class HttpClientBuilder { * - `undefined`: IPv4 (if present) or IPv6 * - `4`: Only IPv4 * - `6`: Only IPv6 - * - * @param dnsLookupIpVersion {import('got').DnsLookupIpVersion} - * @return {HttpClientBuilder} */ - dnsLookupIpVersion(dnsLookupIpVersion) { - this.#options.dnsLookupIpVersion = dnsLookupIpVersion + public dnsLookupIpVersion(dns: DnsLookupIpVersion): HttpClientBuilder { + this.options.dnsLookupIpVersion = dns return this } @@ -900,12 +815,9 @@ export class HttpClientBuilder { * * console.log(parsed) * ``` - * - * @param fn {import('got').ParseJsonFunction} - * @return {HttpClientBuilder} */ - parseJson(fn) { - this.#options.parseJson = fn + public parseJson(fn: ParseJsonFunction): HttpClientBuilder { + this.options.parseJson = fn return this } @@ -928,12 +840,9 @@ export class HttpClientBuilder { * })) * .request() * ``` - * - * @param fn {import('got').StringifyJsonFunction} - * @return {HttpClientBuilder} */ - stringifyJson(fn) { - this.#options.stringifyJson = fn + public stringifyJson(fn: StringifyJsonFunction): HttpClientBuilder { + this.options.stringifyJson = fn return this } @@ -959,12 +868,9 @@ export class HttpClientBuilder { * * __Note__: If `maxRetryAfter` is set to `undefined`, it will use `options.timeout`. * __Note__: If [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) header is greater than `maxRetryAfter`, it will cancel the request. - * - * @param retry {Partial} - * @return {HttpClientBuilder} */ - retry(retry) { - this.#options.retry = retry + public retry(retry: Partial): HttpClientBuilder { + this.options.retry = retry return this } @@ -974,16 +880,13 @@ export class HttpClientBuilder { * * The strategy function needs to return the delay between the execution count * of each request, if the strategy function returns 0, the retry is canceled. - * - * @param strategy {(response: import('got').RequestError, execCount: number, retryObject: import('got').RetryObject) => number | Promise} - * @return {HttpClientBuilder} */ - retryStrategy(strategy) { - if (!this.#options.retry) { - this.#options.retry = {} + public retryStrategy(strategy: RetryStrategyCallback): HttpClientBuilder { + if (!this.options.retry) { + this.options.retry = {} } - this.#options.retry.calculateDelay = ({ + this.options.retry.calculateDelay = ({ error, retryAfter, attemptCount, @@ -1006,36 +909,27 @@ export class HttpClientBuilder { * From `http.RequestOptions`. * * The IP address used to send the request from. - * - * @param localAddress {string} - * @return {HttpClientBuilder} */ - localAddress(localAddress) { - this.#options.localAddress = localAddress + public localAddress(localAddress: string): HttpClientBuilder { + this.options.localAddress = localAddress return this } /** * Set the createConnection options. - * - * @param value {import('got').CreateConnectionFunction} - * @return {HttpClientBuilder} */ - createConnection(value) { - this.#options.createConnection = value + public createConnection(value: CreateConnectionFunction): HttpClientBuilder { + this.options.createConnection = value return this } /** * Options for the advanced HTTPS API. - * - * @param https {import('got').HttpsOptions} - * @return {HttpClientBuilder} */ - https(https) { - this.#options.https = https + public https(https: HttpsOptions): HttpClientBuilder { + this.options.https = https return this } @@ -1047,12 +941,9 @@ export class HttpClientBuilder { * Don't set this option to `null`. * * __Note__: This doesn't affect streams! Instead, you need to do `got.stream(...).setEncoding(encoding)`. - * - * @param encoding {BufferEncoding} - * @return {HttpClientBuilder} */ - encoding(encoding) { - this.#options.encoding = encoding + public encoding(encoding: BufferEncoding): HttpClientBuilder { + this.options.encoding = encoding return this } @@ -1060,25 +951,9 @@ export class HttpClientBuilder { /** * When set to `true` the promise will return the * Response body instead of the Response object. - * - * @param resolveBodyOnly {boolean} - * @return {HttpClientBuilder} - */ - resolveBodyOnly(resolveBodyOnly) { - this.#options.resolveBodyOnly = resolveBodyOnly - - return this - } - - /** - * Returns a `Stream` instead of a `Promise`. - * This is equivalent to calling `got.stream(url, options?)`. - * - * @param value {boolean} - * @return {HttpClientBuilder} */ - isStream(value) { - this.#options.isStream = value + public resolveBodyOnly(resolveBodyOnly: boolean): HttpClientBuilder { + this.options.resolveBodyOnly = resolveBodyOnly return this } @@ -1112,245 +987,162 @@ export class HttpClientBuilder { * // is semantically the same as this * const body = await HttpClient.get(url, { responseType: 'json', resolveBodyOnly: true }) * ``` - * - * @param type {import('got').ResponseType} - * @return {HttpClientBuilder} */ - responseType(type) { - this.#options.responseType = type + public responseType(type: ResponseType): HttpClientBuilder { + this.options.responseType = type as any return this } /** * Set pagination options. - * - * @param options {import('got').PaginationOptions} - * @return {HttpClientBuilder} - */ - pagination(options) { - this.#options.pagination = options - - return this - } - - /** - * Set the auth option. - * - * @param value {any} - * @return {HttpClientBuilder} */ - auth(value) { - this.#options.auth = value + public pagination( + options: PaginationOptions, + ): HttpClientBuilder { + this.options.pagination = options return this } /** * Set the host option. - * - * @param value {boolean} - * @return {HttpClientBuilder} */ - setHost(value) { - this.#options.setHost = value + public setHost(value: boolean): HttpClientBuilder { + this.options.setHost = value return this } /** * Set the maxHeaderSize option. - * - * @param maxHeaderSize {number} - * @return {HttpClientBuilder} */ - maxHeaderSize(maxHeaderSize) { - this.#options.maxHeaderSize = maxHeaderSize + public maxHeaderSize(maxHeaderSize: number): HttpClientBuilder { + this.options.maxHeaderSize = maxHeaderSize return this } /** * Set the enableUnixSockets option. - * - * @param enableUnixSockets {boolean} - * @return {HttpClientBuilder} */ - enableUnixSockets(enableUnixSockets) { - this.#options.enableUnixSockets = enableUnixSockets + public enableUnixSockets(enableUnixSockets: boolean): HttpClientBuilder { + this.options.enableUnixSockets = enableUnixSockets return this } /** * Set the merge options. - * - * @param options {import('got').OptionsInit} - * @return {HttpClientBuilder} */ - mergeOptions(options) { - this.#options = { ...this.#options, ...options } + public mergeOptions(options: ReqOptions): HttpClientBuilder { + this.options = { ...this.options, ...options } + return this } /** * Execute the request and return as stream. - * - * @param [options] {import('got').OptionsInit} - * @return {Request} */ - stream(options) { - return got.stream({ ...this.#options, ...options }) + public stream(options: ReqOptions = {}): Request { + return got.stream({ ...this.options, ...options } as any) } /** * Execute the request and return paginated data. - * - * @param [options] {import('got').OptionsInit} - * @return {AsyncIterableIterator} */ - paginate(options) { - return got.paginate({ ...this.#options, ...options }) + public paginate(options: ReqOptions = {}): AsyncIterableIterator { + return got.paginate({ ...this.options, ...options } as any) } /** * Execute the request using all the options defined. - * - * @param [options] {import('got').OptionsInit} - * @return {import('got').CancelableRequest> | import('got').CancelableRequest | Request} */ - request(options = {}) { - return got({ ...this.#options, ...options }) + public request(options: ReqOptions = {}) { + return got({ ...this.options, ...options } as any) } /** * Make a GET request. - * - * @param [url] {string} - * @param [options] {import('got').OptionsInit} - * @return {import('got').CancelableRequest> | import('got').CancelableRequest | Request} */ - get(url, options = {}) { - this.method('GET').url(url || options.url || this.#options.url) - - if (this.#options.isStream) { - return this.stream(options) - } - - return this.request(options) + public get(url?: string | URL, options: ReqOptions = {}) { + return this.method('GET') + .url(url || options.url || this.options.url) + .request(options) } /** * Make a POST request. - * - * @param [url] {string} - * @param [body] {Record | string | ReadableStream | Generator | AsyncGenerator | import('form-data-encoder').FormDataLike} - * @param [options] {import('got').OptionsInit} - * @return {import('got').CancelableRequest> | import('got').CancelableRequest | Request} */ - post(url, body, options = {}) { - this.method('POST') - .url(url || options.url || this.#options.url) - .body(body || options.body || this.#options.body || {}) - - if (this.#options.isStream) { - return this.stream(options) - } - - return this.request(options) + public post( + url?: string | URL, + body?: Body, + options: ReqOptions = {}, + ) { + return this.method('POST') + .url(url || options.url || this.options.url) + .body(body || options.body || this.options.body || {}) + .request(options) } /** * Make a PUT request. - * - * @param [url] {string} - * @param [body] {Record | string | ReadableStream | Generator | AsyncGenerator | import('form-data-encoder').FormDataLike} - * @param [options] {import('got').OptionsInit} - * @return {import('got').CancelableRequest> | import('got').CancelableRequest | Request} */ - put(url, body, options = {}) { - this.method('PUT') - .url(url || options.url || this.#options.url) - .body(body || options.body || this.#options.body || {}) - - if (this.#options.isStream) { - return this.stream(options) - } - - return this.request(options) + public put( + url?: string | URL, + body?: Body, + options: ReqOptions = {}, + ) { + return this.method('PUT') + .url(url || options.url || this.options.url) + .body(body || options.body || this.options.body || {}) + .request(options) } /** * Make a PATCH request. - * - * @param [url] {string} - * @param [body] {Record | string | ReadableStream | Generator | AsyncGenerator | import('form-data-encoder').FormDataLike} - * @param [options] {import('got').OptionsInit} - * @return {import('got').CancelableRequest> | import('got').CancelableRequest | Request} */ - patch(url, body, options = {}) { - this.method('PATCH') - .url(url || options.url || this.#options.url) - .body(body || options.body || this.#options.body || {}) - - if (this.#options.isStream) { - return this.stream(options) - } - - return this.request(options) + public patch( + url?: string | URL, + body?: Response, + options: ReqOptions = {}, + ) { + return this.method('PATCH') + .url(url || options.url || this.options.url) + .body(body || options.body || this.options.body || {}) + .request(options) } /** * Make a DELETE request. - * - * @param [url] {string} - * @param [options] {import('got').OptionsInit} - * @return {import('got').CancelableRequest> | import('got').CancelableRequest | Request} */ - delete(url, options = {}) { - this.method('DELETE').url(url || options.url || this.#options.url) - - if (this.#options.isStream) { - return this.stream(options) - } - - return this.request(options) + public delete(url?: string | URL, options: ReqOptions = {}) { + return this.method('DELETE') + .url(url || options.url || this.options.url) + .request(options) } /** * Make a HEAD request. - * - * @param [url] {string} - * @param [options] {import('got').OptionsInit} - * @return {import('got').CancelableRequest> | import('got').CancelableRequest | Request} */ - head(url, options = {}) { - this.method('HEAD').url(url || options.url || this.#options.url) - - if (this.#options.isStream) { - return this.stream(options) - } - - return this.request(options) + public head(url?: string | URL, options: ReqOptions = {}) { + return this.method('HEAD') + .url(url || options.url || this.options.url) + .request(options) } } export class HttpClient { /** * The global builder used in all HttpClient static requests. - * - * @type {HttpClientBuilder} */ - static #builder = new HttpClientBuilder() + private static _builder = new HttpClientBuilder() /** * Set the global builder for HttpClient. - * - * @param builder {HttpClientBuilder} - * @return {typeof HttpClient} */ - static setBuilder(builder) { - this.#builder = builder + public static setBuilder(builder: HttpClientBuilder): typeof HttpClient { + this._builder = builder return this } @@ -1358,84 +1150,62 @@ export class HttpClient { /** * Uses the instance of HttpClientBuilder or creates * a new one. - * - * @param [newBuilder] {boolean} - * @return {HttpClientBuilder} */ - static builder(newBuilder = false) { + public static builder(newBuilder = false): HttpClientBuilder { if (newBuilder) { return new HttpClientBuilder() } - return new HttpClientBuilder(this.#builder.getOptions()) + return new HttpClientBuilder(this._builder.getOptions()) } /** * Make a GET request. - * - * @param [url] {string} - * @param [options] {import('got').OptionsInit} - * @return {import('got').CancelableRequest> | import('got').CancelableRequest | Request} */ - static get(url, options) { - return this.#builder.get(url, options) + public static get(url?: string | URL, options?: ReqOptions) { + return this._builder.get(url, options) } /** * Make a POST request. - * - * @param [url] {string} - * @param [body] {Record | string | ReadableStream | Generator | AsyncGenerator | import('form-data-encoder').FormDataLike} - * @param [options] {import('got').OptionsInit} - * @return {import('got').CancelableRequest> | import('got').CancelableRequest | Request} */ - static post(url, body, options) { - return this.#builder.post(url, body, options) + public static post( + url?: string | URL, + body?: Body, + options?: ReqOptions, + ) { + return this._builder.post(url, body, options) } /** * Make a PUT request. - * - * @param [url] {string} - * @param [body] {Record | string | ReadableStream | Generator | AsyncGenerator | import('form-data-encoder').FormDataLike} - * @param [options] {import('got').OptionsInit} - * @return {import('got').CancelableRequest> | import('got').CancelableRequest | Request} */ - static put(url, body, options) { - return this.#builder.put(url, body, options) + public static put( + url?: string | URL, + body?: Body, + options?: ReqOptions, + ) { + return this._builder.put(url, body, options) } /** * Make a PATCH request. - * - * @param [url] {string} - * @param [body] {Record | string | ReadableStream | Generator | AsyncGenerator | import('form-data-encoder').FormDataLike} - * @param [options] {import('got').OptionsInit} - * @return {import('got').CancelableRequest> | import('got').CancelableRequest | Request} */ - static patch(url, body, options) { - return this.#builder.patch(url, body, options) + static patch(url?: string | URL, body?: Body, options?: ReqOptions) { + return this._builder.patch(url, body, options) } /** * Make a DELETE request. - * - * @param [url] {string} - * @param [options] {import('got').OptionsInit} - * @return {import('got').CancelableRequest> | import('got').CancelableRequest | Request} */ - static delete(url, options) { - return this.#builder.delete(url, options) + public static delete(url?: string | URL, options?: ReqOptions) { + return this._builder.delete(url, options) } /** * Make a HEAD request. - * - * @param [url] {string} - * @param [options] {import('got').OptionsInit} - * @return {import('got').CancelableRequest> | import('got').CancelableRequest | Request} */ - static head(url, options) { - return this.#builder.head(url, options) + public static head(url?: string | URL, options?: ReqOptions) { + return this._builder.head(url, options) } } diff --git a/src/Helpers/Is.js b/src/Helpers/Is.ts similarity index 51% rename from src/Helpers/Is.js rename to src/Helpers/Is.ts index 8d689c3..0c8cee9 100644 --- a/src/Helpers/Is.js +++ b/src/Helpers/Is.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/ban-types */ /** * @athenna/common * @@ -16,12 +17,8 @@ import { isCep, isCnpj, isCpf } from 'validator-brazil' export class Is { /** * Return the kindOf. - * - * @private - * @param {any} value - * @return {any} */ - static #kindOf(value) { + public static kindOf(value: any): string { const kind = kindOf(value) if ( @@ -36,21 +33,27 @@ export class Is { /** * Verify if is valid Uuid. - * - * @param {string} value - * @return {boolean} */ - static Uuid(value) { + public static Uuid(value: string): boolean { return validate(value) } + /** + * Verify if the value is defined, even + * with falsy values like false and ''. + */ + public static Defined(value: any): boolean { + if (value === undefined || value === null) { + return false + } + + return true + } + /** * Verify if is valid Json. - * - * @param {string} value - * @return {boolean} */ - static Json(value) { + public static Json(value: string): boolean { try { JSON.parse(value) @@ -62,11 +65,8 @@ export class Is { /** * Verify if is valid Ip. - * - * @param {string} value - * @return {boolean} */ - static Ip(value) { + public static Ip(value: string): boolean { // Removes http/https and port/route values value = value.replace(/^https?:\/\//, '').split(':')[0] @@ -75,11 +75,8 @@ export class Is { /** * Verify if is valid Empty. - * - * @param {string|any|any[]} value - * @return {boolean} */ - static Empty(value) { + public static Empty(value: string | any | any[]): boolean { if (!value) { return true } @@ -101,47 +98,41 @@ export class Is { /** * Verify if is a valid Cep. - * - * @param {string|number} cep - * @return {boolean} */ - static Cep(cep) { - if (typeof cep === 'number') cep = cep.toString() + public static Cep(cep: string | number): boolean { + if (Is.Number(cep)) { + cep = cep.toString() + } return isCep(cep) } /** * Verify if is a valid Cpf. - * - * @param {string|number} cpf - * @return {boolean} */ - static Cpf(cpf) { - if (typeof cpf === 'number') cpf = cpf.toString() + public static Cpf(cpf: string | number): boolean { + if (Is.Number(cpf)) { + cpf = cpf.toString() + } return isCpf(cpf) } /** * Verify if is a valid Cnpj. - * - * @param {string|number} cnpj - * @return {boolean} */ - static Cnpj(cnpj) { - if (typeof cnpj === 'number') cnpj = cnpj.toString() + public static Cnpj(cnpj: string | number): boolean { + if (Is.Number(cnpj)) { + cnpj = cnpj.toString() + } return isCnpj(cnpj) } /** * Verify if is a valid Async function. - * - * @param {any} value - * @return {boolean} */ - static Async(value) { + public static Async(value: any): boolean { const fnString = value.toString().trim() const validation = !!( @@ -153,161 +144,113 @@ export class Is { /** * Verify if is a valid Undefined. - * - * @param {any} value - * @return {boolean} */ - static Undefined(value) { - return Is.#kindOf(value) === 'undefined' + public static Undefined(value: any): value is undefined { + return Is.kindOf(value) === 'undefined' } /** * Verify if is a valid Null. - * - * @param {any} value - * @return {boolean} */ - static Null(value) { - return Is.#kindOf(value) === 'null' + public static Null(value: any): value is null { + return Is.kindOf(value) === 'null' } /** * Verify if is a valid Boolean. - * - * @param {any} value - * @return {boolean} */ - static Boolean(value) { - return Is.#kindOf(value) === 'boolean' + public static Boolean(value: any): value is boolean { + return Is.kindOf(value) === 'boolean' } /** * Verify if is a valid Buffer. - * - * @param {any} value - * @return {boolean} */ - static Buffer(value) { - return Is.#kindOf(value) === 'buffer' + public static Buffer(value: any): value is Buffer { + return Is.kindOf(value) === 'buffer' } /** * Verify if is a valid Number. - * - * @param {any} value - * @return {boolean} */ - static Number(value) { - return Is.#kindOf(value) === 'number' + public static Number(value: any): value is number { + return Is.kindOf(value) === 'number' } /** * Verify if is a valid String. - * - * @param {any} value - * @return {boolean} */ - static String(value) { - return Is.#kindOf(value) === 'string' + public static String(value: any): value is string { + return Is.kindOf(value) === 'string' } /** * Verify if is a valid Object. - * - * @param {any} value - * @return {boolean} */ - static Object(value) { - return Is.#kindOf(value) === 'object' + public static Object(value: any): value is object | Record { + return Is.kindOf(value) === 'object' } /** * Verify if is a valid Date. - * - * @param {any} value - * @return {boolean} */ - static Date(value) { - return Is.#kindOf(value) === 'date' + public static Date(value: any): value is Date { + return Is.kindOf(value) === 'date' } /** * Verify if is a valid Array. - * - * @param {any} value - * @return {boolean} */ - static Array(value) { - return Is.#kindOf(value) === 'array' + public static Array(value: any): value is Array { + return Is.kindOf(value) === 'array' } /** * Verify if is a valid Regexp. - * - * @param {any} value - * @return {boolean} */ - static Regexp(value) { - return Is.#kindOf(value) === 'regexp' + public static Regexp(value: any): value is RegExp { + return Is.kindOf(value) === 'regexp' } /** * Verify if is a valid Error. - * - * @param {any} value - * @return {boolean} */ - static Error(value) { - return Is.#kindOf(value) === 'error' + public static Error(value: any): value is Error { + return Is.kindOf(value) === 'error' } /** * Verify if is a valid Function. - * - * @param {any} value - * @return {boolean} */ - static Function(value) { - return Is.#kindOf(value) === 'function' + public static Function(value: any): value is Function { + return Is.kindOf(value) === 'function' } /** * Verify if is a valid Class. - * - * @param {any} value - * @return {boolean} */ - static Class(value) { - return Is.#kindOf(value) === 'class' + public static Class(value: any): boolean { + return Is.kindOf(value) === 'class' } /** * Verify if is a valid Integer. - * - * @param {any} value - * @return {boolean} */ - static Integer(value) { + public static Integer(value: any): value is number { return Number.isInteger(value) } /** * Verify if is a valid Float. - * - * @param {any} value - * @return {boolean} */ - static Float(value) { + public static Float(value: any): value is number { return value !== (value | 0) } /** * Verify if is a valid ArrayOfObjects. - * - * @param {any[]} value - * @return {boolean} */ - static ArrayOfObjects(value) { + public static ArrayOfObjects(value: any[]): value is Array { if (!value.length) return false const results = value.map(v => Is.Object(v)) diff --git a/src/Helpers/Json.js b/src/Helpers/Json.js deleted file mode 100644 index 629069d..0000000 --- a/src/Helpers/Json.js +++ /dev/null @@ -1,143 +0,0 @@ -/** - * @athenna/common - * - * (c) João Lenon - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -import lodash from 'lodash' - -export class Json { - /** - * Deep copy any object properties without reference. - * - * @param {any} object - * @return {any} - */ - static copy(object) { - return lodash.cloneDeep(object) - } - - /** - * Find all JSON inside string and return it. - * - * @param {string} text - * @return {string[]} - */ - static getJson(text) { - let match - const json = [] - - while ((match = /{(?:[^{}])*}/.exec(text)) !== null) { - text = text.replace(match[0], '') - - json.push(match[0]) - } - - return json - } - - /** - * Reviver callback. - * - * @callback reviver - * @param {any} this - * @param {string} key - * @param {any} value - * @return any - */ - - /** - * Converts a JSON string into an object without exception. - * - * @param {string} text - * @param {reviver?} reviver - * @return {any} - */ - static parse(text, reviver) { - try { - return JSON.parse(text, reviver) - } catch (error) { - return null - } - } - - /** - * Observe changes inside objects. - * - * @param {any} object - * @param {function} func - * @param {...any[]} args - * @return {any} - */ - static observeChanges(object, func, ...args) { - return new Proxy(object, { - set: (target, key, value) => { - func(value, ...args) - - target[key] = value - - return true - }, - }) - } - - /** - * Remove all keys from data that is not inside array keys. - * - * @param {any} data - * @param {any[]} keys - * @return {any[]} - */ - static fillable(data, keys) { - return keys.reduce((previous, key) => { - if (data[key]) { - previous[key] = data[key] - } - - return previous - }, {}) - } - - /** - * Remove all duplicated values from the array. - * - * @deprecated Use the Collection.removeDuplicated method. - * @param {any[]} array - * @return {any[]} - */ - static removeDuplicated(array) { - return [...new Set(array)] - } - - /** - * Raffle any value from the array. - * - * @deprecated Use the Collection.random method. - * @param {any[]} array - * @return {any} - */ - static raffle(array) { - const index = Math.random() * array.length - - return array[Math.floor(index)] - } - - /** - * Get the object properties based on key. - * - * @param {string} key - * @param {any} [defaultValue] - * @param {any} object - * @return {any|undefined} - */ - static get(object, key, defaultValue) { - if (key === '' && object) { - return object - } - - return lodash.get(object, key, defaultValue) - } -} diff --git a/src/Helpers/Json.ts b/src/Helpers/Json.ts new file mode 100644 index 0000000..21f6182 --- /dev/null +++ b/src/Helpers/Json.ts @@ -0,0 +1,325 @@ +/** + * @athenna/common + * + * (c) João Lenon + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import lodash from 'lodash' + +import { Is } from './Is.js' +import { Options } from './Options.js' + +export type ObjectBuilderOptions = { + /** + * The global default value that is going + * to be used if the value that is being set + * is undefined or null. + * + * @default null + */ + defaultValue?: any + + /** + * Ignore null values that are going to be set + * in the object. If some value is null, it will + * not be set inside the object. + * + * @default false + */ + ignoreNull?: boolean + + /** + * Ignore undefined values that are going to be set + * in the object. If some value is undefined, it will + * not be set inside the object. + * + * @default true + */ + ignoreUndefined?: boolean +} + +export class ObjectBuilder { + /** + * The real object that is being built. + */ + private object: any + + /** + * The object builder options that are + * going to be used to shape the object. + */ + private options: ObjectBuilderOptions + + public constructor(options?: ObjectBuilderOptions) { + this.options = Options.create(options, { + ignoreNull: false, + ignoreUndefined: true, + defaultValue: null, + }) + + this.object = {} + } + + /** + * Set a value in the object or fallback to defaultValue. + * + * @example + * const object = Object.builder() + * .set('hello.world', 'hello world!') + * .get() + * + * console.log(object.hello.world) + */ + public set(key: string, value: any, defaultValue?: any): this { + if (this.isDefinedDefaultValue(defaultValue) && !Is.Defined(value)) { + lodash.set( + this.object, + key.split('.'), + Json.copy(defaultValue || this.options.defaultValue), + ) + + return this + } + + if (this.options.ignoreNull && value === null) { + return this + } + + if (this.options.ignoreUndefined && value === undefined) { + return this + } + + lodash.set(this.object, key.split('.'), Json.copy(value)) + + return this + } + + /** + * Delete the configuration key. + */ + public delete(key: string): this { + if (this.notExists(key)) { + return this + } + + const [mainKey, ...keys] = key.split('.') + + if (key === mainKey) { + delete this.object[key] + + return this + } + + const object = this.object[mainKey] + lodash.unset(object, keys.join('.')) + object[mainKey] = object + + return this + } + + /** + * Get the value builded. + */ + public get(key?: string, defaultValue?: any): T { + if (key === undefined) { + return this.object + } + + return Json.get(this.object, key, defaultValue) + } + + /** + * Verify if the object key path has the same value. + */ + public is(key: string, ...values: any | any[]): boolean { + let is = false + values = Is.Array(values[0]) ? values[0] : values + + for (const value of values) { + if (this.get(key) === value) { + is = true + break + } + } + + return is + } + + /** + * Verify if the object key path does not have the same value. + */ + public isNot(key: string, ...values: any | any[]): boolean { + return !this.is(key, ...values) + } + + /** + * Verify if key path exists in object. + */ + public exists(key: string): boolean { + return !!this.get(key) + } + + /** + * Verify if key path does not exists in object. + */ + public notExists(key: string): boolean { + return !this.exists(key) + } + + /** + * Verify if all the object keys exists. + */ + public existsAll(...keys: string[]): boolean { + let existsAll = true + keys = Is.Array(keys[0]) ? keys[0] : keys + + for (const key of keys) { + if (this.notExists(key)) { + existsAll = false + + break + } + } + + return existsAll + } + + /** + * Verify if all the object keys does not exist. + */ + public notExistsAll(...keys: string[]): boolean { + return !this.existsAll(...keys) + } + + /** + * Verify if defaultValue or global default value option + * is defined. + */ + private isDefinedDefaultValue(defaultValue: string): boolean { + return Is.Defined(defaultValue) || Is.Defined(this.options.defaultValue) + } +} + +export class Json { + /** + * Create a new instance of ObjectBuilder class. + * This class is responsible to build new objects + * in a more easy way, removing null and undefined values + * and setting default values in options. + */ + public static builder(options?: ObjectBuilderOptions): ObjectBuilder { + return new ObjectBuilder(options) + } + + /** + * Deep copy any object properties without reference. + */ + public static copy(object: any): any { + return lodash.cloneDeep(object) + } + + /** + * Find all JSON inside string and return it. + */ + public static getJson(text: string): string[] { + let match + const json = [] + + while ((match = /{(?:[^{}])*}/.exec(text)) !== null) { + text = text.replace(match[0], '') + + json.push(match[0]) + } + + return json + } + + /** + * Converts a JSON string into an object without exception. + */ + public static parse( + text: string, + reviver?: (this: any, key: string, value: any) => any, + ): any { + try { + return JSON.parse(text, reviver) + } catch (error) { + return null + } + } + + /** + * Observe changes inside objects. + * + * @param {any} object + * @param {function} func + * @param {...any[]} args + * @return {any} + */ + public static observeChanges(object: any, func: any, ...args: any[]): any { + return new Proxy(object, { + set: (target, key, value) => { + func(value, ...args) + + target[key] = value + + return true + }, + }) + } + + /** + * Remove all keys from data that is not inside array keys. + * + * @param {any} data + * @param {any[]} keys + * @return {any[]} + */ + public static fillable(data: any, keys: any[]): any[] { + return keys.reduce((previous, key) => { + if (data[key]) { + previous[key] = data[key] + } + + return previous + }, {}) + } + + /** + * Remove all duplicated values from the array. + * + * @deprecated Use the Collection.removeDuplicated method. + */ + public static removeDuplicated(array: any[]): any[] { + return [...new Set(array)] + } + + /** + * Raffle any value from the array. + * + * @deprecated Use the Collection.random method. + */ + public static raffle(array: any[]): any { + const index = Math.random() * array.length + + return array[Math.floor(index)] + } + + /** + * Get the object properties based on key. + */ + public static get( + object: T, + key: string, + defaultValue: any = undefined, + ): T | undefined { + if (key === '' && object) { + return object + } + + return lodash.get(object, key, defaultValue) + } +} diff --git a/src/Helpers/Module.js b/src/Helpers/Module.ts similarity index 54% rename from src/Helpers/Module.js rename to src/Helpers/Module.ts index ca4418c..4993c8a 100644 --- a/src/Helpers/Module.js +++ b/src/Helpers/Module.ts @@ -8,18 +8,15 @@ */ import { dirname } from 'node:path' +import { createRequire } from 'node:module' +import { Path, File, Folder } from '#src/index' import { fileURLToPath, pathToFileURL } from 'node:url' -import { Folder, Path } from '#src/index' - export class Module { /** * Get the module first export match or default. - * - * @param {any|Promise} module - * @return {Promise} */ - static async get(module) { + public static async get(module: any | Promise): Promise { module = await module if (module.default) { @@ -30,13 +27,21 @@ export class Module { } /** - * Get the module first export match or default with alias. + * Get the module first export match or default with an alias. + * + * @example + * const _module = import('#app/Services/MyService') + * const _alias = 'App/Services' + * + * const { alias, module } = Module.getWithAlias(_module, _alias) * - * @param {any|Promise} module - * @param {string} subAlias - * @return {Promise<{ alias: string, module: any }>} + * console.log(alias) // 'App/Services/MyService' + * console.log(module) // [class MyService] */ - static async getWithAlias(module, subAlias) { + public static async getWithAlias( + module: any | Promise, + subAlias: string, + ): Promise<{ alias: string; module: any }> { module = await Module.get(module) if (!subAlias.endsWith('/')) { @@ -51,25 +56,29 @@ export class Module { /** * Get all modules first export match or default and return * as array. - * - * @param {any[]|Promise} modules - * @return {Promise} */ - static async getAll(modules) { + public static async getAll(modules: any[]): Promise { const promises = modules.map(m => Module.get(m)) return Promise.all(promises) } /** - * Get all modules first export match or default with alias and return - * as array. + * Get all modules first export match or default with an alias. + * + * @example + * const _modules = [import('#app/Services/MyService')] + * const _alias = 'App/Services' + * + * const [{ alias, module }] = Module.getAllWithAlias(_modules, _alias) * - * @param {any[]|Promise} modules - * @param {string} subAlias - * @return {Promise} + * console.log(alias) // 'App/Services/MyService' + * console.log(module) // [class MyService] */ - static async getAllWithAlias(modules, subAlias) { + public static async getAllWithAlias( + modules: any[], + subAlias: string, + ): Promise<{ alias: string; module: any }[]> { const promises = modules.map(m => Module.getWithAlias(m, subAlias)) return Promise.all(promises) @@ -77,11 +86,8 @@ export class Module { /** * Same as get method, but import the path directly. - * - * @param {string} path - * @return {Promise} */ - static async getFrom(path) { + public static async getFrom(path: string): Promise { const module = await Module.import(path) return Module.get(module) @@ -89,12 +95,11 @@ export class Module { /** * Same as getWithAlias method, but import the path directly. - * - * @param {string} path - * @param {string} subAlias - * @return {Promise<{ alias: string, module: any }>} */ - static async getFromWithAlias(path, subAlias) { + public static async getFromWithAlias( + path: string, + subAlias: string, + ): Promise<{ alias: string; module: any }> { const module = await Module.import(path) return Module.getWithAlias(module, subAlias) @@ -102,11 +107,8 @@ export class Module { /** * Same as getAll method but import everything in the path directly. - * - * @param {string} path - * @return {Promise} */ - static async getAllFrom(path) { + public static async getAllFrom(path: string): Promise { const files = await Module.getAllJSFilesFrom(path) const promises = files.map(file => Module.getFrom(file.path)) @@ -116,12 +118,11 @@ export class Module { /** * Same as getAllWithAlias method but import everything in the path directly. - * - * @param {string} path - * @param {string} subAlias - * @return {Promise<{ alias: string, module: any }[]>} */ - static async getAllFromWithAlias(path, subAlias) { + public static async getAllFromWithAlias( + path: string, + subAlias: string, + ): Promise<{ alias: string; module: any }[]> { const files = await Module.getAllJSFilesFrom(path) const promises = files.map(f => Module.getFromWithAlias(f.path, subAlias)) @@ -131,11 +132,8 @@ export class Module { /** * Verify if folder exists and get all .js files inside. - * - * @param {string} path - * @return {Promise} */ - static async getAllJSFilesFrom(path) { + public static async getAllJSFilesFrom(path: string): Promise { if (!(await Folder.exists(path))) { return [] } @@ -155,22 +153,31 @@ export class Module { /** * Import a full path using the path href to ensure compatibility * between OS's. - * - * @param {string} path - * @return {Promise} */ - static async import(path) { + public static async import(path: string): Promise { return import(pathToFileURL(path).href) } + /** + * Same as import method, but safeImport return null if the + * module does not exist, catching the error throw from bad + * import. + */ + public static async safeImport(path: string): Promise { + try { + return await import(path) + } catch (err) { + return null + } + } + /** * Create the __dirname property. Set in global if necessary. - * - * @param {string} [url] - * @param {boolean} [setInGlobal] - * @return {string} */ - static createDirname(url = import.meta.url, setInGlobal = false) { + public static createDirname( + url = import.meta.url, + setInGlobal = false, + ): string { const __dirname = dirname(Module.createFilename(url, false)) if (setInGlobal) { @@ -182,12 +189,11 @@ export class Module { /** * Create the __filename property. Set in global if necessary. - * - * @param {string} [url] - * @param {boolean} [setInGlobal] - * @return {string} */ - static createFilename(url = import.meta.url, setInGlobal = false) { + public static createFilename( + url = import.meta.url, + setInGlobal = false, + ): string { const __filename = fileURLToPath(url) if (setInGlobal) { @@ -196,4 +202,20 @@ export class Module { return __filename } + + /** + * Create the require function. Set in global if necessary. + */ + public static createRequire( + url = import.meta.url, + setInGlobal = false, + ): NodeRequire { + const require = createRequire(url) + + if (setInGlobal) { + global.require = require + } + + return require + } } diff --git a/src/Helpers/Number.js b/src/Helpers/Number.ts similarity index 68% rename from src/Helpers/Number.js rename to src/Helpers/Number.ts index caa2763..e4da4bd 100644 --- a/src/Helpers/Number.js +++ b/src/Helpers/Number.ts @@ -12,22 +12,19 @@ import { Parser } from '#src/Helpers/Parser' export class Number { /** * Get the higher number from an array of numbers. - * - * @param {number[]} numbers - * @return {number} */ - static getHigher(numbers) { + public static getHigher(numbers: number[]): number { + // eslint-disable-next-line prefer-spread return Math.max.apply(Math, numbers) } /** * Get km radius between two coordinates. - * - * @param {{ latitude: number, longitude: number }} centerCord - * @param {{ latitude: number, longitude: number }} pointCord - * @return {number} */ - static getKmRadius(centerCord, pointCord) { + public static getKmRadius( + centerCord: { latitude: number; longitude: number }, + pointCord: { latitude: number; longitude: number }, + ): number { const deg2rad = deg => deg * (Math.PI / 180) const radius = 6371 @@ -52,32 +49,24 @@ export class Number { /** * Get the lower number from an array of numbers. - * - * @param {number[]} numbers - * @return {number} */ - static getLower(numbers) { + public static getLower(numbers: number[]): number { + // eslint-disable-next-line prefer-spread return Math.min.apply(Math, numbers) } /** * Extract all numbers inside a string and * return as a unique number. - * - * @param {string} string - * @return {number} */ - static extractNumber(string) { + public static extractNumber(string: string): number { return Parser.stringToNumber(string.replace(/\D/g, '')) } /** * Extract all numbers inside a string. - * - * @param {string} string - * @return {number[]} */ - static extractNumbers(string) { + public static extractNumbers(string: string): number[] { return string.match(/\d+/g).map(numberString => { return Parser.stringToNumber(numberString) }) @@ -85,32 +74,22 @@ export class Number { /** * The average of all numbers in function arguments. - * - * @param {number[]} args - * @return {number} */ - static argsAverage(...args) { + public static argsAverage(...args: number[]): number { return Number.arrayAverage(args) } /** * The average of all numbers in the array. - * - * @param {number[]} array - * @return {number} */ - static arrayAverage(array) { + public static arrayAverage(array: number[]): number { return array.reduce((acc, curr) => acc + curr, 0) / array.length } /** * Generate a random integer from a determined interval of numbers. - * - * @param {number} min - * @param {number} max - * @return {number} */ - static randomIntFromInterval(min, max) { + public static randomIntFromInterval(min: number, max: number): number { return Math.floor(Math.random() * (max - min + 1) + min) } } diff --git a/src/Helpers/Options.js b/src/Helpers/Options.ts similarity index 73% rename from src/Helpers/Options.js rename to src/Helpers/Options.ts index a22f029..54d3e06 100644 --- a/src/Helpers/Options.js +++ b/src/Helpers/Options.ts @@ -10,12 +10,8 @@ export class Options { /** * Creates an option object with default values. - * - * @param {any} object - * @param {any} defaultValues - * @return {any} */ - static create(object, defaultValues) { + public static create(object: T, defaultValues?: Partial): T { return Object.assign({}, defaultValues, object) } } diff --git a/src/Helpers/Parser.js b/src/Helpers/Parser.ts similarity index 69% rename from src/Helpers/Parser.js rename to src/Helpers/Parser.ts index 9b32268..a451711 100644 --- a/src/Helpers/Parser.js +++ b/src/Helpers/Parser.ts @@ -10,37 +10,31 @@ import ms from 'ms' import bytes from 'bytes' -import { getReasonPhrase, getStatusCode } from 'http-status-codes' - import { Is } from '#src/Helpers/Is' import { String } from '#src/Helpers/String' import { Options } from '#src/Helpers/Options' +import { getReasonPhrase, getStatusCode } from 'http-status-codes' import { InvalidNumberException } from '#src/Exceptions/InvalidNumberException' export class Parser { /** * Parse a string to array. - * - * @param {string} string - * @param {string} separator - * @return {string[]} */ - static stringToArray(string, separator) { + public static stringToArray(string: string, separator: string): string[] { return string.split(separator).map(index => index.trim()) } /** * Parse an array of strings to a string. - * - * @param {string[]} values - * @param {{ - * separator?: string, - * pairSeparator?: string, - * lastSeparator?: string - * }} [options] - * @return {string} */ - static arrayToString(values, options) { + public static arrayToString( + values: string[], + options?: { + separator?: string + pairSeparator?: string + lastSeparator?: string + }, + ): string { if (values.length === 0) { return '' } @@ -67,13 +61,8 @@ export class Parser { /** * Parse a string to number or Coordinate. - * - * @param {string} string - * @param {boolean} isCoordinate - * @throws {InvalidNumberException} - * @return {number} */ - static stringToNumber(string, isCoordinate = false) { + public static stringToNumber(string: string, isCoordinate = false): number { if (!string.replace(/\D/g, '')) { throw new InvalidNumberException(string) } @@ -93,7 +82,7 @@ export class Parser { * @param {any} object * @return {string} */ - static jsonToFormData(object) { + public static jsonToFormData(object: any): string { return Object.keys(object) .reduce((previous, current) => { return previous + `&${current}=${encodeURIComponent(object[current])}` @@ -103,11 +92,8 @@ export class Parser { /** * Parse form data to json. - * - * @param {string} formData - * @return {any} */ - static formDataToJson(formData) { + public static formDataToJson(formData: string): any { const object = {} if (formData.startsWith('?')) formData = formData.replace('?', '') @@ -124,11 +110,8 @@ export class Parser { /** * Parses all links inside the string to HTML link * with . - * - * @param {string} string - * @return {string} */ - static linkToHref(string) { + public static linkToHref(string: string): string { const regex = /(https?:\/\/[^\s]+)/g return string.replace(regex, '$1') @@ -136,68 +119,46 @@ export class Parser { /** * Parses a number to Byte format. - * - * @param {number} value - * @param {object} [options] - * @param {number} [options.decimalPlaces=2] - * @param {number} [options.fixedDecimals=false] - * @param {string} [options.thousandsSeparator=] - * @param {string} [options.unit=] - * @param {string} [options.unitSeparator=] - * @return {string} */ - static sizeToByte(value, options) { + public static sizeToByte( + value: number, + options?: bytes.BytesOptions, + ): string { return bytes.format(value, options) } /** * Parses a byte format to number. - * - * @param {string|number} byte - * @return {number} */ - static byteToSize(byte) { + public static byteToSize(byte: string | number): number { return bytes.parse(byte) } /** * Parses a string to MS format. - * - * @param {string} value - * @return {number} */ - static timeToMs(value) { + public static timeToMs(value: string): number { return ms(value) } /** * Parses an MS number to time format. - * - * @param {number} value - * @param {boolean} long - * @return {string} */ - static msToTime(value, long = false) { + public static msToTime(value: number, long = false): string { return ms(value, { long }) } /** * Parses the status code number to it reason in string. - * - * @param {string|number} status - * @return {string} */ - static statusCodeToReason(status) { + public static statusCodeToReason(status: string | number): string { return String.toConstantCase(getReasonPhrase(status)) } /** * Parses the reason in string to it status code number - * - * @param {string} reason - * @return {number} */ - static reasonToStatusCode(reason) { + public static reasonToStatusCode(reason: string): number { reason = String.toSentenceCase(reason, true) if (reason === 'Ok') reason = 'OK' @@ -207,19 +168,16 @@ export class Parser { /** * Parses the database connection url to connection object. - * - * @param {string} url - * @return {{ - * protocol: string, - * user?: string, - * password?: string, - * host: string|string[], - * port?: number, - * database: string, - * options?: any, - * }} */ - static dbUrlToConnectionObj(url) { + public static dbUrlToConnectionObj(url: string): { + protocol: string + user?: string + password?: string + host: string | string[] + port?: number + database: string + options?: any + } { const urlRegexp = /^([^:\\/\s]+):\/\/((.*):(.*)@|)(.*)(:(.*)|)\/(.*)(\?(.+))?/ @@ -264,19 +222,16 @@ export class Parser { /** * Parses the database connection object to connection url. - * - * @param {{ - * protocol: string, - * user?: string, - * password?: string, - * host: string|string[], - * port?: number, - * database: string, - * options?: any, - * }} object - * @return {string} */ - static connectionObjToDbUrl(object) { + public static connectionObjToDbUrl(object: { + protocol: string + user?: string + password?: string + host: string | string[] + port?: number + database: string + options?: any + }): string { const { protocol, user, password, host, port, database, options } = object let url = `${protocol}://` diff --git a/src/Helpers/Path.js b/src/Helpers/Path.ts similarity index 61% rename from src/Helpers/Path.js rename to src/Helpers/Path.ts index 780104e..3c839f0 100644 --- a/src/Helpers/Path.js +++ b/src/Helpers/Path.ts @@ -17,10 +17,8 @@ export class Path { /** * Set a default beforePath for all Path methods that * use Path.pwd. - * - * @type {string} */ - static defaultBeforePath = '' + public static defaultBeforePath = '' /** * Resolve the environment where the application @@ -30,12 +28,11 @@ export class Path { * defaultBeforePath if IS_TS is true. * * The beforePath is always set as '/build' by default. - * - * @param metaUrl {string} - * @param beforePath {string} - * @return {typeof Path} */ - static resolveEnvironment(metaUrl, beforePath = '') { + public static resolveEnvironment( + metaUrl: string, + beforePath = '', + ): typeof Path { const isTs = metaUrl.endsWith('.ts') ? 'true' : 'false' process.env.IS_TS = process.env.IS_TS || isTs @@ -46,15 +43,11 @@ export class Path { /** * Return js or ts extension depending on IS_TS. - * - * @return {string} */ - static ext() { + public static ext(): string { const isTs = !!( process.env.IS_TS && - (process.env.IS_TS === true || - process.env.IS_TS === 'true' || - process.env.IS_TS === '(true)') + (process.env.IS_TS === 'true' || process.env.IS_TS === '(true)') ) if (isTs) { @@ -66,326 +59,235 @@ export class Path { /** * Return the pwd path of your project. - * - * @param {string} [subPath] - * @return {string} */ - static pwd(subPath = sep) { + public static pwd(subPath = sep): string { if (Path.defaultBeforePath) { subPath = normalize(Path.defaultBeforePath).concat(sep, subPath) } const pwd = normalize(`${process.cwd()}${sep}${normalize(subPath)}`) - return this.#removeSlashes(pwd) + return this.removeSlashes(pwd) } /** * Return the app path of your project. - * - * @param {string} subPath - * @return {string} */ - static app(subPath = sep) { + public static app(subPath = sep): string { return this.pwd('app' + sep + normalize(subPath)) } /** * Return the bootstrap path of your project. - * - * @param {string} subPath - * @return {string} */ - static bootstrap(subPath = sep) { + public static bootstrap(subPath = sep): string { return this.pwd('bootstrap' + sep + normalize(subPath)) } /** * Return the config path of your project. - * - * @param {string} subPath - * @return {string} */ - static config(subPath = sep) { + public static config(subPath = sep): string { return this.pwd('config' + sep + normalize(subPath)) } /** * Return the database path of your project. - * - * @param {string} subPath - * @return {string} */ - static database(subPath = sep) { + public static database(subPath = sep): string { return this.pwd('database' + sep + normalize(subPath)) } /** * Return the lang path of your project. - * - * @param {string} subPath - * @return {string} */ - static lang(subPath = sep) { + public static lang(subPath = sep): string { return this.pwd('lang' + sep + normalize(subPath)) } /** * Return the node_modules path of your project. - * - * @param {string} subPath - * @return {string} */ - static nodeModules(subPath = sep) { + public static nodeModules(subPath = sep): string { return this.pwd('node_modules' + sep + normalize(subPath)) } /** * Return the providers' path of your project. - * - * @param {string} subPath - * @return {string} */ - static providers(subPath = sep) { + public static providers(subPath = sep): string { return this.pwd('providers' + sep + normalize(subPath)) } /** * Return the public path of your project. - * - * @param {string} subPath - * @return {string} */ - static public(subPath = sep) { + public static public(subPath = sep): string { return this.pwd('public' + sep + normalize(subPath)) } /** * Return the resources' path of your project. - * - * @param {string} subPath - * @return {string} */ - static resources(subPath = sep) { + public static resources(subPath = sep): string { return this.pwd('resources' + sep + normalize(subPath)) } /** * Return the routes' path of your project. - * - * @param {string} subPath - * @return {string} */ - static routes(subPath = sep) { + public static routes(subPath = sep): string { return this.pwd('routes' + sep + normalize(subPath)) } /** * Return the storage path of your project. - * - * @param {string} subPath - * @return {string} */ - static storage(subPath = sep) { + public static storage(subPath = sep): string { return this.pwd('storage' + sep + normalize(subPath)) } /** * Return the tests' path of your project. - * - * @param {string} subPath - * @return {string} */ - static tests(subPath = sep) { + public static tests(subPath = sep): string { return this.pwd('tests' + sep + normalize(subPath)) } /** * Return the logs' path of your project. - * - * @param {string} subPath - * @return {string} */ - static logs(subPath = sep) { + public static logs(subPath = sep): string { return this.storage('logs' + sep + normalize(subPath)) } /** * Return the views' path of your project. - * - * @param {string} subPath - * @return {string} */ - static views(subPath = sep) { + public static views(subPath = sep): string { return this.resources('views' + sep + normalize(subPath)) } /** * Return the assets' path of your project. - * - * @param {string} subPath - * @return {string} */ - static assets(subPath = sep) { + public static assets(subPath = sep): string { return this.public('assets' + sep + normalize(subPath)) } /** * Return the locales' path of your project. - * - * @param {string} subPath - * @return {string} */ - static locales(subPath = sep) { + public static locales(subPath = sep): string { return this.resources('locales' + sep + normalize(subPath)) } /** * Return the facades' path of your project. - * - * @param {string} subPath - * @return {string} */ - static facades(subPath = sep) { + public static facades(subPath = sep): string { return this.providers('Facades' + sep + normalize(subPath)) } /** * Return the stubs' path of your project. - * - * @param {string} subPath - * @return {string} */ - static stubs(subPath = sep) { + public static stubs(subPath = sep): string { return this.tests('Stubs' + sep + normalize(subPath)) } /** * Return the http path of your project. - * - * @param {string} subPath - * @return {string} */ - static http(subPath = sep) { + public static http(subPath = sep): string { return this.app('Http' + sep + normalize(subPath)) } /** * Return the console path of your project. - * - * @param {string} subPath - * @return {string} */ - static console(subPath = sep) { + public static console(subPath = sep): string { return this.app('Console' + sep + normalize(subPath)) } /** * Return the services' path of your project. - * - * @param {string} subPath - * @return {string} */ - static services(subPath = sep) { + public static services(subPath = sep): string { return this.app('Services' + sep + normalize(subPath)) } /** * Return the repositories' path of your project. - * - * @param {string} subPath - * @return {string} */ - static repositories(subPath = sep) { + public static repositories(subPath = sep): string { return this.app('Repositories' + sep + normalize(subPath)) } /** * Return the migrations' path of your project. - * - * @param {string} subPath - * @return {string} */ - static migrations(subPath = sep) { + public static migrations(subPath = sep): string { return this.database('migrations' + sep + normalize(subPath)) } /** * Return the seeders' path of your project. - * - * @param {string} subPath - * @return {string} */ - static seeders(subPath = sep) { + public static seeders(subPath = sep): string { return this.database('seeders' + sep + normalize(subPath)) } /** * Return the .bin path of your node_modules. - * - * @param {string} subPath - * @return {string} */ - static bin(subPath = sep) { + public static bin(subPath = sep): string { return this.nodeModules('.bin' + sep + normalize(subPath)) } /** * Return the tmp path of your vm. - * - * @param {string} subPath - * @return {string} */ - static vmTmp(subPath = sep) { + public static vmTmp(subPath = sep): string { const osTmpDir = tmpdir() const tmpDir = osTmpDir.concat(sep, normalize(subPath)) - return this.#removeSlashes(tmpDir) + return this.removeSlashes(tmpDir) } /** * Return the home path of your vm. - * - * @param {string} subPath - * @return {string} */ - static vmHome(subPath = sep) { + public static vmHome(subPath = sep): string { const osHomeDir = homedir() const homeDir = osHomeDir.concat(sep, normalize(subPath)) - return this.#removeSlashes(homeDir) + return this.removeSlashes(homeDir) } /** * Return the execution path of where this method * is being called. - * - * @param {string} subPath - * @param {number} [stackIndex] - * @return {string} */ - static this(subPath = sep, stackIndex = 1) { + public static this(subPath = sep, stackIndex = 1): string { const stack = callSite() const requester = dirname(fileURLToPath(stack[stackIndex].getFileName())) const execDir = normalize(requester.concat(sep, normalize(subPath))) - return this.#removeSlashes(execDir) + return this.removeSlashes(execDir) } /** * Remove additional slashes from path. - * - * @param {string} path - * @return {string} */ - static #removeSlashes(path) { + private static removeSlashes(path: string): string { if (path.endsWith(sep)) { path = path.slice(0, -1) if (path.endsWith(sep)) { - return this.#removeSlashes(path) + return this.removeSlashes(path) } } diff --git a/src/Helpers/Route.js b/src/Helpers/Route.ts similarity index 82% rename from src/Helpers/Route.js rename to src/Helpers/Route.ts index a5a14a6..ee41388 100644 --- a/src/Helpers/Route.js +++ b/src/Helpers/Route.ts @@ -13,11 +13,8 @@ import { RouteMatchException } from '#src/Exceptions/RouteMatchException' export class Route { /** * Get the query string in form data format. - * - * @param {string} route - * @return {string} */ - static getQueryString(route) { + public static getQueryString(route: string): string { const queryIndex = route.search(/\?(.*)/) if (queryIndex === -1) return null @@ -27,11 +24,8 @@ export class Route { /** * Remove query params from the route. - * - * @param {string} route - * @return {string} */ - static removeQueryParams(route) { + public static removeQueryParams(route: string): string { const queryString = this.getQueryString(route) if (!queryString) return route @@ -41,11 +35,8 @@ export class Route { /** * Get object with ?&queryParams values from route. - * - * @param {string} route - * @return {any} */ - static getQueryParamsValue(route) { + public static getQueryParamsValue(route: string): any { const queryString = this.getQueryString(route) if (!queryString) return {} @@ -59,7 +50,7 @@ export class Route { * @param {string} route * @return {string[]} */ - static getQueryParamsName(route) { + public static getQueryParamsName(route: string): string[] { const queryNames = [] let queryString = this.getQueryString(route) @@ -78,12 +69,11 @@ export class Route { /** * Get object with :params values from route. - * - * @param {string} routeWithParams - * @param {string} routeWithValues - * @return {any} */ - static getParamsValue(routeWithParams, routeWithValues) { + public static getParamsValue( + routeWithParams: string, + routeWithValues: string, + ): any { routeWithParams = this.removeQueryParams(routeWithParams) routeWithValues = this.removeQueryParams(routeWithValues) @@ -109,11 +99,8 @@ export class Route { /** * Get array with :params name from route. - * - * @param {string} route - * @return {string[]} */ - static getParamsName(route) { + public static getParamsName(route: string): string[] { route = this.removeQueryParams(route) const replaceDots = value => decodeURIComponent(value.replace(':', '')) @@ -129,11 +116,8 @@ export class Route { /** * Create a matcher RegExp for any route. - * - * @param {string} route - * @return {RegExp} */ - static createMatcher(route) { + public static createMatcher(route: string): RegExp { route = this.removeQueryParams(route) const routeArray = route.split('/') diff --git a/src/Helpers/String.js b/src/Helpers/String.ts similarity index 67% rename from src/Helpers/String.js rename to src/Helpers/String.ts index ad73cc0..203514f 100644 --- a/src/Helpers/String.js +++ b/src/Helpers/String.ts @@ -16,11 +16,8 @@ import { OrdinalNanException } from '#src/Exceptions/OrdinalNanException' export class String { /** * Generate random string by size. - * - * @param {number} size - * @return {string} */ - static generateRandom(size) { + public static generateRandom(size: number): string { const bits = (size + 1) * 6 const buffer = randomBytes(Math.ceil(bits / 8)) @@ -29,42 +26,30 @@ export class String { /** * Generate random color in hexadecimal format. - * - * @return {string} */ - static generateRandomColor() { + public static generateRandomColor(): string { return `#${((Math.random() * 0xffffff) << 0).toString(16)}` } /** * Normalizes the string in base64 format removing * special chars. - * - * @param {string} value - * @return {string} */ - static normalizeBase64(value) { + public static normalizeBase64(value: string): string { return value.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '') } /** * Transforms the string to "camelCase". - * - * @param {string} value - * @return {string} */ - static toCamelCase(value) { + public static toCamelCase(value: string): string { return changeCase.camelCase(value) } /** * Transforms the string to "snake_case". - * - * @param {string} value - * @param {boolean} [capitalize] - * @return {string} */ - static toSnakeCase(value, capitalize) { + public static toSnakeCase(value: string, capitalize?: boolean): string { if (capitalize) { return changeCase.snakeCase(value, { transform: changeCase.capitalCaseTransform, @@ -76,32 +61,22 @@ export class String { /** * Transforms the string to "CONSTANT_CASE". - * - * @param {string} value - * @return {string} */ - static toConstantCase(value) { + public static toConstantCase(value: string): string { return changeCase.constantCase(value) } /** * Transforms the string to "PascalCase". - * - * @param {string} value - * @return {string} */ - static toPascalCase(value) { + public static toPascalCase(value: string): string { return changeCase.pascalCase(value) } /** * Transforms the string to "Sentence case". - * - * @param {string} value - * @param {boolean} [capitalize] - * @return {string} */ - static toSentenceCase(value, capitalize) { + public static toSentenceCase(value: string, capitalize?: boolean): string { if (capitalize) { return changeCase.capitalCase(value) } @@ -111,12 +86,8 @@ export class String { /** * Transforms the string to "dot.case". - * - * @param {string} value - * @param {boolean} [capitalize] - * @return {string} */ - static toDotCase(value, capitalize) { + public static toDotCase(value: string, capitalize?: boolean): string { if (capitalize) { return changeCase.dotCase(value, { transform: changeCase.capitalCaseTransform, @@ -128,22 +99,15 @@ export class String { /** * Removes all sorted cases from string. - * - * @param {string} value - * @return {string} */ - static toNoCase(value) { + public static toNoCase(value: string): string { return changeCase.noCase(value) } /** * Transforms a string to "dash-case" - * - * @param {string} value - * @param {boolean} [capitalize] - * @return {string} */ - static toDashCase(value, capitalize) { + public static toDashCase(value: string, capitalize?: boolean): string { if (capitalize) { return changeCase.headerCase(value) } @@ -152,33 +116,23 @@ export class String { } /** - * Transforms a word to plural. - * - * @param {string} word - * @return {string} + * Transforms a word to plural */ - static pluralize(word) { + public static pluralize(word: string): string { return pluralize.plural(word) } /** * Transforms a word to singular. - * - * @param {string} word - * @return {string} */ - static singularize(word) { + public static singularize(word: string): string { return pluralize.singular(word) } /** * Transforms a number to your ordinal format. - * - * @param {string,number} value - * @throws {OrdinalNanException} - * @return {string} */ - static ordinalize(value) { + public static ordinalize(value: string | number): string { const transformedValue = Math.abs( typeof value === 'string' ? parseInt(value) : value, ) diff --git a/src/Helpers/Uuid.js b/src/Helpers/Uuid.ts similarity index 66% rename from src/Helpers/Uuid.js rename to src/Helpers/Uuid.ts index c118681..7ffd9f6 100644 --- a/src/Helpers/Uuid.js +++ b/src/Helpers/Uuid.ts @@ -14,12 +14,8 @@ import { InvalidUuidException } from '#src/Exceptions/InvalidUuidException' export class Uuid { /** * Verify if string is a valid uuid. - * - * @param {string} token - * @param {boolean} [isPrefixed] - * @return {boolean} */ - static verify(token, isPrefixed = false) { + public static verify(token: string, isPrefixed = false): boolean { if (isPrefixed) { return Is.Uuid(this.getToken(token)) } @@ -29,11 +25,8 @@ export class Uuid { /** * Generate an uuid token - * - * @param {string} [prefix] - * @return {string} */ - static generate(prefix) { + public static generate(prefix?: string): string { if (prefix) { return `${prefix}::${v4()}` } @@ -43,11 +36,8 @@ export class Uuid { /** * Return the token without his prefix. - * - * @param {string} token - * @return {string} */ - static getToken(token) { + public static getToken(token: string): string { const prefix = Uuid.getPrefix(token) if (!prefix) { @@ -59,11 +49,8 @@ export class Uuid { /** * Return the prefix without his token. - * - * @param {string} token - * @return {string|null} */ - static getPrefix(token) { + public static getPrefix(token: string): string | null { const prefix = token.split('::')[0] /** @@ -79,13 +66,8 @@ export class Uuid { /** * Inject a prefix in the uuid token. - * - * @param {string} prefix - * @param {string} token - * @throws {InvalidUuidException} - * @return {string} */ - static injectPrefix(prefix, token) { + public static injectPrefix(prefix: string, token: string): string { if (!this.verify(token)) { throw new InvalidUuidException(token) } @@ -95,13 +77,8 @@ export class Uuid { /** * Change the prefix of and uuid token - * - * @param {string} newPrefix - * @param {string} token - * @throws {InvalidUuidException} - * @return {string} */ - static changePrefix(newPrefix, token) { + public static changePrefix(newPrefix: string, token: string): string { const uuid = this.getToken(token) if (!this.verify(uuid)) { @@ -113,12 +90,8 @@ export class Uuid { /** * Change the token prefix or generate a new one - * - * @param {string} prefix - * @param {string?} token - * @return {string} */ - static changeOrGenerate(prefix, token) { + public static changeOrGenerate(prefix: string, token?: string): string { if (token) { return this.changePrefix(prefix, token) } diff --git a/tests/Stubs/config/notNormalized.js b/src/Types/Except.ts similarity index 60% rename from tests/Stubs/config/notNormalized.js rename to src/Types/Except.ts index ef162ee..ea045db 100644 --- a/tests/Stubs/config/notNormalized.js +++ b/src/Types/Except.ts @@ -7,6 +7,7 @@ * file that was distributed with this source code. */ -export const config = { - not: 'normalized', -} +export type Except = Pick< + ObjectType, + Exclude +> diff --git a/tests/Stubs/config/recursiveTwo.js b/src/Types/HttpClient/Body.ts similarity index 52% rename from tests/Stubs/config/recursiveTwo.js rename to src/Types/HttpClient/Body.ts index 40073a4..a17fe79 100644 --- a/tests/Stubs/config/recursiveTwo.js +++ b/src/Types/HttpClient/Body.ts @@ -7,8 +7,13 @@ * file that was distributed with this source code. */ -import { Config } from '#src/Helpers/Config' +import { FormDataLike } from 'form-data-encoder' -export default { - value: Config.get('recursiveOne.value'), -} +export type Body = + | any + | string + | Record + | ReadableStream + | Generator + | AsyncGenerator + | FormDataLike diff --git a/tests/Stubs/config/database.js b/src/Types/HttpClient/Query.ts similarity index 66% rename from tests/Stubs/config/database.js rename to src/Types/HttpClient/Query.ts index 7e71b85..56519c0 100644 --- a/tests/Stubs/config/database.js +++ b/src/Types/HttpClient/Query.ts @@ -7,8 +7,6 @@ * file that was distributed with this source code. */ -import { Config } from '#src/Helpers/Config' +import { SearchParameters } from 'got' -export default { - username: Config.get('app.name'), -} +export type Query = string | SearchParameters | URLSearchParams diff --git a/src/Types/HttpClient/ReqOptions.ts b/src/Types/HttpClient/ReqOptions.ts new file mode 100644 index 0000000..59c44c3 --- /dev/null +++ b/src/Types/HttpClient/ReqOptions.ts @@ -0,0 +1,17 @@ +/** + * @athenna/common + * + * (c) João Lenon + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import { Except } from '#src/Types/Except' +import { OptionsInit, ResponseType } from 'got' + +export type ReqOptions = Except & + Partial<{ + get responseType(): ResponseType | string + set responseType(value: ResponseType | string) + }> diff --git a/src/Types/HttpClient/RetryStrategyCallback.ts b/src/Types/HttpClient/RetryStrategyCallback.ts new file mode 100644 index 0000000..fa62aa5 --- /dev/null +++ b/src/Types/HttpClient/RetryStrategyCallback.ts @@ -0,0 +1,16 @@ +/** + * @athenna/common + * + * (c) João Lenon + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import { RequestError, RetryObject } from 'got' + +export type RetryStrategyCallback = ( + error: RequestError, + execCount: number, + retryObject: RetryObject, +) => number | Promise diff --git a/tests/Stubs/config/recursiveOne.js b/src/Types/Merge.ts similarity index 54% rename from tests/Stubs/config/recursiveOne.js rename to src/Types/Merge.ts index 849883f..5952a9e 100644 --- a/tests/Stubs/config/recursiveOne.js +++ b/src/Types/Merge.ts @@ -7,8 +7,10 @@ * file that was distributed with this source code. */ -import { Config } from '#src/Helpers/Config' +import { Except } from '#src/Types/Except' -export default { - value: Config.get('recursiveTwo.value'), -} +export type Merge = Except< + FirstType, + Extract +> & + SecondType diff --git a/src/index.d.ts b/src/index.d.ts deleted file mode 100644 index f9c4071..0000000 --- a/src/index.d.ts +++ /dev/null @@ -1,3507 +0,0 @@ -/** - * @athenna/common - * - * (c) João Lenon - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -import CacheableLookup from 'cacheable-lookup' -import { Collection as CollectJS } from 'collect.js' -import { - CancelableRequest, - Response, - Request, - OptionsInit as GotOptions, -} from 'got' -import fastify from 'fastify' -import fastifyFormbody from '@fastify/formbody' - -export declare interface ExceptionJSON { - code?: string - name: string - status: number - content: string - help?: string - stack?: any -} - -export declare interface FileJSON { - dir: string - name: string - base: string - path: string - mime: string - createdAt: Date - accessedAt: Date - modifiedAt: Date - fileSize: number - extension: string - isCopy: boolean - originalDir: string - originalName: string - originalPath: string - originalFileExists: boolean - content: string -} - -export declare interface FolderJSON { - dir: string - name: string - base: string - path: string - files: File[] - folders: Folder[] - createdAt: Date - accessedAt: Date - modifiedAt: Date - folderSize: number - isCopy: boolean - originalDir: string - originalName: string - originalPath: string - originalFolderExists: boolean -} - -export declare interface CoordinateContract { - latitude: number - longitude: number -} - -export declare interface PaginationContract { - page?: number - limit?: number - resourceUrl?: string -} - -export declare interface PaginatedResponse { - data: any[] - meta: { - totalItems: number - itemsPerPage: number - totalPages: number - currentPage: number - itemCount: number - } - links: { - next: string - previous: string - last: string - first: string - } -} - -export declare interface DBConnectionContract { - protocol: string - user?: string - password?: string - host: string | string[] - port?: number - database: string - options?: any -} - -export declare class Clean { - /** - * Remove all falsy values from array. - * - * @param {any[]} array - * @param {boolean} [removeEmpty] - * @param {boolean} [cleanInsideObjects] - * @return {any[]} - */ - static cleanArray( - array: any[], - removeEmpty?: boolean, - cleanInsideObjects?: boolean, - ): any[] - - /** - * Remove all falsy values from object. - * - * @param {any} object - * @param {boolean} [removeEmpty] - * @param {boolean} [cleanInsideArrays] - * @return {any} - */ - static cleanObject( - object: any, - removeEmpty?: boolean, - cleanInsideArrays?: boolean, - ): any -} - -export declare class Collection extends CollectJS { - /** - * An alias for macro instance method: - * - * @example - * new Collection().macro() - * - * @param {string} name - * @param {Function} fn - */ - static macro(name: string, fn: Function): void - - /** - * Remove all duplicated values from the array. - * - * @return {any[]} - */ - removeDuplicated(): Item[] - - /** - * Execute the toResource method inside objects if exists. - * - * @param {any} [criterias] - * @return {any[]} - */ - toResource(criterias?: any): any[] - - /** - * The sortDesc method sort the collection in descending mode. - */ - sortDesc(): Collection - - /** - * The sortKeys method sort the keys of the collection. - */ - sortKeys(): Collection - - /** - * The sortKeysDesc method sort the keys of the collection in descending mode. - */ - sortKeysDesc(): Collection - - /** - * The order method orders the collection. - */ - order(fn?: (a: Item, b: Item) => number): Collection - - /** - * The orderBy method orders the collection by the given key. - * The ordered collection keeps the original array keys. - */ - orderBy(value: V): Collection - - /** - * The orderBy method orders the collection by the given callback. - * The ordered collection keeps the original array keys. - */ - orderBy(fn: (item: Item) => number): Collection - - /** - * This method has the same signature as the orderBy method, - * but will order the collection in the opposite order. - */ - orderByDesc(value: V): Collection - - /** - * This method has the same signature as the orderBy method, - * but will order the collection in the opposite order. - */ - orderByDesc(fn: (item: Item) => number): Collection - - /** - * The orderDesc method order the collection in descending mode. - */ - orderDesc(): Collection - - /** - * The orderKeys method order the keys of the collection. - */ - orderKeys(): Collection - - /** - * The orderKeysDesc method order the keys of the collection in descending mode. - */ - orderKeysDesc(): Collection -} - -export declare class Debug { - /** - * Format the message using Chalk API. - * - * @param {string} message - * @return {string} - */ - static format(message: string): string - - /** - * Format and throw the message in the stdout accordingly to the namespace. - * - * @param {string|any} message - * @param {string} [namespace] - * @return {void} - */ - static log(message: string | any, namespace?: string): void -} - -export declare class Exception extends Error { - /** - * Creates a new instance of Exception. - * - * @param {string} [content] - * @param {number} [status] - * @param {string} [code] - * @param {string} [help] - * @return {Exception} - */ - constructor(content?: string, status?: number, code?: string, help?: string) - - /** - * Transform the exception to a valid JSON Object. - * - * @param {boolean} [stack] - * @return {ExceptionJSON} - */ - toJSON(stack?: boolean): ExceptionJSON - - /** - * Prettify the error using Youch API. - * - * @param {any} [options] - * @param {string} [options.prefix] - * @param {boolean} [options.hideMessage] - * @param {boolean} [options.hideErrorTitle] - * @param {boolean} [options.displayShortPath] - * @param {boolean} [options.displayMainFrameOnly] - * @return {Promise} - */ - prettify(options?: { - prefix?: string - hideMessage?: boolean - hideErrorTitle?: boolean - displayShortPath?: boolean - displayMainFrameOnly?: boolean - }): Promise -} - -export declare class Exec { - /** - * Sleep the code in the line that this function - * is being called. - * - * @param {number} ms - * @return {Promise} - */ - static sleep(ms: number): Promise - - /** - * Execute a command of child process exec as promise. - * - * @param {string} command - * @param {{ - * ignoreErrors?: boolean - * }} [options] - * @throws {NodeCommandException} - * @return {Promise<{ stdout: string, stderr: string }>} - */ - static command( - command: string, - options?: { ignoreErrors?: boolean }, - ): Promise<{ stdout: string; stderr: string }> - - /** - * Download an archive to determined path. - * - * @param {string} name - * @param {string} path - * @param {string} url - * @return {Promise} - */ - static download(name: string, path: string, url: string): Promise - - /** - * Paginate a collection of data. - * - * @param {any[]} data - * @param {number} total - * @param {{ - * page?: number, - * limit?: number, - * resourceUrl?: string - * }} pagination - * @return {{ - * data: any[], - * meta: { - * totalItems: number, - * itemsPerPage: number, - * totalPages: number, - * currentPage: number, - * itemCount: number - * }, - * links: { - * next: string, - * previous: string, - * last: string, - * first: string - * } - * }} - */ - static pagination( - data: any[], - total: number, - pagination: PaginationContract, - ): PaginatedResponse -} - -export class FakeApi { - /** - * Create the fastify server with plugins. - * - * This method is already called when you import FakeApi module. - * - * @return {import('fastify').FastifyInstance} - */ - static recreate(): import('fastify').FastifyInstance - - /** - * Creates a new instance of FakeApiBuilder - * - * @return {FakeApiBuilder} - */ - static build(): FakeApiBuilder - - /** - * List the routes registered in the fake server. - * - * @return {string} - */ - static listRoutes(): string - - /** - * List the routes registered in the fake server. - * - * @return {boolean} - */ - static isRunning(): boolean - - /** - * Register all routes inside folder path - * and start the fake api server at port 8989. - * - * @param [port] {number} - * @param [folderPath] {string | null} - * @return {Promise} - */ - static start(port?: number, folderPath?: string | null): Promise - - /** - * Stop the fake api server. - * - * @return {Promise} - */ - static stop(): Promise -} - -export class FakeApiBuilder { - /** - * Set the route path. - * - * @param path {string} - * @return {FakeApiBuilder} - */ - path(path: string): FakeApiBuilder - - /** - * Set the route method. - * - * @param method {import('fastify').HTTPMethods} - * @return {FakeApiBuilder} - */ - method(method: import('fastify').HTTPMethods): FakeApiBuilder - - /** - * Set the response body of the route. - * - * @param body {any | any[]} - * @return {FakeApiBuilder} - */ - body(body: any | any[]): FakeApiBuilder - - /** - * Set the response headers of the route. - * - * @param headers {any} - * @return {FakeApiBuilder} - */ - headers(headers: any): FakeApiBuilder - - /** - * Set the response status code of the route. - * - * @param statusCode {number} - * @return {FakeApiBuilder} - */ - statusCode(statusCode: number): FakeApiBuilder - - /** - * Register the route. - * - * @param [options] {import('fastify').RouteOptions} - * @return void - */ - register(options?: import('fastify').RouteOptions): void -} - -export declare class File { - public originalDir: string - - public originalName: string - - public originalBase: string - - public originalPath: string - - public dir: string - - public name: string - - public base: string - - public path: string - - public href: string - - public isCopy: boolean - - public originalFileExists: boolean - - public fileExists: boolean - - public content: Buffer - - public mime: string - - public extension: string - - /** - * Creates a new instance of File. - * - * @param {string} filePath - * @param {Buffer} [content] - * @param {boolean} [mockedValues] - * @param {boolean} [isCopy] - * @return {File} - */ - constructor( - filePath: string, - content?: Buffer, - mockedValues?: boolean, - isCopy?: boolean, - ) - - /** - * Remove the file it's existing or not. - * - * @param {string} filePath - * @return {Promise} - */ - static safeRemove(filePath: string): Promise - - /** - * Verify if file exists. - * - * @param {string} filePath - * @return {boolean} - */ - static existsSync(filePath: string): boolean - - /** - * Verify if file exists. - * - * @param {string} filePath - * @return {Promise} - */ - static exists(filePath: string): Promise - - /** - * Verify if path is from file or directory. - * - * @param {string} path - * @return {boolean} - */ - static isFileSync(path: string): boolean - - /** - * Verify if path is from file or directory. - * - * @param {string} path - * @return {Promise} - */ - static isFile(path: string): Promise - - /** - * Create fake file with determined size. - * - * @param {string} filePath - * @param {number} size - * @return {Promise} - */ - static createFileOfSize(filePath: string, size?: number): Promise - - /** - * Returns the file as a JSON object. - * - * @return {FileJSON} - */ - toJSON(): FileJSON - - /** - * Load or create the file. - * - * @param {{ - * withContent?: boolean, - * isInternalLoad?: boolean - * }} [options] - * @return {File} - */ - loadSync(options?: { withContent?: boolean; isInternalLoad?: boolean }): File - - /** - * Load or create the file. - * - * @param {{ - * withContent?: boolean, - * isInternalLoad?: boolean - * }} [options] - * @return {Promise} - */ - load(options?: { - withContent?: boolean - isInternalLoad?: boolean - }): Promise - - /** - * Remove the file. - * - * @return {void} - */ - removeSync(): void - - /** - * Remove the file. - * - * @return {Promise} - */ - remove(): Promise - - /** - * Create a copy of the file. - * - * @param {string} path - * @param {{ - * withContent?: boolean, - * mockedValues?: boolean - * }} [options] - * @return {File} - */ - copySync( - path: string, - options?: { withContent?: boolean; mockedValues?: boolean }, - ): File - - /** - * Create a copy of the file. - * - * @param {string} path - * @param {{ - * withContent?: boolean, - * mockedValues?: boolean - * }} [options] - * @return {Promise} - */ - copy( - path: string, - options?: { withContent?: boolean; mockedValues?: boolean }, - ): Promise - - /** - * Move the file to other path. - * - * @param {string} path - * @param {{ - * withContent?: boolean, - * mockedValues?: boolean - * }} [options] - * @return {File} - */ - moveSync( - path: string, - options?: { withContent?: boolean; mockedValues?: boolean }, - ): File - - /** - * Move the file to other path. - * - * @param {string} path - * @param {{ - * withContent?: boolean, - * mockedValues?: boolean - * }} [options] - * @return {Promise} - */ - move( - path: string, - options?: { withContent?: boolean; mockedValues?: boolean }, - ): Promise - - /** - * Append any data to the file. - * - * @param {string|Buffer} data - * @return {File} - */ - appendSync(data: string | Buffer): File - - /** - * Append any data to the file. - * - * @param {string|Buffer} data - * @return {Promise} - */ - append(data: string | Buffer): Promise - - /** - * Prepend any data to the file. - * - * @param {string|Buffer} data - * @return {File} - */ - prependSync(data: string | Buffer): File - - /** - * Prepend any data to the file. - * - * @param {string|Buffer} data - * @return {Promise} - */ - prepend(data: string | Buffer): Promise - - /** - * Get only the content of the file. - * - * @param {{ - * saveContent?: boolean - * }} [options] - * @return {Buffer} - */ - getContentSync(options?: { saveContent?: boolean }): Buffer - - /** - * Get only the content of the file. - * - * @param {{ - * saveContent?: boolean - * }} [options] - * @return {Promise} - */ - getContent(options?: { saveContent?: boolean }): Promise - - /** - * Create a readable stream of the file. - * - * @param options {BufferEncoding | import('node:stream').StreamOptions} - * @return {import('node:fs').ReadStream} - */ - createReadStream( - options?: BufferEncoding | import('node:stream').StreamOptions, - ): import('node:fs').ReadStream - - /** - * Create a writable stream of the file. - * - * @param options {BufferEncoding | import('node:stream').StreamOptions} - * @return {import('node:fs').WriteStream} - */ - createWriteStream( - options?: BufferEncoding | import('node:stream').StreamOptions, - ): import('node:fs').WriteStream -} - -export declare class Folder { - public files: File[] - - public folders: Folder[] - - public originalDir: string - - public originalName: string - - public originalPath: string - - public dir: string - - public name: string - - public path: string - - public isCopy: boolean - - public originalFolderExists: boolean - - public folderExists: boolean - - /** - * Creates a new instance of Folder. - * - * @param {string} folderPath - * @param {boolean} [mockedValues] - * @param {boolean} [isCopy] - * @return {Folder} - */ - constructor(folderPath: string, mockedValues?: boolean, isCopy?: boolean) - - /** - * Get the size of the folder. - * - * @param {string} folderPath - * @return {number} - */ - static folderSizeSync(folderPath: string): number - - /** - * Get the size of the folder. - * - * @param {string} folderPath - * @return {Promise} - */ - static folderSize(folderPath: string): Promise - - /** - * Remove the folder it's existing or not. - * - * @param {string} folderPath - * @return {Promise} - */ - static safeRemove(folderPath: string): Promise - - /** - * Verify if folder exists. - * - * @param {string} folderPath - * @return {boolean} - */ - static existsSync(folderPath: string): boolean - - /** - * Verify if folder exists. - * - * @param {string} folderPath - * @return {Promise} - */ - static exists(folderPath: string): Promise - - /** - * Verify if path is from folder or file. - * - * @param {string} path - * @return {boolean} - */ - static isFolderSync(path: string): boolean - - /** - * Verify if path is from folder or file. - * - * @param {string} path - * @return {Promise} - */ - static isFolder(path: string): Promise - - /** - * Returns the file as a JSON object. - * - * @return {FolderJSON} - */ - toJSON(): FolderJSON - - /** - * Load or create the folder. - * - * @param {{ - * withSub?: boolean, - * withFileContent?: boolean, - * isInternalLoad?: boolean, - * }} [options] - * @return {Folder} - */ - loadSync(options?: { - withSub?: boolean - withFileContent?: boolean - isInternalLoad?: boolean - }): Folder - - /** - * Load or create the folder. - * - * @param {{ - * withSub?: boolean, - * withFileContent?: boolean, - * isInternalLoad?: boolean, - * }} [options] - * @return {Promise} - */ - load(options?: { - withSub?: boolean - withFileContent?: boolean - isInternalLoad?: boolean - }): Promise - - /** - * Remove the folder. - * - * @return {void} - */ - removeSync(): void - - /** - * Remove the folder. - * - * @return {Promise} - */ - remove(): Promise - - /** - * Create a copy of the folder. - * - * @param {string} path - * @param {{ - * withSub?: boolean, - * withFileContent?: boolean, - * mockedValues?: boolean - * }} [options] - * @return {Folder} - */ - copySync( - path: string, - options?: { - withSub?: boolean - withFileContent?: boolean - mockedValues?: boolean - }, - ): Folder - - /** - * Create a copy of the folder. - * - * @param {string} path - * @param {{ - * withSub?: boolean, - * withFileContent?: boolean, - * mockedValues?: boolean - * }} [options] - * @return {Promise} - */ - copy( - path: string, - options?: { - withSub?: boolean - withFileContent?: boolean - mockedValues?: boolean - }, - ): Promise - - /** - * Move the folder to other path. - * - * @param {string} path - * @param {{ - * withSub?: boolean, - * withFileContent?: boolean, - * mockedValues?: boolean - * }} [options] - * @return {Folder} - */ - moveSync( - path: string, - options?: { - withSub?: boolean - withFileContent?: boolean - mockedValues?: boolean - }, - ): Folder - - /** - * Move the folder to other path. - * - * @param {string} path - * @param {{ - * withSub?: boolean, - * withFileContent?: boolean, - * mockedValues?: boolean - * }} [options] - * @return {Promise} - */ - move( - path: string, - options?: { - withSub?: boolean - withFileContent?: boolean - mockedValues?: boolean - }, - ): Promise - - /** - * Get all the files of folder using glob pattern. - * - * @param {string} [pattern] - * @param {boolean} [recursive] - * @return {File[]} - */ - getFilesByPattern(pattern?: string, recursive?: boolean): File[] - - /** - * Get all the folders of folder using glob pattern. - * - * @param {string} [pattern] - * @param {boolean} [recursive] - * @return {Folder[]} - */ - getFoldersByPattern(pattern?: string, recursive?: boolean): Folder[] -} - -export declare class HttpClientBuilder { - /** - * Creates a new instance of HttpClientBuilder. - * - * @param [options] {GotOptions} - */ - constructor(options?: GotOptions) - - /** - * Return the options of the client builder. - * - * @return {GotOptions} - */ - getOptions(): HttpClientBuilder - - /** - * From `http-cache-semantics` - * - * @param cacheOptions {import('got').CacheOptions} - * @return {HttpClientBuilder} - */ - cacheOptions(cacheOptions: import('got').CacheOptions): HttpClientBuilder - - /** - * Called with the plain request options, right before their normalization. - * - * The second argument represents the current `Options` instance. - * - * **Note:** - * > - This hook must be synchronous. - * - * **Note:** - * > - This is called every time options are merged. - * - * **Note:** - * > - The `options` object may not have the `url` property. To modify it, use a `beforeRequest` hook instead. - * - * **Note:** - * > - This hook is called when a new instance of `Options` is created. - * > - Do not confuse this with the creation of `Request` or `got(…)`. - * - * **Note:** - * > - When using `got(url)` or `got(url, undefined, defaults)` this hook will **not** be called. - * - * This is especially useful in conjunction with `got.extend()` when the input needs custom handling. - * - * For example, this can be used to fix typos to migrate from older versions faster. - * - * @example - * ``` - * await HttpClient.builder() - * .setInitHook(plain => { - * if ('followRedirects' in plain) { - * plain.followRedirect = plain.followRedirects - * delete plain.followRedirects - * } - * }) - * .mergeOptions({ followRedirects: true }) - * .get('https://example.com') - * - * // There is no option named `followRedirects` in got, but we correct it - * // in an `init` hook. - * ``` - * - * @param initHook {import('got').InitHook} - * @return {HttpClientBuilder} - */ - setInitHook(initHook: import('got').InitHook): HttpClientBuilder - - /** - * Called right before making the request with `options.createNativeRequestOptions()`. - * - * This hook is especially useful in conjunction with `HttpClient.setBuilder(customBuilder)` when you want to sign your request. - * - * *Note:** - * > - Got will make no further changes to the request before it is sent. - * - * *Note:** - * > - Changing `options.json` or `options.form` has no effect on the request. You should change `options.body` instead. If needed, update the `options.headers` accordingly. - * - * @example - * ``` - * const response = await HttpClient.builder() - * .setBeforeRequestHook(options => { - * options.body = JSON.stringify({ payload: 'new' }) - * options.headers['content-length'] = options.body.length.toString() - * }) - * .post('https://httpbin.org/anything', { payload: 'old' }) - * ``` - * - * @param beforeRequestHook {import('got').BeforeRequestHook} - * @return {HttpClientBuilder} - */ - setBeforeRequestHook( - beforeRequestHook: import('got').BeforeRequestHook, - ): HttpClientBuilder - - /** - * The equivalent of `setBeforeRequestHook` but when redirecting. - * - * *Tip:** - * > - This is especially useful when you want to avoid dead sites. - * - * @example - * ``` - * const response = await HttpClient.builder() - * .setBeforeRedirectHook((options, response) => { - * if (options.hostname === 'deadSite') { - * options.hostname = 'fallbackSite' - * } - * }) - * .get('https://example.com') - * ``` - * - * @param beforeRedirectHook {import('got').BeforeRedirectHook} - * @return {HttpClientBuilder} - */ - setBeforeRedirectHook( - beforeRedirectHook: import('got').BeforeRedirectHook, - ): HttpClientBuilder - - /** - * Called with a `RequestError` instance. The error is passed to the hook right before it's thrown. - * - * This is especially useful when you want to have more detailed errors. - * - * @example - * ``` - * await HttpClient.builder() - * .responseType('json') - * .setBeforeErrorHook(error => { - * const { response } = error - * - * if (response && response.body) { - * error.name = 'GitHubError' - * error.message = `${response.body.message} (${response.statusCode})` - * } - * - * return error - * }) - * .get('https://api.github.com/repos/AthennaIO/Common/commits') - * ``` - * - * @param beforeErrorHook {import('got').BeforeErrorHook} - * @return {HttpClientBuilder} - */ - setBeforeErrorHook( - beforeErrorHook: import('got').BeforeErrorHook, - ): HttpClientBuilder - - /** - * The equivalent of `setBeforeErrorHook` but when retrying. Additionally, - * there is a second argument `retryCount`, the current retry number. - * - * *Note:** - * > - When using the Stream API, this hook is ignored. - * - * *Note:** - * > - When retrying, the `beforeRequest` hook is called afterwards. - * - * *Note:** - * > - If no retry occurs, the `beforeError` hook is called instead. - * - * This hook is especially useful when you want to retrieve the cause of a retry. - * - * @example - * ``` - * await HttpClient.builder() - * .setBeforeRetryHook((error, retryCount) => { - * console.log(`Retrying [${retryCount}]: ${error.code}`) - * // Retrying [1]: ERR_NON_2XX_3XX_RESPONSE - * }) - * .get('https://httpbin.org/status/500') - * ``` - * - * @param beforeRetryHook {import('got').BeforeRetryHook} - * @return {HttpClientBuilder} - */ - setBeforeRetryHook( - beforeRetryHook: import('got').BeforeRetryHook, - ): HttpClientBuilder - - /** - * Each function should return the response. This is especially useful when you want to refresh an access token. - * - * *Note:** - * > - When using the Stream API, this hook is ignored. - * - * *Note:** - * > - Calling the `retryWithMergedOptions` function will trigger `beforeRetry` hooks. If the retry is successful, all remaining `afterResponse` hooks will be called. In case of an error, `beforeRetry` hooks will be called instead. - * Meanwhile, the `init`, `beforeRequest` , `beforeRedirect` as well as already executed `afterResponse` hooks will be skipped. - * - * @example - * ``` - * const builder = HttpClient.builder() - * .mutableDefaults(true) - * .setBeforeRetry(error => { - * // This will be called on `retryWithMergedOptions(...)` - * }) - * .setAfterResponseHook((response, retryWithMergedOptions) => { - * // Unauthorized - * if (response.statusCode === 401) { - * // Refresh the access token - * const updatedOptions = { - * headers: { - * token: getNewToken() - * } - * }; - * - * // Update the defaults - * instance.defaults.options.merge(updatedOptions) - * - * // Make a new retry - * return retryWithMergedOptions(updatedOptions) - * } - * - * // No changes otherwise - * return response - * }) - * ``` - * - * @param afterResponseHook {import('got').AfterResponseHook} - * @return {HttpClientBuilder} - */ - setAfterResponseHook( - afterResponseHook: import('got').AfterResponseHook, - ): HttpClientBuilder - - /** - * An object representing `http`, `https` and `http2` keys for [`http.Agent`](https://nodejs.org/api/http.html#http_class_http_agent), [`https.Agent`](https://nodejs.org/api/https.html#https_class_https_agent) and [`http2wrapper.Agent`](https://github.com/szmarczak/http2-wrapper#new-http2agentoptions) instance. - * This is necessary because a request to one protocol might redirect to another. - * In such a scenario, Got will switch over to the right protocol agent for you. - * - * If a key is not present, it will default to a global agent. - * - * @example - * ``` - * import HttpAgent from 'agentkeepalive' - * - * const { HttpsAgent } = HttpAgent - * - * await HttpClient.builder() - * .agent({ http: new HttpAgent(), https: new HttpsAgent() } - * .get('https://sindresorhus.com') - * ``` - * - * @param agents {import('got').Agents} - * @return {HttpClientBuilder} - */ - agent(agents: import('got').Agents): HttpClientBuilder - - /** - * Set the http2 session. - * - * @param h2session {import('http2').ClientHttp2Session} - * @return {HttpClientBuilder} - */ - h2session(h2session: import('http2').ClientHttp2Session): HttpClientBuilder - - /** - * Decompress the response automatically. - * - * This will set the `accept-encoding` header to `gzip, deflate, br` unless you set it yourself. - * - * If this is disabled, a compressed response is returned as a `Buffer`. - * This may be useful if you want to handle decompression yourself or stream the raw compressed data. - * - * @param decompress {boolean} - * @return {HttpClientBuilder} - */ - decompress(decompress: boolean): HttpClientBuilder - - /** - * Milliseconds to wait for the server to end the response before aborting the request with `got.TimeoutError` error (a.k.a. `request` property). - * - * By default, there's no timeout. - * - * This also accepts an `object` with the following fields to constrain the duration of each phase of the request lifecycle: - * - * - `lookup` starts when a socket is assigned and ends when the hostname has been resolved. - * Does not apply when using a Unix domain socket. - * - `connect` starts when `lookup` completes (or when the socket is assigned if lookup does not apply to the request) and ends when the socket is connected. - * - `secureConnect` starts when `connect` completes and ends when the handshaking process completes (HTTPS only). - * - `socket` starts when the socket is connected. See [request.setTimeout](https://nodejs.org/api/http.html#http_request_settimeout_timeout_callback). - * - `response` starts when the request has been written to the socket and ends when the response headers are received. - * - `send` starts when the socket is connected and ends with the request has been written to the socket. - * - `request` starts when the request is initiated and ends when the response's end event fires. - * @param delays {number | Partial} - */ - timeout(delays: number): HttpClientBuilder - timeout(delays: Partial): HttpClientBuilder - - /** - * Set the request body. - * - * @param body {Record | string | Readable | Generator | AsyncGenerator | import('form-data-encoder').FormDataLike } - * @return {HttpClientBuilder} - */ - body( - body: - | Record - | string - | ReadableStream - | Generator - | AsyncGenerator - | import('form-data-encoder').FormDataLike, - ): HttpClientBuilder - - /** - * Set the request form. - * - * @param form {any} - * @return {HttpClientBuilder} - */ - form(form: any): HttpClientBuilder - - /** - * Set a header at the request. - * - * @param key {string} - * @param value {string} - * @return {HttpClientBuilder} - */ - header(key: string, value: any): HttpClientBuilder - - /** - * Set a header at the request only if is not already - * defined. - * - * @param key {string} - * @param value {string} - * @return {HttpClientBuilder} - */ - safeHeader(key: string, value: any): HttpClientBuilder - - /** - * Remove a header from the request. - * - * @param key {string} - * @return {HttpClientBuilder} - */ - removeHeader(key: string): HttpClientBuilder - - /** - * When specified, `prefixUrl` will be prepended to `url`. - * The prefix can be any valid URL, either relative or absolute. - * A trailing slash `/` is optional - one will be added automatically. - * - * __Note__: `prefixUrl` will be ignored if the `url` argument is a URL instance. - * - * __Note__: Leading slashes in `input` are disallowed when using this option to enforce consistency and avoid confusion. - * For example, when the prefix URL is `https://example.com/foo` and the input is `/bar`, there's ambiguity whether the resulting URL would become `https://example.com/foo/bar` or `https://example.com/bar`. - * The latter is used by browsers. - * - * __Tip__: Useful when used with `got.extend()` to create niche-specific Got instances. - * - * __Tip__: You can change `prefixUrl` using hooks as long as the URL still includes the `prefixUrl`. - * If the URL doesn't include it anymore, it will throw. - * - * @example - * ``` - * await HttpClient.builder() - * .prefixUrl('https://cats.com') - * .get('unicorn') - * .json() - * //=> 'https://cats.com/unicorn' - * ``` - * @param prefixUrl {string} - * @return {HttpClientBuilder} - */ - prefixUrl(prefixUrl: string): HttpClientBuilder - - /** - * Set the request method. - * - * @param method {import('got').Method} - * @return {HttpClientBuilder} - */ - method(method: import('got').Method): HttpClientBuilder - - /** - * Set the request url. - * - * @param url {string} - * @return {HttpClientBuilder} - */ - url(url: string): HttpClientBuilder - - /** - * Cookie support. You don't have to care about parsing or how to store them. - * - * __Note__: If you provide this option, `options.headers.cookie` will be overridden. - * - * @param jar {import('got').PromiseCookieJar | import('got').ToughCookieJar} - * @return {HttpClientBuilder} - */ - cookieJar( - jar: import('got').PromiseCookieJar | import('got').ToughCookieJar, - ): HttpClientBuilder - - /** - * You can abort the `request` using [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController). - * - * Requires Node.js 16 or later.* - * - * @example - * ``` - * const abortController = new AbortController(); - * - * const request = HttpClient.builder() - * .signal(abortController.signal) - * .get('https://httpbin.org/anything') - * - * setTimeout(() => { - * abortController.abort(); - * }, 100); - * ``` - * - * @param signal {any} - * @return {HttpClientBuilder} - */ - signal(signal: any): HttpClientBuilder - - /** - * Ignore invalid cookies instead of throwing an error. - * Only useful when the `cookieJar` option has been set. Not recommended. - * - * @param ignore {boolean} - * @return {HttpClientBuilder} - */ - ignoreInvalidCookies(ignore: boolean): HttpClientBuilder - - /** - * Query string that will be added to the request URL. - * This will override the query string in `url`. - * - * If you need to pass in an array, you can do it using a `URLSearchParams` instance. - * - * @example - * ``` - * await HttpClient.builder() - * .searchParams(new URLSearchParams([['key', 'a'], ['key', 'b']])) - * .get('https://example.com') - * - * console.log(searchParams.toString()); - * //=> 'key=a&key=b' - * ``` - * - * @param value { string | import('got').SearchParameters | URLSearchParams } - * @return {HttpClientBuilder} - */ - searchParams( - value: string | import('got').SearchParameters | URLSearchParams, - ): HttpClientBuilder - - /** - * Alias for the searchParams method. - * - * @param value { string | import('got').SearchParameters | URLSearchParams } - * @return {HttpClientBuilder} - */ - queryParams(value: string | import('got').SearchParameters | URLSearchParams): HttpClientBuilder - - /** - * Set the dnsLookup parameter. - * - * @param lookup {CacheableLookup | boolean} - * @return {HttpClientBuilder} - */ - dnsLookup(lookup: CacheableLookup['lookup'] | boolean): HttpClientBuilder - - /** - * An instance of [`CacheableLookup`](https://github.com/szmarczak/cacheable-lookup) used for making DNS lookups. - * Useful when making lots of requests to different *public* hostnames. - * - * `CacheableLookup` uses `dns.resolver4(..)` and `dns.resolver6(...)` under the hood and fall backs to `dns.lookup(...)` when the first two fail, which may lead to additional delay. - * - * __Note__: This should stay disabled when making requests to internal hostnames such as `localhost`, `database.local` etc. - * - * @param cache {any | boolean} - * @return {HttpClientBuilder} - */ - dnsCache(cache: CacheableLookup | boolean): HttpClientBuilder - - /** - * User data. `context` is shallow merged and enumerable. If it contains non-enumerable properties they will NOT be merged. - * - * @example - * ``` - * HttpClient.builder() - * .setBeforeRequestHook(options => { - * if (!options.context || !options.context.token) { - * throw new Error('Token required') - * } - * - * options.headers.token = options.context.token - * }) - * - * const response = await HttpClient.builder() - * .context({ token: 'secret' }) - * .get('https://httpbin.org/headers') - * - * // Let's see the headers - * console.log(response.body) - * ``` - * - * @param context {Record} - * @return {HttpClientBuilder} - */ - context(context: Record): HttpClientBuilder - - /** - * Hooks allow modifications during the request lifecycle. - * Hook functions may be async and are run serially. - * - * @param hooks {import('got').Hooks} - * @return {HttpClientBuilder} - */ - hooks(hooks: import('got').Hooks): HttpClientBuilder - - /** - * Defines if redirect responses should be followed automatically. - * - * Note that if a `303` is sent by the server in response to any request type (`POST`, `DELETE`, etc.), Got will automatically request the resource pointed to in the location header via `GET`. - * This is in accordance with [the spec](https://tools.ietf.org/html/rfc7231#section-6.4.4). You can optionally turn on this behavior also for other redirect codes - see `methodRewriting`. - * - * @param followRedirect {boolean} - * @return {HttpClientBuilder} - */ - followRedirect(followRedirect: boolean): HttpClientBuilder - - /** - * Defines if redirect responses should be followed automatically. - * - * Note that if a `303` is sent by the server in response to any request type (`POST`, `DELETE`, etc.), Got will automatically request the resource pointed to in the location header via `GET`. - * This is in accordance with [the spec](https://tools.ietf.org/html/rfc7231#section-6.4.4). You can optionally turn on this behavior also for other redirect codes - see `methodRewriting`. - * - * @param followRedirect {boolean} - * @return {HttpClientBuilder} - */ - followRedirects(followRedirect: boolean): HttpClientBuilder - - /** - * If exceeded, the request will be aborted and a `MaxRedirectsError` will be thrown. - * - * @param maxRedirects {number} - * @return {HttpClientBuilder} - */ - maxRedirects(maxRedirects: number): HttpClientBuilder - - /** - * A cache adapter instance for storing cached response data. - * - * @param cache {string | import('keyv').Store | boolean } - * @return {HttpClientBuilder} - */ - cache(cache: string | import('keyv').Store | boolean): HttpClientBuilder - - /** - * Determines if a `got.HTTPError` is thrown for unsuccessful responses. - * - * If this is disabled, requests that encounter an error status code will be resolved with the `response` instead of throwing. - * This may be useful if you are checking for resource availability and are expecting error responses. - * - * @param throwHttpErrors {boolean} - * @return {HttpClientBuilder} - */ - throwHttpErrors(throwHttpErrors: boolean): HttpClientBuilder - - /** - * Set the username. - * - * @param value {string} - * @return {HttpClientBuilder} - */ - username(value: string): HttpClientBuilder - - /** - * Set the password. - * - * @param value {string} - * @return {HttpClientBuilder} - */ - password(value: string): HttpClientBuilder - - /** - * If set to `true`, Got will additionally accept HTTP2 requests. - * - * It will choose either HTTP/1.1 or HTTP/2 depending on the ALPN protocol. - * - * __Note__: This option requires Node.js 15.10.0 or newer as HTTP/2 support on older Node.js versions is very buggy. - * - * __Note__: Overriding `options.request` will disable HTTP2 support. - * - * @example - * ``` - * const {headers} = await HttpClient.builder() - * .http2(true) - * .get('https://nghttp2.org/httpbin/anything') - * - * console.log(headers.via) - * //=> '2 nghttpx' - * ``` - * - * @param value {boolean} - * @return {HttpClientBuilder} - */ - http2(value: boolean): HttpClientBuilder - - /** - * Set this to `true` to allow sending body for the `GET` method. - * However, the [HTTP/2 specification](https://tools.ietf.org/html/rfc7540#section-8.1.3) says that `An HTTP GET request includes request header fields and no payload body`, therefore when using the HTTP/2 protocol this option will have no effect. - * This option is only meant to interact with non-compliant servers when you have no other choice. - * - * __Note__: The [RFC 7231](https://tools.ietf.org/html/rfc7231#section-4.3.1) doesn't specify any particular behavior for the GET method having a payload, therefore __it's considered an [anti-pattern](https://en.wikipedia.org/wiki/Anti-pattern)__. - * - * @param value {boolean} - * @return {HttpClientBuilder} - */ - allowGetBody(value: boolean): HttpClientBuilder - - /** - * Specifies if the HTTP request method should be [rewritten as `GET`](https://tools.ietf.org/html/rfc7231#section-6.4) on redirects. - * - * As the [specification](https://tools.ietf.org/html/rfc7231#section-6.4) prefers to rewrite the HTTP method only on `303` responses, this is Got's default behavior. - * Setting `methodRewriting` to `true` will also rewrite `301` and `302` responses, as allowed by the spec. This is the behavior followed by `curl` and browsers. - * - * __Note__: Got never performs method rewriting on `307` and `308` responses, as this is [explicitly prohibited by the specification](https://www.rfc-editor.org/rfc/rfc7231#section-6.4.7). - * - * @param value {boolean} - * @return {HttpClientBuilder} - */ - methodRewriting(value: boolean): HttpClientBuilder - - /** - * Indicates which DNS record family to use. - * - * Values: - * - `undefined`: IPv4 (if present) or IPv6 - * - `4`: Only IPv4 - * - `6`: Only IPv6 - * - * @param dnsLookupIpVersion {import('got').DnsLookupIpVersion} - * @return {HttpClientBuilder} - */ - dnsLookupIpVersion( - dnsLookupIpVersion: import('got').DnsLookupIpVersion, - ): HttpClientBuilder - - /** - * A function used to parse JSON responses. - * - * @example - * ``` - * import Bourne from '@hapi/bourne' - * - * const parsed = await HttpClient.builder() - * .url('https://example.com') - * .parseJson(text => Bourne.parse(text)) - * .request() - * .json() - * - * console.log(parsed) - * ``` - * - * @param fn {import('got').ParseJsonFunction} - * @return {HttpClientBuilder} - */ - parseJson(fn: import('got').ParseJsonFunction): HttpClientBuilder - - /** - * A function used to stringify the body of JSON requests. - * - * @example - * ``` - * await HttpClient.builder() - * .method('POST') - * .url('https://example.com') - * .body({ some: 'payload', _ignoreMe: 1234 }) - * .stringifyJson(object => JSON.stringify(object, (key, value) => { - * if (key.startsWith('_')) { - * return - * } - * - * return value - * })) - * .request() - * ``` - * - * @param fn {import('got').StringifyJsonFunction} - * @return {HttpClientBuilder} - */ - stringifyJson(fn: import('got').StringifyJsonFunction): HttpClientBuilder - - /** - * An object representing `limit`, `calculateDelay`, `methods`, `statusCodes`, `maxRetryAfter` and `errorCodes` fields for maximum retry count, retry handler, allowed methods, allowed status codes, maximum [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) time and allowed error codes. - * - * Delays between retries counts with function `1000 * Math.pow(2, retry) + Math.random() * 100`, where `retry` is attempt number (starts from 1). - * - * The `calculateDelay` property is a `function` that receives an object with `attemptCount`, `retryOptions`, `error` and `computedValue` properties for current retry count, the retry options, error and default computed value. - * The function must return a delay in milliseconds (or a Promise resolving with it) (`0` return value cancels retry). - * - * By default, it retries *only* on the specified methods, status codes, and on these network errors: - * - * - `ETIMEDOUT`: One of the [timeout](#timeout) limits were reached. - * - `ECONNRESET`: Connection was forcibly closed by a peer. - * - `EADDRINUSE`: Could not bind to any free port. - * - `ECONNREFUSED`: Connection was refused by the server. - * - `EPIPE`: The remote side of the stream being written has been closed. - * - `ENOTFOUND`: Couldn't resolve the hostname to an IP address. - * - `ENETUNREACH`: No internet connection. - * - `EAI_AGAIN`: DNS lookup timed out. - * - * __Note__: If `maxRetryAfter` is set to `undefined`, it will use `options.timeout`. - * __Note__: If [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) header is greater than `maxRetryAfter`, it will cancel the request. - * - * @param retry {Partial} - * @return {HttpClientBuilder} - */ - retry(retry: Partial): HttpClientBuilder - - /** - * This method is just an alias to set the limit of retry requests that - * can be done and the strategy to use to set the delay between retry requests. - * - * The strategy function needs to return the delay between the execution count - * of each request, if the strategy function returns 0, the retry is canceled. - * - * @param strategy {(response: import('got').RequestError, execCount: number, retryObject: import('got').RetryObject) => number | Promise} - * @return {HttpClientBuilder} - */ - retryStrategy( - strategy: ( - response: import('got').RequestError, - execCount: number, - retryObject: import('got').RetryObject, - ) => number | Promise, - ): HttpClientBuilder - - /** - * From `http.RequestOptions`. - * - * The IP address used to send the request from. - * - * @param localAddress {string} - * @return {HttpClientBuilder} - */ - localAddress(localAddress: string): HttpClientBuilder - - /** - * Set the createConnection options. - * - * @param value {import('got').CreateConnectionFunction} - * @return {HttpClientBuilder} - */ - createConnection( - value: import('got').CreateConnectionFunction, - ): HttpClientBuilder - - /** - * Options for the advanced HTTPS API. - * - * @param https {import('got').HttpsOptions} - * @return {HttpClientBuilder} - */ - https(https: import('got').HttpsOptions): HttpClientBuilder - - /** - * [Encoding](https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings) to be used on `setEncoding` of the response data. - * - * To get a [`Buffer`](https://nodejs.org/api/buffer.html), you need to set `responseType` to `buffer` instead. - * Don't set this option to `null`. - * - * __Note__: This doesn't affect streams! Instead, you need to do `got.stream(...).setEncoding(encoding)`. - * - * @param encoding {BufferEncoding} - * @return {HttpClientBuilder} - */ - encoding(encoding: BufferEncoding): HttpClientBuilder - - /** - * When set to `true` the promise will return the - * Response body instead of the Response object. - * - * @param resolveBodyOnly {boolean} - * @return {HttpClientBuilder} - */ - resolveBodyOnly(resolveBodyOnly: boolean): HttpClientBuilder - - /** - * Returns a `Stream` instead of a `Promise`. - * This is equivalent to calling `got.stream(url, options?)`. - * - * @param value {boolean} - * @return {HttpClientBuilder} - */ - isStream(value: boolean): HttpClientBuilder - - /** - * The parsing method. - * - * The promise also has `.text()`, `.json()` and `.buffer()` methods which return another Got promise for the parsed body. - * - * It's like setting the options to `{responseType: 'json', resolveBodyOnly: true}` but without affecting the main Got promise. - * - * __Note__: When using streams, this option is ignored. - * - * @example - * ``` - * const responsePromise = HttpClient.get(url); - * const bufferPromise = responsePromise.buffer(); - * const jsonPromise = responsePromise.json(); - * - * const [response, buffer, json] = Promise.all([responsePromise, bufferPromise, jsonPromise]); - * // `response` is an instance of Got Response - * // `buffer` is an instance of Buffer - * // `json` is an object - * ``` - * - * @example - * ``` - * // This - * const body = await HttpClient.get(url).json(); - * - * // is semantically the same as this - * const body = await HttpClient.get(url, { responseType: 'json', resolveBodyOnly: true }) - * ``` - * - * @param type {import('got').ResponseType} - * @return {HttpClientBuilder} - */ - responseType(type: import('got').ResponseType): HttpClientBuilder - - /** - * Set pagination options. - * - * @param options {import('got').PaginationOptions} - * @return {HttpClientBuilder} - */ - pagination( - options: import('got').PaginationOptions, - ): HttpClientBuilder - - /** - * Set the auth option. - * - * @param value {any} - * @return {HttpClientBuilder} - */ - auth(value: any): HttpClientBuilder - - /** - * Set the host option. - * - * @param value {boolean} - * @return {HttpClientBuilder} - */ - setHost(value: boolean): HttpClientBuilder - - /** - * Set the maxHeaderSize option. - * - * @param maxHeaderSize {number} - * @return {HttpClientBuilder} - */ - maxHeaderSize(maxHeaderSize: number): HttpClientBuilder - - /** - * Set the enableUnixSockets option. - * - * @param enableUnixSockets {boolean} - * @return {HttpClientBuilder} - */ - enableUnixSockets(enableUnixSockets: boolean): HttpClientBuilder - - /** - * Set the merge options. - * - * @param options {GotOptions} - * @return {HttpClientBuilder} - */ - mergeOptions(options: GotOptions): HttpClientBuilder - - /** - * Execute the request and return as stream. - * - * @param [options] {GotOptions} - * @return {Request} - */ - stream(options?: GotOptions): Request - - /** - * Execute the request and return paginated data. - * - * @param [options] {GotOptions} - * @return {AsyncIterableIterator} - */ - paginate(options?: GotOptions): AsyncIterableIterator - - /** - * Execute the request using all the options defined. - * - * @param [options] {GotOptions} - * @return {CancelableRequest | CancelableRequest | Request} - */ - request( - options?: GotOptions, - ): CancelableRequest | CancelableRequest | Request - - /** - * Make a GET request. - * - * @param [url] {string} - * @param [options] {GotOptions} - * @return {CancelableRequest | CancelableRequest | Request} - */ - get( - url?: string, - options?: GotOptions, - ): CancelableRequest | CancelableRequest | Request - - /** - * Make a POST request. - * - * @param [url] {string} - * @param [body] {Record | string | ReadableStream | Generator | AsyncGenerator | import('form-data-encoder').FormDataLike} - * @param [options] {GotOptions} - * @return {CancelableRequest | CancelableRequest | Request} - */ - post( - url?: string, - body?: - | Record - | string - | ReadableStream - | Generator - | AsyncGenerator - | import('form-data-encoder').FormDataLike, - options?: GotOptions, - ): CancelableRequest | CancelableRequest | Request - - /** - * Make a PUT request. - * - * @param [url] {string} - * @param [body] {Record | string | ReadableStream | Generator | AsyncGenerator | import('form-data-encoder').FormDataLike} - * @param [options] {GotOptions} - * @return {CancelableRequest | CancelableRequest | Request} - */ - put( - url?: string, - body?: - | Record - | string - | ReadableStream - | Generator - | AsyncGenerator - | import('form-data-encoder').FormDataLike, - options?: GotOptions, - ): CancelableRequest | CancelableRequest | Request - - /** - * Make a PATCH request. - * - * @param [url] {string} - * @param [body] {Record | string | ReadableStream | Generator | AsyncGenerator | import('form-data-encoder').FormDataLike} - * @param [options] {GotOptions} - * @return {CancelableRequest | CancelableRequest | Request} - */ - patch( - url?: string, - body?: - | Record - | string - | ReadableStream - | Generator - | AsyncGenerator - | import('form-data-encoder').FormDataLike, - options?: GotOptions, - ): CancelableRequest | CancelableRequest | Request - - /** - * Make a DELETE request. - * - * @param [url] {string} - * @param [options] {GotOptions} - * @return {CancelableRequest | CancelableRequest | Request} - */ - delete( - url?: string, - options?: GotOptions, - ): CancelableRequest | CancelableRequest | Request - - /** - * Make a HEAD request. - * - * @param [url] {string} - * @param [options] {GotOptions} - * @return {CancelableRequest | CancelableRequest | Request} - */ - head( - url?: string, - options?: GotOptions, - ): CancelableRequest | CancelableRequest | Request -} - -export declare class HttpClient { - /** - * Set the global builder for HttpClient. - * - * @param builder {HttpClientBuilder} - * @return {typeof HttpClient} - */ - static setBuilder(builder: HttpClientBuilder): typeof HttpClient - - /** - * Uses the instance of HttpClientBuilder or creates - * a new one. - * - * @param [newBuilder] {boolean} - * @return {HttpClientBuilder} - */ - static builder(newBuilder?: boolean): HttpClientBuilder - - /** - * Make a GET request. - * - * @param [url] {string} - * @param [options] {GotOptions} - * @return {CancelableRequest | CancelableRequest | Request} - */ - static get(url?: string, options?: GotOptions): CancelableRequest - - /** - * Make a POST request. - * - * @param [url] {string} - * @param [body] {Record | string | ReadableStream | Generator | AsyncGenerator | import('form-data-encoder').FormDataLike} - * @param [options] {GotOptions} - * @return {CancelableRequest | CancelableRequest | Request} - */ - static post( - url?: string, - body?: - | Record - | string - | ReadableStream - | Generator - | AsyncGenerator - | import('form-data-encoder').FormDataLike, - options?: GotOptions, - ): CancelableRequest | CancelableRequest | Request - - /** - * Make a PUT request. - * - * @param [url] {string} - * @param [body] {Record | string | ReadableStream | Generator | AsyncGenerator | import('form-data-encoder').FormDataLike} - * @param [options] {GotOptions} - * @return {CancelableRequest | CancelableRequest | Request} - */ - static put( - url?: string, - body?: - | Record - | string - | ReadableStream - | Generator - | AsyncGenerator - | import('form-data-encoder').FormDataLike, - options?: GotOptions, - ): CancelableRequest | CancelableRequest | Request - - /** - * Make a PATCH request. - * - * @param [url] {string} - * @param [body] {Record | string | ReadableStream | Generator | AsyncGenerator | import('form-data-encoder').FormDataLike} - * @param [options] {GotOptions} - * @return {CancelableRequest | CancelableRequest | Request} - */ - static patch( - url?: string, - body?: - | Record - | string - | ReadableStream - | Generator - | AsyncGenerator - | import('form-data-encoder').FormDataLike, - options?: GotOptions, - ): CancelableRequest | CancelableRequest | Request - - /** - * Make a DELETE request. - * - * @param [url] {string} - * @param [options] {GotOptions} - * @return {CancelableRequest | CancelableRequest | Request} - */ - static delete( - url?: string, - options?: GotOptions, - ): CancelableRequest | CancelableRequest | Request - - /** - * Make a HEAD request. - * - * @param [url] {string} - * @param [options] {GotOptions} - * @return {CancelableRequest | CancelableRequest | Request} - */ - static head( - url?: string, - options?: GotOptions, - ): CancelableRequest | CancelableRequest | Request -} - -export declare class Is { - /** - * Verify if is valid Uuid. - * - * @param {string} value - * @return {boolean} - */ - static Uuid(value: string): boolean - - /** - * Verify if is valid Json. - * - * @param {string} value - * @return {boolean} - */ - static Json(value: string): boolean - - /** - * Verify if is valid Ip. - * - * @param {string} value - * @return {boolean} - */ - static Ip(value: string): boolean - - /** - * Verify if is valid Empty. - * - * @param {string|any|any[]} value - * @return {boolean} - */ - static Empty(value: string | any | any[]): boolean - - /** - * Verify if is a valid Cep. - * - * @param {string|number} cep - * @return {boolean} - */ - static Cep(cep: string | number): boolean - - /** - * Verify if is a valid Cpf. - * - * @param {string|number} cpf - * @return {boolean} - */ - static Cpf(cpf: string | number): boolean - - /** - * Verify if is a valid Cnpj. - * - * @param {string|number} cnpj - * @return {boolean} - */ - static Cnpj(cnpj: string | number): boolean - - /** - * Verify if is a valid Async function. - * - * @param {any} value - * @return {boolean} - */ - static Async(value: any): value is Promise - - /** - * Verify if is a valid Undefined. - * - * @param {any} value - * @return {boolean} - */ - static Undefined(value: any): value is undefined - - /** - * Verify if is a valid Null. - * - * @param {any} value - * @return {boolean} - */ - static Null(value: any): value is null - - /** - * Verify if is a valid Boolean. - * - * @param {any} value - * @return {boolean} - */ - static Boolean(value: any): value is boolean - - /** - * Verify if is a valid Buffer. - * - * @param {any} value - * @return {boolean} - */ - static Buffer(value: any): value is Buffer - - /** - * Verify if is a valid Number. - * - * @param {any} value - * @return {boolean} - */ - static Number(value: any): value is number - - /** - * Verify if is a valid String. - * - * @param {any} value - * @return {boolean} - */ - static String(value: any): value is string - - /** - * Verify if is a valid Object. - * - * @param {any} value - * @return {boolean} - */ - static Object(value: any): value is Object - - /** - * Verify if is a valid Date. - * - * @param {any} value - * @return {boolean} - */ - static Date(value: any): value is Date - - /** - * Verify if is a valid Array. - * - * @param {any} value - * @return {boolean} - */ - static Array(value: any): value is any[] - - /** - * Verify if is a valid Regexp. - * - * @param {any} value - * @return {boolean} - */ - static Regexp(value: any): value is RegExp - - /** - * Verify if is a valid Error. - * - * @param {any} value - * @return {boolean} - */ - static Error(value: any): value is Error - - /** - * Verify if is a valid Function. - * - * @param {any} value - * @return {boolean} - */ - static Function(value: any): value is Function - - /** - * Verify if is a valid Class. - * - * @param {any} value - * @return {boolean} - */ - static Class(value: any): boolean - - /** - * Verify if is a valid Integer. - * - * @param {any} value - * @return {boolean} - */ - static Integer(value: any): value is number - - /** - * Verify if is a valid Float. - * - * @param {any} value - * @return {boolean} - */ - static Float(value: any): value is number - - /** - * Verify if is a valid ArrayOfObjects. - * - * @param {any[]} value - * @return {boolean} - */ - static ArrayOfObjects(value: any[]): boolean -} - -export declare class Json { - /** - * Deep copy any object properties without reference. - * - * @param {any} object - * @return {any} - */ - static copy(object: any): any - - /** - * Find all JSON inside string and return it. - * - * @param {string} text - * @return {string[]} - */ - static getJson(text: string): string[] - - /** - * Reviver callback. - * - * @callback reviver - * @param {any} this - * @param {string} key - * @param {any} value - * @return any - */ - - /** - * Converts a JSON string into an object without exception. - * - * @param {string} text - * @param {reviver} [reviver] - * @return {any} - */ - static parse(text: string, reviver?: any): any - - /** - * Observe changes inside objects. - * - * @param {any} object - * @param {function} func - * @param {...any[]} args - * @return {any} - */ - static observeChanges(object: any, func: any, ...args: any[]) - - /** - * Remove all keys from data that is not inside array keys. - * - * @param {any} data - * @param {any[]} keys - * @return {any[]} - */ - static fillable(data: any, keys: any[]): any[] - - /** - * Remove all duplicated values from the array. - * - * @param {any[]} array - * @return {any[]} - */ - static removeDuplicated(array: any[]): any[] - - /** - * Raffle any value from the array. - * - * @param {any[]} array - * @return {number} - */ - static raffle(array: any[]): number - - /** - * Get the object properties based on key. - * - * @param {string} key - * @param {any} [defaultValue] - * @param {any} object - * @return {any|undefined} - */ - static get(object: any, key: string, defaultValue?: any): any | undefined -} - -export class Module { - /** - * Get the module first export match or default. - * - * @param {any|Promise} module - * @return {Promise} - */ - static get(module: any | Promise): Promise - - /** - * Get the module first export match or default with alias. - * - * @param {any|Promise} module - * @param {string} subAlias - * @return {Promise<{ alias: string, module: any }>} - */ - static getWithAlias( - module: any | Promise, - subAlias: string, - ): Promise<{ alias: string; module: any }> - - /** - * Get all modules first export match or default and return - * as array. - * - * @param {any[]|Promise} modules - * @return {Promise} - */ - static getAll(modules: any[] | Promise): Promise - - /** - * Get all modules first export match or default with alias and return - * as array. - * - * @param {any[]|Promise} modules - * @param {string} subAlias - * @return {Promise} - */ - static getAllWithAlias( - modules: any[] | Promise, - subAlias: string, - ): Promise<{ alias: string; module: any }[]> - - /** - * Same as get method, but import the path directly. - * - * @param {string} path - * @return {Promise} - */ - static getFrom(path: string): Promise - - /** - * Same as getWithAlias method, but import the path directly. - * - * @param {string} path - * @param {string} subAlias - * @return {Promise<{ alias: string, module: any }>} - */ - static getFromWithAlias( - path: string, - subAlias: string, - ): Promise<{ alias: string; module: any }> - - /** - * Same as getAll method but import everything in the path directly. - * - * @param {string} path - * @return {Promise} - */ - static getAllFrom(path: string): Promise - - /** - * Same as getAllWithAlias method but import everything in the path directly. - * - * @param {string} path - * @param {string} subAlias - * @return {Promise<{ alias: string, module: any }[]>} - */ - static getAllFromWithAlias( - path: string, - subAlias: string, - ): Promise<{ alias: string; module: any }[]> - - /** - * Verify if folder exists and get all .js files inside. - * - * @param {string} path - * @return {Promise} - */ - static getAllJSFilesFrom(path: string): Promise - - /** - * Import a full path using the path href to ensure compatibility - * between OS's. - * - * @param {string} path - * @return {Promise} - */ - static import(path: string): Promise - - /** - * Create the __dirname property. Set in global if necessary. - * - * @param {string} [url] - * @param {boolean} [setInGlobal] - * @return {string} - */ - static createDirname(url?: string, setInGlobal?: boolean): string - - /** - * Create the __filename property. Set in global if necessary. - * - * @param {string} [url] - * @param {boolean} [setInGlobal] - * @return {string} - */ - static createFilename(url?: string, setInGlobal?: boolean): string -} - -export declare class Number { - /** - * Get the higher number from an array of numbers. - * - * @param {number[]} numbers - * @return {number} - */ - static getHigher(numbers: number[]): number - - /** - * Get km radius between two coordinates. - * - * @param {{ latitude: number, longitude: number }} centerCord - * @param {{ latitude: number, longitude: number }} pointCord - * @return {number} - */ - static getKmRadius( - centerCord: CoordinateContract, - pointCord: CoordinateContract, - ): number - - /** - * Get the lower number from an array of numbers. - * - * @param {number[]} numbers - * @return {number} - */ - static getLower(numbers: number[]): number - - /** - * Extract all numbers inside a string and - * return as a unique number. - * - * @param {string} string - * @return {number} - */ - static extractNumber(string: string): number - - /** - * Extract all numbers inside a string. - * - * @param {string} string - * @return {number[]} - */ - static extractNumbers(string: string): number[] - - /** - * The average of all numbers in function arguments. - * - * @param {number[]} args - * @return {number} - */ - static argsAverage(...args: number[]): number - - /** - * The average of all numbers in the array. - * - * @param {number[]} array - * @return {number} - */ - static arrayAverage(array: number[]): number - - /** - * Generate a random integer from a determined interval of numbers. - * - * @param {number} min - * @param {number} max - * @return {number} - */ - static randomIntFromInterval(min: number, max: number): number -} - -export declare class Options { - /** - * Creates an option object with default values. - * - * @param {any} object - * @param {any} defaultValues - * @return {any} - */ - static create(object: Partial, defaultValues: Partial): T -} - -export declare class Parser { - /** - * Parse a string to array. - * - * @param {string} string - * @param {string} separator - * @return {string[]} - */ - static stringToArray(string: string, separator: string): string[] - - /** - * Parse an array of strings to a string. - * - * @param {string[]} values - * @param {{ - * separator?: string, - * pairSeparator?: string, - * lastSeparator?: string - * }} [options] - * @return {string} - */ - static arrayToString( - values: string[], - options?: { - separator?: string - pairSeparator?: string - lastSeparator?: string - }, - ): string - - /** - * Parse a string to number or Coordinate. - * - * @param {string} string - * @param {boolean} isCoordinate - * @throws {InvalidNumberException} - * @return {number} - */ - static stringToNumber(string: string, isCoordinate: boolean): number - - /** - * Parse an object to form data. - * - * @param {any} object - * @return {string} - */ - static jsonToFormData(object: any): string - - /** - * Parse form data to json. - * - * @param {string} formData - * @return {any} - */ - static formDataToJson(formData: string): any - - /** - * Parses all links inside the string to HTML link - * with . - * - * @param {string} string - * @return {string} - */ - static linkToHref(string: string): any - - /** - * Parses a number to Byte format. - * - * @param {number} value - * @param {object} [options] - * @param {number} [options.decimalPlaces=2] - * @param {number} [options.fixedDecimals=false] - * @param {string} [options.thousandsSeparator=] - * @param {string} [options.unit=] - * @param {string} [options.unitSeparator=] - * @return {string} - */ - static sizeToByte( - value, - options?: { - decimalPlaces?: number - fixedDecimals?: boolean - thousandsSeparator?: any - unit?: any - unitSeparator?: any - }, - ): string - - /** - * Parses a byte format to number. - * - * @param {string|number} byte - * @return {number} - */ - static byteToSize(byte: string | number): number - - /** - * Parses a string to MS format. - * - * @param {string} value - * @return {number} - */ - static timeToMs(value: string): number - - /** - * Parses an MS number to time format. - * - * @param {number} value - * @param {boolean} long - * @return {string} - */ - static msToTime(value: number, long: boolean): string - - /** - * Parses the status code number to it reason in string. - * - * @param {string|number} status - * @return {string} - */ - static statusCodeToReason(status: string | number): string - - /** - * Parses the reason in string to it status code number - * - * @param {string} reason - * @return {number} - */ - static reasonToStatusCode(reason: string): number - - /** - * Parses the database connection url to connection object. - * - * @param {string} url - * @return {DBConnectionContract} - */ - static dbUrlToConnectionObj(url: string): DBConnectionContract - - /** - * Parses the database connection object to connection url. - * - * @param {DBConnectionContract} object - * @return {string} - */ - static connectionObjToDbUrl(object?: DBConnectionContract): string -} - -export declare class Path { - /** - * Set a default beforePath for all Path methods that - * use Path.pwd. - * - * @type {string} - */ - static defaultBeforePath: string - - /** - * Resolve the environment where the application - * is running by verifying the import.meta.url. - * - * This method will auto set the IS_TS env and the - * defaultBeforePath if IS_TS is true. - * - * The beforePath is always set as '/build' by default. - * - * @param metaUrl {string} - * @param beforePath {string} - * @return {typeof Path} - */ - static resolveEnvironment(metaUrl: string, beforePath?: string): typeof Path - - /** - * Return js or ts extension depending on IS_TS. - * - * @return {string} - */ - static ext(): string - - /** - * Return the pwd path of your project. - * - * @param {string} [subPath] - * @return {string} - */ - static pwd(subPath?: string): string - - /** - * Return the app path of your project. - * - * @param {string} subPath - * @return {string} - */ - static app(subPath?: string): string - - /** - * Return the bootstrap path of your project. - * - * @param {string} subPath - * @return {string} - */ - static bootstrap(subPath?: string): string - - /** - * Return the config path of your project. - * - * @param {string} subPath - * @return {string} - */ - static config(subPath?: string): string - - /** - * Return the database path of your project. - * - * @param {string} subPath - * @return {string} - */ - static database(subPath?: string): string - - /** - * Return the lang path of your project. - * - * @param {string} subPath - * @return {string} - */ - static lang(subPath?: string): string - - /** - * Return the node_modules path of your project. - * - * @param {string} subPath - * @return {string} - */ - static nodeModules(subPath?: string): string - - /** - * Return the providers' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static providers(subPath?: string): string - - /** - * Return the public path of your project. - * - * @param {string} subPath - * @return {string} - */ - static public(subPath?: string): string - - /** - * Return the resources' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static resources(subPath?: string): string - - /** - * Return the routes' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static routes(subPath?: string): string - - /** - * Return the storage path of your project. - * - * @param {string} subPath - * @return {string} - */ - static storage(subPath?: string): string - - /** - * Return the tests' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static tests(subPath?: string): string - - /** - * Return the logs' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static logs(subPath?: string): string - - /** - * Return the views' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static views(subPath?: string): string - - /** - * Return the assets' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static assets(subPath?: string): string - - /** - * Return the locales' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static locales(subPath?: string): string - - /** - * Return the facades' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static facades(subPath?: string): string - - /** - * Return the stubs' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static stubs(subPath?: string): string - - /** - * Return the http path of your project. - * - * @param {string} subPath - * @return {string} - */ - static http(subPath?: string): string - - /** - * Return the console path of your project. - * - * @param {string} subPath - * @return {string} - */ - static console(subPath?: string): string - - /** - * Return the services' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static services(subPath?: string): string - - /** - * Return the repositories' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static repositories(subPath?: string): string - - /** - * Return the migrations' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static migrations(subPath?: string): string - - /** - * Return the seeders' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static seeders(subPath?: string): string - - /** - * Return the .bin path of your node_modules. - * - * @param {string} subPath - * @return {string} - */ - static bin(subPath?: string): string - - /** - * Return the tmp path of your vm. - * - * @param {string} subPath - * @return {string} - */ - static vmTmp(subPath?: string): string - - /** - * Return the home path of your vm. - * - * @param {string} subPath - * @return {string} - */ - static vmHome(subPath?: string): string - - /** - * Return the execution path of where this method - * is being called. - * - * @param {string} subPath - * @param {number} [stackIndex] - * @return {string} - */ - static this(subPath?: string, stackIndex?: number): string -} - -export declare class Route { - /** - * Get the query string in form data format. - * - * @param {string} route - * @return {string} - */ - static getQueryString(route: string): string - - /** - * Remove query params from the route. - * - * @param {string} route - * @return {string} - */ - static removeQueryParams(route: string): string - - /** - * Get object with ?&queryParams values from route. - * - * @param {string} route - * @return {any} - */ - static getQueryParamsValue(route: string): any - - /** - * Get array with ?&queryParams name from route. - * - * @param {string} route - * @return {string[]} - */ - static getQueryParamsName(route: string): string[] - - /** - * Get object with :params values from route. - * - * @param {string} routeWithParams - * @param {string} routeWithValues - * @return {any} - */ - static getParamsValue(routeWithParams: string, routeWithValues: string): any - - /** - * Get array with :params name from route. - * - * @param {string} route - * @return {string[]} - */ - static getParamsName(route: string): string[] - - /** - * Create a matcher RegExp for any route. - * - * @param {string} route - * @return {RegExp} - */ - static createMatcher(route: string): RegExp -} - -export declare class String { - /** - * Generate random string by size. - * - * @param {number} size - * @return {string} - */ - static generateRandom(size: number): string - - /** - * Generate random color in hexadecimal format. - * - * @return {string} - */ - static generateRandomColor(): string - - /** - * Normalizes the string in base64 format removing - * special chars. - * - * @param {string} value - * @return {string} - */ - static normalizeBase64(value: string): string - - /** - * Transforms the string to "camelCase". - * - * @param {string} value - * @return {string} - */ - static toCamelCase(value: string): string - - /** - * Transforms the string to "snake_case". - * - * @param {string} value - * @param {boolean} [capitalize] - * @return {string} - */ - static toSnakeCase(value: string, capitalize?: boolean): string - - /** - * Transforms the string to "CONSTANT_CASE". - * - * @param {string} value - * @return {string} - */ - static toConstantCase(value: string): string - - /** - * Transforms the string to "PascalCase". - * - * @param {string} value - * @return {string} - */ - static toPascalCase(value: string): string - - /** - * Transforms the string to "Sentence case". - * - * @param {string} value - * @param {boolean} [capitalize] - * @return {string} - */ - static toSentenceCase(value: string, capitalize?: boolean): string - - /** - * Transforms the string to "dot.case". - * - * @param {string} value - * @param {boolean} [capitalize] - * @return {string} - */ - static toDotCase(value: string, capitalize?: boolean): string - - /** - * Removes all sorted cases from string. - * - * @param {string} value - * @return {string} - */ - static toNoCase(value: string): string - - /** - * Transforms a string to "dash-case" - * - * @param {string} value - * @param {boolean} [capitalize] - * @return {string} - */ - static toDashCase(value: string, capitalize?: boolean): string - - /** - * Transforms a word to plural. - * - * @param {string} word - * @return {string} - */ - static pluralize(word: string): string - - /** - * Transforms a word to singular. - * - * @param {string} word - * @return {string} - */ - static singularize(word: string): string - - /** - * Transforms a number to your ordinal format. - * - * @param {string,number} value - * @return {string} - */ - static ordinalize(value: string | number): string -} - -export declare class Uuid { - /** - * Verify if string is a valid uuid. - * - * @param {string} token - * @param {boolean} [isPrefixed] - * @return {boolean} - */ - static verify(token: string, isPrefixed?: boolean): boolean - - /** - * Generate an uuid token - * - * @param {string} [prefix] - * @return {string} - */ - static generate(prefix?: string): string - - /** - * Return the token without his prefix. - * - * @param {string} token - * @return {string} - */ - static getToken(token: string): string - - /** - * Return the prefix without his token. - * - * @param {string} token - * @return {string|null} - */ - static getPrefix(token: string): string | null - - /** - * Inject a prefix in the uuid token. - * - * @param {string} prefix - * @param {string} token - * @return {string} - */ - static injectPrefix(prefix: string, token: string): string - - /** - * Change the prefix of and uuid token - * - * @param {string} newPrefix - * @param {string} token - * @return {string} - */ - static changePrefix(newPrefix: string, token: string): string - - /** - * Change the token prefix or generate a new one - * - * @param {string} prefix - * @param {string?} token - * @return {string} - */ - static changeOrGenerate(prefix: string, token?: string): string -} - -declare global { - export class Path { - /** - * Set a default beforePath for all Path methods that - * use Path.pwd. - * - * @type {string} - */ - static defaultBeforePath: string - - /** - * Resolve the environment where the application - * is running by verifying the import.meta.url. - * - * This method will auto set the IS_TS env and the - * defaultBeforePath if IS_TS is true. - * - * The beforePath is always set as '/build' by default. - * - * @param metaUrl {string} - * @param beforePath {string} - * @return {typeof Path} - */ - static resolveEnvironment(metaUrl: string, beforePath?: string): typeof Path - - /** - * Return js or ts extension depending on IS_TS. - * - * @return {string} - */ - static ext(): string - - /** - * Return the pwd path of your project. - * - * @param {string} [subPath] - * @return {string} - */ - static pwd(subPath?: string): string - - /** - * Return the app path of your project. - * - * @param {string} subPath - * @return {string} - */ - static app(subPath?: string): string - - /** - * Return the bootstrap path of your project. - * - * @param {string} subPath - * @return {string} - */ - static bootstrap(subPath?: string): string - - /** - * Return the config path of your project. - * - * @param {string} subPath - * @return {string} - */ - static config(subPath?: string): string - - /** - * Return the database path of your project. - * - * @param {string} subPath - * @return {string} - */ - static database(subPath?: string): string - - /** - * Return the lang path of your project. - * - * @param {string} subPath - * @return {string} - */ - static lang(subPath?: string): string - - /** - * Return the node_modules path of your project. - * - * @param {string} subPath - * @return {string} - */ - static nodeModules(subPath?: string): string - - /** - * Return the providers' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static providers(subPath?: string): string - - /** - * Return the public path of your project. - * - * @param {string} subPath - * @return {string} - */ - static public(subPath?: string): string - - /** - * Return the resources' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static resources(subPath?: string): string - - /** - * Return the routes' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static routes(subPath?: string): string - - /** - * Return the storage path of your project. - * - * @param {string} subPath - * @return {string} - */ - static storage(subPath?: string): string - - /** - * Return the tests' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static tests(subPath?: string): string - - /** - * Return the logs' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static logs(subPath?: string): string - - /** - * Return the views' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static views(subPath?: string): string - - /** - * Return the assets' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static assets(subPath?: string): string - - /** - * Return the locales' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static locales(subPath?: string): string - - /** - * Return the facades' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static facades(subPath?: string): string - - /** - * Return the stubs' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static stubs(subPath?: string): string - - /** - * Return the http path of your project. - * - * @param {string} subPath - * @return {string} - */ - static http(subPath?: string): string - - /** - * Return the console path of your project. - * - * @param {string} subPath - * @return {string} - */ - static console(subPath?: string): string - - /** - * Return the services' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static services(subPath?: string): string - - /** - * Return the repositories' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static repositories(subPath?: string): string - - /** - * Return the migrations' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static migrations(subPath?: string): string - - /** - * Return the seeders' path of your project. - * - * @param {string} subPath - * @return {string} - */ - static seeders(subPath?: string): string - - /** - * Return the .bin path of your node_modules. - * - * @param {string} subPath - * @return {string} - */ - static bin(subPath?: string): string - - /** - * Return the tmp path of your vm. - * - * @param {string} subPath - * @return {string} - */ - static vmTmp(subPath?: string): string - - /** - * Return the home path of your vm. - * - * @param {string} subPath - * @return {string} - */ - static vmHome(subPath?: string): string - - /** - * Return the execution path of where this method - * is being called. - * - * @param {string} subPath - * @param {number} [stackIndex] - * @return {string} - */ - static this(subPath?: string, stackIndex?: number): string - } - - interface Array { - toResource(criterias?: any): T[] - - toCollection(): Collection - } - - interface ErrorConstructor { - /** - * Transform your error to an instance of - * the Athenna exception. - * - * @param options {{ - * code?: string, - * status?: number, - * content?: string, - * help?: string, - * stack?: any - * }} - * @return {Exception} - */ - toAthennaException(options?: { - code?: string - status?: number - content?: string - help?: string - stack?: any - }): Exception - } -} diff --git a/src/index.js b/src/index.ts similarity index 71% rename from src/index.js rename to src/index.ts index 7682a70..a1bb083 100644 --- a/src/index.js +++ b/src/index.ts @@ -7,13 +7,14 @@ * file that was distributed with this source code. */ -// Helpers -import { Path } from './Helpers/Path.js' +import('./Globals/Path.js') +import('./Globals/Array.js') +import('./Globals/Error.js') +export * from './Helpers/Exception.js' export * from './Helpers/Clean.js' export * from './Helpers/Collection.js' export * from './Helpers/Debug.js' -export * from './Helpers/Exception.js' export * from './Helpers/Exec.js' export * from './Helpers/FakeApi.js' export * from './Helpers/File.js' @@ -30,6 +31,9 @@ export * from './Helpers/Route.js' export * from './Helpers/String.js' export * from './Helpers/Uuid.js' -if (!global.Path) { - global.Path = Path -} +export * from './Types/Merge.js' +export * from './Types/Except.js' +export * from './Types/HttpClient/Body.js' +export * from './Types/HttpClient/Query.js' +export * from './Types/HttpClient/ReqOptions.js' +export * from './Types/HttpClient/RetryStrategyCallback.js' diff --git a/tests/Stubs/config/app.d.ts b/tests/Stubs/config/app.d.ts deleted file mode 100644 index e69de29..0000000 diff --git a/tests/Stubs/config/app.js.map b/tests/Stubs/config/app.js.map deleted file mode 100644 index e69de29..0000000 diff --git a/tests/Stubs/config/app.js b/tests/Stubs/config/app.ts similarity index 82% rename from tests/Stubs/config/app.js rename to tests/Stubs/config/app.ts index f3375ab..86f6ae4 100644 --- a/tests/Stubs/config/app.js +++ b/tests/Stubs/config/app.ts @@ -8,6 +8,5 @@ */ export default { - name: 'SecJS', - env: process.env.NODE_ENV, + name: 'Athenna', } diff --git a/tests/Unit/CleanTest.js b/tests/Unit/CleanTest.ts similarity index 100% rename from tests/Unit/CleanTest.js rename to tests/Unit/CleanTest.ts diff --git a/tests/Unit/CollectionTest.js b/tests/Unit/CollectionTest.ts similarity index 100% rename from tests/Unit/CollectionTest.js rename to tests/Unit/CollectionTest.ts diff --git a/tests/Unit/DebugTest.js b/tests/Unit/DebugTest.ts similarity index 100% rename from tests/Unit/DebugTest.js rename to tests/Unit/DebugTest.ts diff --git a/tests/Unit/ExceptionTest.js b/tests/Unit/ExceptionTest.ts similarity index 77% rename from tests/Unit/ExceptionTest.js rename to tests/Unit/ExceptionTest.ts index 1687f76..572042b 100644 --- a/tests/Unit/ExceptionTest.js +++ b/tests/Unit/ExceptionTest.ts @@ -12,18 +12,19 @@ import { Exception } from '#src/index' test.group('ExceptionTest', () => { test('should be able to create a new exception', async ({ assert }) => { - const exception = new Exception('My custom instance error', 500) + const exception = new Exception({ message: 'My custom instance error' }) const errorJson = exception.toJSON() assert.equal(errorJson.status, 500) assert.equal(errorJson.code, 'EXCEPTION') assert.equal(errorJson.name, 'Exception') - assert.equal(errorJson.content, 'My custom instance error') + assert.equal(errorJson.message, 'My custom instance error') }) test('should be able to create a new exception from vanilla errors', async ({ assert }) => { const exception = new Error('My custom instance error').toAthennaException({ + status: 0, code: 'EXCEPTION', name: 'Exception', }) @@ -33,13 +34,13 @@ test.group('ExceptionTest', () => { assert.equal(errorJson.status, 0) assert.equal(errorJson.code, 'EXCEPTION') assert.equal(errorJson.name, 'Exception') - assert.equal(errorJson.content, 'My custom instance error') + assert.equal(errorJson.message, 'My custom instance error') }) test('should be able to extend exception class to create a new exception', async ({ assert }) => { class InternalServerException extends Exception { constructor(content = 'Internal Server Error', status = 500) { - super(content, status, 'E_RUNTIME_EXCEPTION', 'Restart computer.') + super({ message: content, status, code: 'E_RUNTIME_EXCEPTION', help: 'Restart computer.' }) } } @@ -51,13 +52,18 @@ test.group('ExceptionTest', () => { assert.equal(errorJson.status, 500) assert.equal(errorJson.code, 'E_RUNTIME_EXCEPTION') assert.equal(errorJson.name, 'InternalServerException') - assert.equal(errorJson.content, 'Internal Server Error') + assert.equal(errorJson.message, 'Internal Server Error') }) test('should be able to pretiffy the exception', async ({ assert }) => { class InternalServerException extends Exception { constructor(content = 'Internal Server Error.', status = 500) { - super(content, status, 'E_RUNTIME_EXCEPTION', 'Restart your computer, works always. 👍') + super({ + status, + message: content, + code: 'E_RUNTIME_EXCEPTION', + help: 'Restart your computer, works always. 👍', + }) } } diff --git a/tests/Unit/ExecTest.js b/tests/Unit/ExecTest.ts similarity index 96% rename from tests/Unit/ExecTest.js rename to tests/Unit/ExecTest.ts index 8b2fc74..ba52801 100644 --- a/tests/Unit/ExecTest.js +++ b/tests/Unit/ExecTest.ts @@ -27,7 +27,9 @@ test.group('ExecTest', group => { }) test('should throw an node exec exception when command fails', async ({ assert }) => { - const useCase = async () => await Exec.command('echo "error thrown" && exit 255') + const useCase = async () => { + await Exec.command('echo "error thrown" && exit 255') + } await assert.rejects(useCase, NodeCommandException) }) diff --git a/tests/Unit/FakeApiTest.js b/tests/Unit/FakeApiTest.ts similarity index 100% rename from tests/Unit/FakeApiTest.js rename to tests/Unit/FakeApiTest.ts diff --git a/tests/Unit/FileTest.js b/tests/Unit/FileTest.ts similarity index 100% rename from tests/Unit/FileTest.js rename to tests/Unit/FileTest.ts diff --git a/tests/Unit/FolderTest.js b/tests/Unit/FolderTest.ts similarity index 100% rename from tests/Unit/FolderTest.js rename to tests/Unit/FolderTest.ts diff --git a/tests/Unit/HttpClientTest.js b/tests/Unit/HttpClientTest.ts similarity index 95% rename from tests/Unit/HttpClientTest.js rename to tests/Unit/HttpClientTest.ts index 051200c..a636a41 100644 --- a/tests/Unit/HttpClientTest.js +++ b/tests/Unit/HttpClientTest.ts @@ -9,6 +9,7 @@ import stream from 'node:stream' +import { Response } from 'got' import { test } from '@japa/runner' import { promisify } from 'node:util' import { File } from '#src/Helpers/File' @@ -30,7 +31,6 @@ test.group('HttpClientTest', group => { builder .http2(false) .setHost(true) - .isStream(false) .timeout(10000) .dnsCache(false) .prefixUrl(FAKE_API_URL) @@ -47,7 +47,7 @@ test.group('HttpClientTest', group => { .throwHttpErrors(true) .resolveBodyOnly(false) .enableUnixSockets(true) - .retryStrategy((response, execCount) => { + .retryStrategy((_response, execCount) => { if (execCount === 3) { return 0 } @@ -227,7 +227,7 @@ test.group('HttpClientTest', group => { test('should be able to setup init hooks for requests', async ({ assert }) => { const builder = HttpClient.builder() - .setInitHook(plain => { + .setInitHook((plain: any) => { assert.isTrue('followRedirects' in plain) if ('followRedirects' in plain) { @@ -236,14 +236,16 @@ test.group('HttpClientTest', group => { delete plain.followRedirects } }) - .mergeOptions({ followRedirects: true }) + .mergeOptions({ followRedirects: true } as any) await builder.get('/users').json() }) test('should be able to setup before request hooks for requests', async ({ assert }) => { const builder = HttpClient.builder().setBeforeRequestHook(options => { - assert.isTrue(options.body.includes('payload')) + const body = options.body as string + + assert.isTrue(body.includes('payload')) options.body = JSON.stringify({ payload: 'new' }) options.headers['content-length'] = options.body.length.toString() @@ -254,7 +256,7 @@ test.group('HttpClientTest', group => { }) test('should be able to setup before redirect hooks for requests', async ({ assert }) => { - const builder = HttpClient.builder().setBeforeRedirectHook((options, response) => { + const builder = HttpClient.builder().setBeforeRedirectHook((options: any, _response) => { assert.deepEqual(options.hostname, 'deadSite') if (options.hostname === 'deadSite') { @@ -269,7 +271,7 @@ test.group('HttpClientTest', group => { const builder = HttpClient.builder(true) .responseType('json') .setBeforeErrorHook(error => { - const { response } = error + const response: Response<{ message?: string }> = error.response if (response && response.body) { error.name = 'GitHubError' @@ -288,7 +290,7 @@ test.group('HttpClientTest', group => { }) test('should be able to setup before retry hooks for requests', async ({ assert }) => { - const builder = HttpClient.builder().setBeforeRetryHook((error, retryCount) => + const builder = HttpClient.builder().setBeforeRetryHook((error, _retryCount) => assert.deepEqual(error.name, 'ERR_NON_2XX_3XX_RESPONSE'), ) @@ -313,7 +315,7 @@ test.group('HttpClientTest', group => { }) test('should be able to make a get request and get the response as stream', async ({ assert }) => { - const requestStream = HttpClient.builder().isStream(true).get('users') + const requestStream = HttpClient.builder().url('users').stream() const file = new File(Path.stubs('streamed.json'), Buffer.from('')) await pipeline(requestStream, file.createWriteStream()) diff --git a/tests/Unit/IsTest.js b/tests/Unit/IsTest.ts similarity index 97% rename from tests/Unit/IsTest.js rename to tests/Unit/IsTest.ts index 6ed9201..6cf2174 100644 --- a/tests/Unit/IsTest.js +++ b/tests/Unit/IsTest.ts @@ -10,7 +10,7 @@ import { test } from '@japa/runner' import { Is, Exception } from '#src/index' -test.group('\n IsTest', () => { +test.group('IsTest', () => { test('should verify if is a valid json string', async ({ assert }) => { assert.isFalse(Is.Json('')) assert.isFalse(Is.Json('Hello')) @@ -156,7 +156,7 @@ test.group('\n IsTest', () => { assert.isFalse(Is.Error(0)) assert.isFalse(Is.Error('')) assert.isTrue(Is.Error(new Error())) - assert.isTrue(Is.Error(new Exception('Test'))) + assert.isTrue(Is.Error(new Exception({ message: 'Test' }))) }) test('should verify if is a valid function', async ({ assert }) => { @@ -196,8 +196,6 @@ test.group('\n IsTest', () => { }, ] - assert.isFalse(Is.ArrayOfObjects(0)) - assert.isFalse(Is.ArrayOfObjects('')) assert.isFalse(Is.ArrayOfObjects([])) assert.isFalse(Is.ArrayOfObjects([1, 2, 3])) assert.isFalse(Is.ArrayOfObjects(['', '', ''])) diff --git a/tests/Unit/JsonTest.js b/tests/Unit/JsonTest.js deleted file mode 100644 index 11109b4..0000000 --- a/tests/Unit/JsonTest.js +++ /dev/null @@ -1,122 +0,0 @@ -/** - * @athenna/common - * - * (c) João Lenon - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -import { test } from '@japa/runner' -import { Exec, Json } from '#src/index' - -test.group('Json Class', () => { - test('should return a deep copy from the object', async ({ assert }) => { - const object = { - test: 'hello', - hello: () => 'hy', - } - - const objectCopy = Json.copy(object) - - objectCopy.test = 'hello from copy' - objectCopy.hello = () => 'hy from copy' - - assert.equal(object.test, 'hello') - assert.equal(object.hello(), 'hy') - assert.equal(objectCopy.test, 'hello from copy') - assert.equal(objectCopy.hello(), 'hy from copy') - }) - - test('should return all json found inside of the string', async ({ assert }) => { - const text = 'this is a string with a json inside of it {"text":"hello"} and one more json {"hello":"world"}' - - assert.deepEqual(Json.getJson(text), ['{"text":"hello"}', '{"hello":"world"}']) - }) - - test('should return null if JSON parse goes wrong', async ({ assert }) => { - const text = 'a string that is not a valid JSON' - - assert.isNull(Json.parse(text)) - }) - - test('should return the object when string is a valid JSON', async ({ assert }) => { - const text = '{"text":"hello"}' - - assert.deepEqual(Json.parse(text), { text: 'hello' }) - }) - - test('should clean data object removing all keys that are not in key array', async ({ assert }) => { - const data = { - hello: 'hello', - world: 'world', - } - - assert.deepEqual(Json.fillable(data, ['world']), { world: 'world' }) - assert.deepEqual(Json.fillable(data, ['world', 'someNullWord']), { world: 'world' }) - }) - - test('should be able to observe changes of an object', async ({ assert }) => { - const object = { - joao: 'lenon', - hello: 'world', - } - - const objectProxy = Json.observeChanges( - object, - (value, arg1, arg2, arg3) => { - assert.equal(value, 'oi') - assert.equal(arg1, 1) - assert.equal(arg2, 2) - assert.equal(arg3, 3) - }, - 1, - 2, - 3, - ) - - objectProxy.joao = 'oi' - - await Exec.sleep(2000) - }) - - test('should be able to remove duplicated values from array', async ({ assert }) => { - const array = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5] - - assert.deepEqual(Json.removeDuplicated(array), [1, 2, 3, 4, 5]) - }) - - test('should be able to raffle any value from the array', async ({ assert }) => { - const array = [1, 2, 3, 4, 5] - - const raffledValue = Json.raffle(array) - - assert.isDefined(array.find(a => a === raffledValue)) - }) - - test('should be able to get nested properties from object', async ({ assert }) => { - const object = { - hello: { - world: { - value: { - hello: 'Hello World!', - }, - }, - }, - } - - const value = Json.get(object, 'hello.world.value.hello') - const undefinedValue = Json.get(object, 'hello.worlld.value.hello') - const defaultValue = Json.get(object, 'hello.worlld.value.hello', 'Hi World!') - const fullObject = Json.get(object, '') - const defaultValueInObjectNull = Json.get(undefined, '', { hello: 'world' }) - const falsyDefaultValue = Json.get(object, 'hello.not-found', false) - - assert.equal(value, 'Hello World!') - assert.equal(defaultValue, 'Hi World!') - assert.isUndefined(undefinedValue) - assert.deepEqual(object, fullObject) - assert.deepEqual(defaultValueInObjectNull, { hello: 'world' }) - assert.deepEqual(falsyDefaultValue, false) - }) -}) diff --git a/tests/Unit/JsonTest.ts b/tests/Unit/JsonTest.ts new file mode 100644 index 0000000..162c57a --- /dev/null +++ b/tests/Unit/JsonTest.ts @@ -0,0 +1,227 @@ +/** + * @athenna/common + * + * (c) João Lenon + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import { test } from '@japa/runner' +import { Exec, Json } from '#src/index' + +test.group('Json Class', () => { + test('should return a deep copy from the object', async ({ assert }) => { + const object = { + test: 'hello', + hello: () => 'hy', + } + + const objectCopy = Json.copy(object) + + objectCopy.test = 'hello from copy' + objectCopy.hello = () => 'hy from copy' + + assert.equal(object.test, 'hello') + assert.equal(object.hello(), 'hy') + assert.equal(objectCopy.test, 'hello from copy') + assert.equal(objectCopy.hello(), 'hy from copy') + }) + + test('should return all json found inside of the string', async ({ assert }) => { + const text = 'this is a string with a json inside of it {"text":"hello"} and one more json {"hello":"world"}' + + assert.deepEqual(Json.getJson(text), ['{"text":"hello"}', '{"hello":"world"}']) + }) + + test('should return null if JSON parse goes wrong', async ({ assert }) => { + const text = 'a string that is not a valid JSON' + + assert.isNull(Json.parse(text)) + }) + + test('should return the object when string is a valid JSON', async ({ assert }) => { + const text = '{"text":"hello"}' + + assert.deepEqual(Json.parse(text), { text: 'hello' }) + }) + + test('should clean data object removing all keys that are not in key array', async ({ assert }) => { + const data = { + hello: 'hello', + world: 'world', + } + + assert.deepEqual(Json.fillable(data, ['world']), { world: 'world' }) + assert.deepEqual(Json.fillable(data, ['world', 'someNullWord']), { world: 'world' }) + }) + + test('should be able to observe changes of an object', async ({ assert }) => { + const object = { + joao: 'lenon', + hello: 'world', + } + + const objectProxy = Json.observeChanges( + object, + (value, arg1, arg2, arg3) => { + assert.equal(value, 'oi') + assert.equal(arg1, 1) + assert.equal(arg2, 2) + assert.equal(arg3, 3) + }, + 1, + 2, + 3, + ) + + objectProxy.joao = 'oi' + + await Exec.sleep(2000) + }) + + test('should be able to remove duplicated values from array', async ({ assert }) => { + const array = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5] + + assert.deepEqual(Json.removeDuplicated(array), [1, 2, 3, 4, 5]) + }) + + test('should be able to raffle any value from the array', async ({ assert }) => { + const array = [1, 2, 3, 4, 5] + + const raffledValue = Json.raffle(array) + + assert.isDefined(array.find(a => a === raffledValue)) + }) + + test('should be able to get nested properties from object', async ({ assert }) => { + const object = { + hello: { + world: { + value: { + hello: 'Hello World!', + }, + }, + }, + } + + const value = Json.get(object, 'hello.world.value.hello') + const undefinedValue = Json.get(object, 'hello.worlld.value.hello') + const defaultValue = Json.get(object, 'hello.worlld.value.hello', 'Hi World!') + const fullObject = Json.get(object, '') + const defaultValueInObjectNull = Json.get(undefined, '', { hello: 'world' }) + const falsyDefaultValue = Json.get(object, 'hello.not-found', false) + + assert.equal(value, 'Hello World!') + assert.equal(defaultValue, 'Hi World!') + assert.isUndefined(undefinedValue) + assert.deepEqual(object, fullObject) + assert.deepEqual(defaultValueInObjectNull, { hello: 'world' }) + assert.deepEqual(falsyDefaultValue, false) + }) + + test('should be able to build objects using the ObjectBuilder', async ({ assert }) => { + const me = Json.builder() + .set('name', 'João Lenon') + .set('email', 'lenon@athenna.io') + .set('age', 22) + .set('details.car.color', 'white') + .set('details.car.name', 'BMW E46 M3') + .set('details.favoriteColor', 'black') + .set('details.job', 'Software Engineer') + .set('createdAt', new Date('2000-12-09').toISOString()) + .set('updatedAt', new Date('2022-12-09').toISOString()) + .set('deletedAt', null) + .set('willNotBeSet', undefined) + .set('willSetDefaultOne', null, 'Hello') + .set('willSetDefaultTwo', undefined, 'Hello') + .get() + + assert.deepEqual(me, { + name: 'João Lenon', + email: 'lenon@athenna.io', + age: 22, + details: { + car: { + color: 'white', + name: 'BMW E46 M3', + }, + job: 'Software Engineer', + favoriteColor: 'black', + }, + createdAt: '2000-12-09T00:00:00.000Z', + updatedAt: '2022-12-09T00:00:00.000Z', + deletedAt: null, + willSetDefaultOne: 'Hello', + willSetDefaultTwo: 'Hello', + }) + + const ignores = Json.builder({ ignoreNull: true, ignoreUndefined: true, defaultValue: 'Global' }) + .set('name', null) + .set('email', undefined) + .set('age', 0) + .set('createdAt', undefined, new Date('2000-12-09').toISOString()) + .get() + + assert.deepEqual(ignores, { + name: 'Global', + email: 'Global', + age: 0, + createdAt: '2000-12-09T00:00:00.000Z', + }) + }) + + test('should be able to build objects and get the values using nested key path', async ({ assert }) => { + const builder = Json.builder() + .set('name', 'João Lenon') + .set('email', 'lenon@athenna.io') + .set('age', 22) + .set('details.car.color', 'white') + .set('details.car.name', 'BMW E46 M3') + .set('details.favoriteColor', 'black') + .set('details.job', 'Software Engineer') + .set('createdAt', new Date('2000-12-09').toISOString()) + .set('updatedAt', new Date('2022-12-09').toISOString()) + .set('deletedAt', null) + .set('willNotBeSet', undefined) + .set('willSetDefaultOne', null, 'Hello') + .set('willSetDefaultTwo', undefined, 'Hello') + + assert.equal(builder.get('details.car.name'), 'BMW E46 M3') + assert.equal(builder.get('deletedAt', new Date('2022-12-09').toISOString()), null) + assert.equal( + builder.get('deletedAt.notFound', new Date('2022-12-09').toISOString()), + new Date('2022-12-09').toISOString(), + ) + }) + + test('should be able to build objects and validate the values using nested key path', async ({ assert }) => { + const builder = Json.builder() + .set('name', 'João Lenon') + .set('email', 'lenon@athenna.io') + .set('age', 22) + .set('details.car.color', 'white') + .set('details.car.name', 'BMW E46 M3') + .set('details.favoriteColor', 'black') + .set('details.job', 'Software Engineer') + .set('createdAt', new Date('2000-12-09').toISOString()) + .set('updatedAt', new Date('2022-12-09').toISOString()) + .set('deletedAt', null) + .set('willNotBeSet', undefined) + .set('willSetDefaultOne', null, 'Hello') + .set('willSetDefaultTwo', undefined, 'Hello') + + assert.isTrue(builder.existsAll('name', 'details.car', 'details.car.name')) + assert.isFalse(builder.notExistsAll('name', 'details.car', 'details.car.name')) + + assert.isTrue(builder.is('details.car.name', 'FAKE1', 'FAKE2', 'BMW E46 M3')) + assert.isFalse(builder.is('details.car.name', 'FAKE1', 'FAKE2', 'FAKE3')) + assert.isFalse(builder.isNot('details.car.name', 'FAKE1', 'FAKE2', 'BMW E46 M3')) + assert.isTrue(builder.isNot('details.car.name', 'FAKE1', 'FAKE2', 'FAKE3')) + + assert.isTrue(builder.is('details.car.name', ['FAKE1', 'FAKE2', 'BMW E46 M3'])) + assert.isFalse(builder.is('details.car.name', ['FAKE1', 'FAKE2', 'FAKE3'])) + assert.isFalse(builder.isNot('details.car.name', ['FAKE1', 'FAKE2', 'BMW E46 M3'])) + assert.isTrue(builder.isNot('details.car.name', ['FAKE1', 'FAKE2', 'FAKE3'])) + }) +}) diff --git a/tests/Unit/ModuleTest.js b/tests/Unit/ModuleTest.ts similarity index 85% rename from tests/Unit/ModuleTest.js rename to tests/Unit/ModuleTest.ts index 096e684..8f49ad7 100644 --- a/tests/Unit/ModuleTest.js +++ b/tests/Unit/ModuleTest.ts @@ -10,11 +10,11 @@ import { test } from '@japa/runner' import { Module, Path } from '#src/index' -test.group('ExecTest', group => { +test.group('ModuleTest', () => { test('should be able to get the module first export match or default', async ({ assert }) => { const moduleDefault = await Module.get(import('../Stubs/config/app.js')) - assert.equal(moduleDefault.name, 'SecJS') + assert.equal(moduleDefault.name, 'Athenna') const moduleFirstExport = await Module.get(import('#src/Helpers/Options')) @@ -26,7 +26,7 @@ test.group('ExecTest', group => { const modulesResolved = await Module.getAll(modules) - assert.equal(modulesResolved[0].name, 'SecJS') + assert.equal(modulesResolved[0].name, 'Athenna') assert.equal(modulesResolved[1].name, 'Options') }) @@ -43,11 +43,11 @@ test.group('ExecTest', group => { }) test('should be able to get the module first export match or default from any path', async ({ assert }) => { - const moduleDefault = await Module.getFrom(Path.stubs('config/app.js')) + const moduleDefault = await Module.getFrom(Path.stubs('config/app.ts')) - assert.equal(moduleDefault.name, 'SecJS') + assert.equal(moduleDefault.name, 'Athenna') - const moduleFirstExport = await Module.getFrom(Path.pwd('src/Helpers/Options.js')) + const moduleFirstExport = await Module.getFrom(Path.pwd('src/Helpers/Options.ts')) assert.equal(moduleFirstExport.name, 'Options') }) @@ -72,7 +72,7 @@ test.group('ExecTest', group => { test('should be able to create __filename property inside node global', async ({ assert }) => { Module.createFilename(import.meta.url, true) - assert.isTrue(__filename.includes('ModuleTest.js')) + assert.isTrue(__filename.includes('ModuleTest.ts')) }) test('should be able to create __dirname property inside node global', async ({ assert }) => { @@ -80,4 +80,10 @@ test.group('ExecTest', group => { assert.isTrue(__dirname.includes('Unit')) }) + + test('should be able to safe import some path without errors', async ({ assert }) => { + const nullValue = await Module.safeImport(Path.pwd('not-found.ts')) + + assert.isNull(nullValue) + }) }) diff --git a/tests/Unit/NumberTest.js b/tests/Unit/NumberTest.ts similarity index 100% rename from tests/Unit/NumberTest.js rename to tests/Unit/NumberTest.ts diff --git a/tests/Unit/ParserTest.js b/tests/Unit/ParserTest.ts similarity index 100% rename from tests/Unit/ParserTest.js rename to tests/Unit/ParserTest.ts diff --git a/tests/Unit/PathTest.js b/tests/Unit/PathTest.ts similarity index 94% rename from tests/Unit/PathTest.js rename to tests/Unit/PathTest.ts index e69f47b..a2e0cfb 100644 --- a/tests/Unit/PathTest.js +++ b/tests/Unit/PathTest.ts @@ -13,51 +13,50 @@ import { test } from '@japa/runner' test.group('PathTest', () => { test('should be able to resolve the environment where the app will run', async ({ assert }) => { const metaUrl = import.meta.url - const metaUrlTs = metaUrl.replace('.js', '.ts') + const metaUrlJs = metaUrl.replace('.ts', '.js') - Path.resolveEnvironment(metaUrlTs) + Path.resolveEnvironment(metaUrl) assert.equal(process.env.IS_TS, 'true') assert.equal(Path.defaultBeforePath, '') delete process.env.IS_TS - Path.resolveEnvironment(metaUrlTs, '/build') + Path.resolveEnvironment(metaUrl, '/build') assert.equal(process.env.IS_TS, 'true') assert.equal(Path.defaultBeforePath, '') delete process.env.IS_TS - Path.resolveEnvironment(metaUrl, '/build') + Path.resolveEnvironment(metaUrlJs, '/build') assert.equal(process.env.IS_TS, 'false') assert.equal(Path.defaultBeforePath, '/build') delete process.env.IS_TS - Path.resolveEnvironment(metaUrl) + Path.resolveEnvironment(metaUrlJs) assert.equal(process.env.IS_TS, 'false') assert.equal(Path.defaultBeforePath, '') + + process.env.IS_TS = 'true' }) test('should get the extension js and ts', async ({ assert }) => { - assert.equal(Path.ext(), 'js') - - process.env.IS_TS = true assert.equal(Path.ext(), 'ts') - process.env.IS_TS = 'true' - assert.equal(Path.ext(), 'ts') + process.env.IS_TS = 'false' + assert.equal(Path.ext(), 'js') - process.env.IS_TS = '(true)' - assert.equal(Path.ext(), 'ts') + process.env.IS_TS = '(false)' + assert.equal(Path.ext(), 'js') process.env.IS_TS = 'false' Path.defaultBeforePath = 'build' - console.log(Path.pwd(`artisan.${Path.ext()}`)) assert.isTrue(Path.pwd(`artisan.${Path.ext()}`).includes(`build${sep}artisan.js`)) Path.defaultBeforePath = '' + process.env.IS_TS = 'true' }) test('should get pwd path', async ({ assert }) => { diff --git a/tests/Unit/RouteTest.js b/tests/Unit/RouteTest.ts similarity index 100% rename from tests/Unit/RouteTest.js rename to tests/Unit/RouteTest.ts diff --git a/tests/Unit/StringTest.js b/tests/Unit/StringTest.ts similarity index 98% rename from tests/Unit/StringTest.js rename to tests/Unit/StringTest.ts index bcf225f..fd71730 100644 --- a/tests/Unit/StringTest.js +++ b/tests/Unit/StringTest.ts @@ -11,7 +11,7 @@ import { test } from '@japa/runner' import { String } from '#src/index' import { OrdinalNanException } from '#src/Exceptions/OrdinalNanException' -test.group('\n StringTest', () => { +test.group('StringTest', () => { test('should generate random strings by size', async ({ assert }) => { assert.lengthOf(String.generateRandom(10), 10) assert.lengthOf(String.generateRandom(20), 20) diff --git a/tests/Unit/UuidTest.js b/tests/Unit/UuidTest.ts similarity index 100% rename from tests/Unit/UuidTest.js rename to tests/Unit/UuidTest.ts diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..e2ff82f --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,19 @@ +{ + "ts-node": { + "esm": true, + "swc": true + }, + "compilerOptions": { + "strict": false, + "rootDir": ".", + "outDir": "build", + "module": "ESNext", + "target": "ESNext", + "esModuleInterop": true, + "skipLibCheck": true, + "removeComments": false, + "resolveJsonModule": true, + "moduleResolution": "NodeNext" + }, + "exclude": ["node_modules"] +}