diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..fd2171e --- /dev/null +++ b/.eslintignore @@ -0,0 +1,4 @@ +node_modules +dist +coverage +*.d.ts diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..71254a7 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "parser": "@typescript-eslint/parser", + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:prettier/recommended" + ], + "env": { + "node": true, + "es6": true, + "jest": true + }, + "parserOptions": { + "ecmaVersion": 2020, + "sourceType": "module" + }, + "rules": {} +} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..eb73077 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,29 @@ +name: Lint + +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Use Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + cache: "npm" + + - name: Install dependencies + run: npm ci + + - name: Run lint + run: npm run lint + + - name: Run prettier check + run: npm run prettier diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 7affe0a..8774309 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -3,10 +3,10 @@ name: Publish Package on: push: tags: - - 'v*' + - "v*" permissions: - id-token: write # Required for OIDC + id-token: write # Required for OIDC contents: read jobs: @@ -17,8 +17,8 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: '20' - registry-url: 'https://registry.npmjs.org' + node-version: "20" + registry-url: "https://registry.npmjs.org" # Ensure npm 11.5.1 or later is installed - name: Update npm diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..68f9def --- /dev/null +++ b/.prettierignore @@ -0,0 +1,4 @@ +node_modules +dist +coverage +package-lock.json diff --git a/jest.config.js b/jest.config.js index 5bb6c19..99d4e51 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,17 +1,13 @@ export default { - preset: 'ts-jest', - testEnvironment: 'node', - roots: ['/src'], - testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'], + preset: "ts-jest", + testEnvironment: "node", + roots: ["/src"], + testMatch: ["**/__tests__/**/*.ts", "**/?(*.)+(spec|test).ts"], transform: { - '^.+\\.ts$': 'ts-jest', + "^.+\\.ts$": "ts-jest", }, - collectCoverageFrom: [ - 'src/**/*.ts', - '!src/**/*.test.ts', - '!src/**/*.d.ts', - ], + collectCoverageFrom: ["src/**/*.ts", "!src/**/*.test.ts", "!src/**/*.d.ts"], moduleNameMapper: { - '^(\\.{1,2}/.*)\\.js$': '$1', + "^(\\.{1,2}/.*)\\.js$": "$1", }, -}; \ No newline at end of file +}; diff --git a/package-lock.json b/package-lock.json index a370f85..9ba4132 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@aep_dev/aep-lib-ts", - "version": "0.0.1", + "version": "0.0.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@aep_dev/aep-lib-ts", - "version": "0.0.1", + "version": "0.0.2", "license": "MIT", "dependencies": { "axios": "^1.6.0", @@ -17,8 +17,14 @@ "@types/jest": "^29.5.0", "@types/js-yaml": "^4.0.0", "@types/node": "^20.10.0", + "@typescript-eslint/eslint-plugin": "^8.56.0", + "@typescript-eslint/parser": "^8.56.0", + "eslint": "^8.57.1", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-prettier": "^5.5.5", "jest": "^29.7.0", "nock": "^13.4.0", + "prettier": "^3.8.1", "ts-jest": "^29.1.0", "typescript": "^5.3.0", "yargs": "^17.7.0" @@ -523,6 +529,109 @@ "dev": true, "license": "MIT" }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -916,6 +1025,53 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -1077,6 +1233,307 @@ "dev": true, "license": "MIT" }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.56.0.tgz", + "integrity": "sha512-lRyPDLzNCuae71A3t9NEINBiTn7swyOhvUj3MyUOxb8x6g6vPEFoOU+ZRmGMusNC3X3YMhqMIX7i8ShqhT74Pw==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.56.0", + "@typescript-eslint/type-utils": "8.56.0", + "@typescript-eslint/utils": "8.56.0", + "@typescript-eslint/visitor-keys": "8.56.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.56.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.0.tgz", + "integrity": "sha512-IgSWvLobTDOjnaxAfDTIHaECbkNlAlKv2j5SjpB2v7QHKv1FIfjwMy8FsDbVfDX/KjmCmYICcw7uGaXLhtsLNg==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "8.56.0", + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/typescript-estree": "8.56.0", + "@typescript-eslint/visitor-keys": "8.56.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.0.tgz", + "integrity": "sha512-M3rnyL1vIQOMeWxTWIW096/TtVP+8W3p/XnaFflhmcFp+U4zlxUxWj4XwNs6HbDeTtN4yun0GNTTDBw/SvufKg==", + "dev": true, + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.56.0", + "@typescript-eslint/types": "^8.56.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.0.tgz", + "integrity": "sha512-7UiO/XwMHquH+ZzfVCfUNkIXlp/yQjjnlYUyYz7pfvlK3/EyyN6BK+emDmGNyQLBtLGaYrTAI6KOw8tFucWL2w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/visitor-keys": "8.56.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.0.tgz", + "integrity": "sha512-bSJoIIt4o3lKXD3xmDh9chZcjCz5Lk8xS7Rxn+6l5/pKrDpkCwtQNQQwZ2qRPk7TkUYhrq3WPIHXOXlbXP0itg==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.56.0.tgz", + "integrity": "sha512-qX2L3HWOU2nuDs6GzglBeuFXviDODreS58tLY/BALPC7iu3Fa+J7EOTwnX9PdNBxUI7Uh0ntP0YWGnxCkXzmfA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/typescript-estree": "8.56.0", + "@typescript-eslint/utils": "8.56.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.0.tgz", + "integrity": "sha512-DBsLPs3GsWhX5HylbP9HNG15U0bnwut55Lx12bHB9MpXxQ+R5GC8MwQe+N1UFXxAeQDvEsEDY6ZYwX03K7Z6HQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.0.tgz", + "integrity": "sha512-ex1nTUMWrseMltXUHmR2GAQ4d+WjkZCT4f+4bVsps8QEdh0vlBsaCokKTPlnqBFqqGaxilDNJG7b8dolW2m43Q==", + "dev": true, + "dependencies": { + "@typescript-eslint/project-service": "8.56.0", + "@typescript-eslint/tsconfig-utils": "8.56.0", + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/visitor-keys": "8.56.0", + "debug": "^4.4.3", + "minimatch": "^9.0.5", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.0.tgz", + "integrity": "sha512-RZ3Qsmi2nFGsS+n+kjLAYDPVlrzf7UhTffrDIKr+h2yzAlYP/y5ZulU0yeDEPItos2Ph46JAL5P/On3pe7kDIQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.56.0", + "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/typescript-estree": "8.56.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.0.tgz", + "integrity": "sha512-q+SL+b+05Ud6LbEE35qe4A99P+htKTKVbyiNEe45eCbJFyh/HVK9QXwlrbz+Q4L8SOW4roxSVwXYj4DMBT7Ieg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.56.0", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.0.tgz", + "integrity": "sha512-A0XeIi7CXU7nPlfHS9loMYEKxUaONu/hTEzHTGba9Huu94Cq1hPivf+DE5erJozZOky0LfvXAyrV/tcswpLI0Q==", + "dev": true, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -1587,11 +2044,10 @@ } }, "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, - "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -1619,6 +2075,12 @@ } } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -1658,6 +2120,18 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -1781,18 +2255,273 @@ "node": ">=8" } }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.5.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz", + "integrity": "sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.1", + "synckit": "^0.11.12" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, "node_modules/execa": { @@ -1845,6 +2574,18 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -1852,6 +2593,21 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/fb-watchman": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", @@ -1862,6 +2618,18 @@ "bser": "2.1.1" } }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -1889,6 +2657,26 @@ "node": ">=8" } }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true + }, "node_modules/follow-redirects": { "version": "1.15.11", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", @@ -2058,6 +2846,45 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globals/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -2077,6 +2904,12 @@ "dev": true, "license": "ISC" }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "node_modules/handlebars": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", @@ -2165,6 +2998,40 @@ "node": ">=10.17.0" } }, + "node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/import-local": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", @@ -2230,6 +3097,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -2250,6 +3126,18 @@ "node": ">=6" } }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -2260,6 +3148,15 @@ "node": ">=0.12.0" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -2992,6 +3889,12 @@ "node": ">=6" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -2999,6 +3902,18 @@ "dev": true, "license": "MIT" }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -3019,6 +3934,15 @@ "node": ">=6" } }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -3039,6 +3963,19 @@ "node": ">=6" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -3066,6 +4003,12 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -3305,6 +4248,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -3360,6 +4320,18 @@ "node": ">=6" } }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -3459,6 +4431,42 @@ "node": ">=8" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", + "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", + "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -3517,6 +4525,15 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "license": "MIT" }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/pure-rand": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", @@ -3534,6 +4551,26 @@ ], "license": "MIT" }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -3605,6 +4642,55 @@ "node": ">=10" } }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -3804,6 +4890,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/synckit": { + "version": "0.11.12", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz", + "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==", + "dev": true, + "dependencies": { + "@pkgr/core": "^0.2.9" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -3819,6 +4920,57 @@ "node": ">=8" } }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -3839,6 +4991,18 @@ "node": ">=8.0" } }, + "node_modules/ts-api-utils": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", + "dev": true, + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, "node_modules/ts-jest": { "version": "29.4.1", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.1.tgz", @@ -3930,6 +5094,18 @@ "url": "https://github.com/fullstack-build/tslog?sponsor=1" } }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -4019,6 +5195,15 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/v8-to-istanbul": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", @@ -4060,6 +5245,15 @@ "node": ">= 8" } }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", diff --git a/package.json b/package.json index c8a7c92..d02ec0b 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,12 @@ "test": "jest", "test:watch": "jest --watch", "prepublishOnly": "npm run clean && npm run build && npm run test", - "dev": "tsc --watch" + "dev": "tsc --watch", + "lint": "eslint . --ext .ts,.tsx,.js", + "lint:fix": "eslint . --ext .ts,.tsx,.js --fix", + "prettier": "prettier --check .", + "prettier:fix": "prettier --write .", + "fix": "npm run lint:fix && npm run prettier:fix" }, "dependencies": { "axios": "^1.6.0", @@ -54,8 +59,14 @@ "@types/jest": "^29.5.0", "@types/js-yaml": "^4.0.0", "@types/node": "^20.10.0", + "@typescript-eslint/eslint-plugin": "^8.56.0", + "@typescript-eslint/parser": "^8.56.0", + "eslint": "^8.57.1", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-prettier": "^5.5.5", "jest": "^29.7.0", "nock": "^13.4.0", + "prettier": "^3.8.1", "ts-jest": "^29.1.0", "typescript": "^5.3.0", "yargs": "^17.7.0" diff --git a/src/api/api.test.ts b/src/api/api.test.ts index 942a579..2552ebb 100644 --- a/src/api/api.test.ts +++ b/src/api/api.test.ts @@ -1,10 +1,6 @@ -/// -import { API, Resource } from "./types.js"; -import { Contact, OpenAPI, Schema } from "../openapi/types.js"; +import { API } from "./types.js"; +import { OpenAPI } from "../openapi/types.js"; import { APIClient } from "./api.js"; -import { fetchOpenAPI, OpenAPIImpl } from "../openapi/openapi.js"; -import yargs from "yargs"; -import { hideBin } from "yargs/helpers"; const basicOpenAPI: OpenAPI = { openapi: "3.1.0", @@ -240,7 +236,7 @@ describe("APIClient", () => { describe("fromOpenAPI", () => { it("should handle basic resource with CRUD operations", async () => { const client = await APIClient.fromOpenAPI(basicOpenAPI); - const api = (client as any).api; + const api = (client as unknown as { api: API }).api; expect(api.serverURL).toBe("https://api.example.com"); @@ -259,16 +255,16 @@ describe("APIClient", () => { it("should handle non-resource schemas", async () => { const client = await APIClient.fromOpenAPI(basicOpenAPI); - const api = (client as any).api; + const api = (client as unknown as { api: API }).api; expect(api.schemas["Account"]).toBeDefined(); }); it("should handle server URL override", async () => { const client = await APIClient.fromOpenAPI( basicOpenAPI, - "https://override.example.com" + "https://override.example.com", ); - const api = (client as any).api; + const api = (client as unknown as { api: API }).api; expect(api.serverURL).toBe("https://override.example.com"); }); @@ -327,7 +323,7 @@ describe("APIClient", () => { }; const client = await APIClient.fromOpenAPI(openAPI); - const api = (client as any).api; + const api = (client as unknown as { api: API }).api; const widget = api.resources["widget"]; expect(widget).toBeDefined(); expect(widget.singular).toBe("widget"); @@ -350,7 +346,7 @@ describe("APIClient", () => { }; await expect(APIClient.fromOpenAPI(invalidOpenAPI)).rejects.toThrow( - "No server URL found in openapi, and none was provided" + "No server URL found in openapi, and none was provided", ); }); @@ -400,7 +396,7 @@ describe("APIClient", () => { }; const client = await APIClient.fromOpenAPI(openAPI); - const api = (client as any).api; + const api = (client as unknown as { api: API }).api; const widget = api.resources["widget"]; expect(widget).toBeDefined(); expect(widget.createMethod?.supportsUserSettableCreate).toBeTruthy(); @@ -408,7 +404,7 @@ describe("APIClient", () => { it("should handle contact information", async () => { const client = await APIClient.fromOpenAPI(basicOpenAPI); - const api = (client as any).api; + const api = (client as unknown as { api: API }).api; expect(api.contact).toBeDefined(); expect(api.contact?.name).toBe("John Doe"); expect(api.contact?.email).toBe("john.doe@example.com"); diff --git a/src/api/api.ts b/src/api/api.ts index 511dc94..c4cebb4 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -1,9 +1,4 @@ -import { - API, - PatternInfo, - Resource, - CustomMethod, -} from "./types.js"; +import { API, PatternInfo, Resource, CustomMethod } from "./types.js"; import { Contact, OpenAPI, @@ -24,11 +19,11 @@ export class APIClient { static async fromOpenAPI( openAPI: OpenAPI, serverURL: string = "", - pathPrefix: string = "" + pathPrefix: string = "", ): Promise { if (!openAPI.openapi && !openAPI.openapi) { throw new Error( - "Unable to detect OAS openapi. Please add an openapi field or a openapi field" + "Unable to detect OAS openapi. Please add an openapi field or a openapi field", ); } logger.info(`reading openapi file: ${openAPI.openapi}`); @@ -63,13 +58,13 @@ export class APIClient { if (!pathItem.post.requestBody) { throw new Error( - `Custom method ${patternInfo.customMethodName} has a POST response but no request body` + `Custom method ${patternInfo.customMethodName} has a POST response but no request body`, ); } const requestSchema = await dereferenceSchema( getSchemaFromRequestBody(pathItem.post.requestBody, openAPI), - openAPI + openAPI, ); customMethodsByPattern[pattern].push({ @@ -133,16 +128,16 @@ export class APIClient { const respSchema = getSchemaFromResponse(response, openAPI); if (!respSchema) { logger.warn( - `Resource ${path} has a LIST method with a response schema, but the response schema is null.` + `Resource ${path} has a LIST method with a response schema, but the response schema is null.`, ); } else { const resolvedSchema = await dereferenceSchema( respSchema, - openAPI + openAPI, ); const arrayProperty = Object.entries( - resolvedSchema.properties || {} - ).find(([_, prop]) => prop.type === "array"); + resolvedSchema.properties || {}, + ).find(([, prop]) => prop.type === "array"); if (arrayProperty) { schemaRef = arrayProperty[1].items || null; @@ -163,7 +158,7 @@ export class APIClient { } } else { logger.warn( - `Resource ${path} has a LIST method with a response schema, but the items field is not present or is not an array.` + `Resource ${path} has a LIST method with a response schema, but the items field is not present or is not an array.`, ); } } @@ -195,7 +190,7 @@ export class APIClient { pattern, dereferencedSchema, resourceBySingular, - openAPI + openAPI, ); if (r.getMethod) resource.getMethod = r.getMethod; @@ -208,10 +203,10 @@ export class APIClient { // Map custom methods to resources for (const [pattern, customMethods] of Object.entries( - customMethodsByPattern + customMethodsByPattern, )) { const resource = Object.values(resourceBySingular).find( - (r) => r.patternElems.join("/") === pattern + (r) => r.patternElems.join("/") === pattern, ); if (resource) { resource.customMethods = customMethods; @@ -228,7 +223,9 @@ export class APIClient { // Add non-resource schemas to API's schemas const schemas: Record = {}; - for (const [key, schema] of Object.entries(openAPI.components?.schemas || {})) { + for (const [key, schema] of Object.entries( + openAPI.components?.schemas || {}, + )) { if (!resourceBySingular[key]) { schemas[key] = schema; } @@ -289,7 +286,7 @@ async function getOrPopulateResource( pattern: string[], schema: Schema, resourceBySingular: Record, - openAPI: OpenAPI + openAPI: OpenAPI, ): Promise { if (resourceBySingular[singular]) { return resourceBySingular[singular]; @@ -304,7 +301,9 @@ async function getOrPopulateResource( // Parents will be set later on. parents: [], children: [], - patternElems: schema["x-aep-resource"].patterns![0].split("/").filter(Boolean), + patternElems: schema["x-aep-resource"] + .patterns![0].split("/") + .filter(Boolean), schema, customMethods: [], }; @@ -326,7 +325,7 @@ async function getOrPopulateResource( const parentSchema = openAPI.components?.schemas[parentSingular]; if (!parentSchema) { throw new Error( - `Resource "${singular}" parent "${parentSingular}" not found` + `Resource "${singular}" parent "${parentSingular}" not found`, ); } @@ -335,7 +334,7 @@ async function getOrPopulateResource( [], parentSchema, resourceBySingular, - openAPI + openAPI, ); resource.parents.push(parentResource); @@ -357,7 +356,7 @@ function getContact(contact?: Contact): Contact | null { function getSchemaFromResponse( response: OpenAPIResponse, - openAPI: OpenAPI + openAPI: OpenAPI, ): Schema | null { if (openAPI.openapi === "2.0") { return response.schema || null; @@ -367,7 +366,7 @@ function getSchemaFromResponse( function getSchemaFromRequestBody( requestBody: OpenAPIRequestBody, - openAPI: OpenAPI + openAPI: OpenAPI, ): Schema { if (openAPI.openapi === "2.0") { return requestBody.schema!; @@ -377,22 +376,22 @@ function getSchemaFromRequestBody( async function dereferenceSchema( schema: Schema, - openAPI: OpenAPI + openAPI: OpenAPI, ): Promise { if (!schema.$ref) { return schema; } if (schema.$ref.startsWith("http://") || schema.$ref.startsWith("https://")) { - logger.debug( - `Fetching external schema from ${schema.$ref}...`); + logger.debug(`Fetching external schema from ${schema.$ref}...`); const response = await fetch(schema.$ref); if (!response.ok) { throw new Error(`Failed to fetch external schema: ${schema.$ref}`); } - const externalSchema = await response.json() as Schema; + const externalSchema = (await response.json()) as Schema; logger.debug( - `Final schema fetched from ${schema.$ref}: ${JSON.stringify(externalSchema)}`); + `Final schema fetched from ${schema.$ref}: ${JSON.stringify(externalSchema)}`, + ); return dereferenceSchema(externalSchema, openAPI); } diff --git a/src/api/openapi.test.ts b/src/api/openapi.test.ts index 42c7fb0..93a79f2 100644 --- a/src/api/openapi.test.ts +++ b/src/api/openapi.test.ts @@ -1,13 +1,4 @@ -import { - API, - Resource, - ListMethod, -} from "./types.js"; -import { - Contact, - OpenAPI, - Schema, -} from "../openapi/types.js"; +import { API, Resource } from "./types.js"; import { convertToOpenAPI, generateParentPatternsWithParams, @@ -160,7 +151,7 @@ describe("convertToOpenAPI", () => { // Verify schemas exist expect(openAPI.components).toBeDefined(); - for (const [key, resource] of Object.entries(exampleAPI.resources)) { + for (const [, resource] of Object.entries(exampleAPI.resources)) { const schema = openAPI.components!.schemas[resource.singular]; expect(schema).toBeDefined(); expect(schema.type).toBe(resource.schema.type); @@ -380,7 +371,7 @@ describe("convertToOpenAPI", () => { expect(actualOp).toBeDefined(); if (!("operationId" in actualOp!)) { throw new Error( - `operationId not found in actualOp for ${path} ${method}` + `operationId not found in actualOp for ${path} ${method}`, ); } expect(actualOp!.operationId).toBe(expectedOp.operationId); @@ -388,7 +379,7 @@ describe("convertToOpenAPI", () => { if ("parameters" in expectedOp) { if (!("parameters" in actualOp!)) { throw new Error( - `Expected 'parameters' in actualOp for ${path} ${method}` + `Expected 'parameters' in actualOp for ${path} ${method}`, ); } console.log(path + " " + method); @@ -398,7 +389,7 @@ describe("convertToOpenAPI", () => { if ("requestBody" in expectedOp) { if (!("requestBody" in actualOp!)) { throw new Error( - `Expected 'requestBody' in actualOp for ${path} ${method}` + `Expected 'requestBody' in actualOp for ${path} ${method}`, ); } expect(actualOp!.requestBody).toEqual(expectedOp.requestBody); diff --git a/src/api/openapi.ts b/src/api/openapi.ts index c9deb60..ec5c4ad 100644 --- a/src/api/openapi.ts +++ b/src/api/openapi.ts @@ -1,10 +1,5 @@ +import { API, PathWithParams, Resource } from "./types.js"; import { - API, - PathWithParams, - Resource, -} from "./types.js"; -import { - Contact, OpenAPI, PathItem, Schema, @@ -227,19 +222,16 @@ export function convertToOpenAPI(api: API): OpenAPI { for (const custom of r.customMethods) { const methodType = custom.method.toLowerCase(); const cmPath = `${resourcePath}:${custom.name}`; - const methodInfo = { - operationId: `:${kebabToPascalCase(custom.name)}${kebabToPascalCase( - singular - )}`, + const methodInfo: Operation = { + operationId: `:${kebabToPascalCase(custom.name)}${kebabToPascalCase(singular)}`, description: `Custom method ${custom.name} for ${singular}`, parameters: [...pwp.params, idParam], - requestBody: {}, responses: { "200": { description: "Successful response", content: { "application/json": { - schema: custom.response, + schema: custom.response || undefined, }, }, }, @@ -251,7 +243,7 @@ export function convertToOpenAPI(api: API): OpenAPI { required: true, content: { "application/json": { - schema: custom.request, + schema: custom.request || undefined, }, }, }; @@ -299,13 +291,11 @@ export function convertToOpenAPI(api: API): OpenAPI { } export function generateParentPatternsWithParams( - resource: Resource + resource: Resource, ): [string, PathWithParams[]] { if (resource.patternElems.length > 0) { - const collection = `/${ - resource.patternElems[resource.patternElems.length - 2] - }`; - const params: any[] = []; + const collection = `/${resource.patternElems[resource.patternElems.length - 2]}`; + const params: PathWithParams["params"] = []; for (let i = 0; i < resource.patternElems.length - 2; i += 2) { const pElem = resource.patternElems[i + 1]; params.push({ @@ -350,7 +340,7 @@ export function generateParentPatternsWithParams( params: [baseParam], }); } else { - const [_, parentPWPS] = generateParentPatternsWithParams(parent); + const [, parentPWPS] = generateParentPatternsWithParams(parent); for (const parentPWP of parentPWPS) { const params = [...parentPWP.params, baseParam]; const pattern = `${parentPWP.pattern}${basePattern}`; @@ -366,7 +356,7 @@ function addMethodToPath( paths: Record, path: string, method: string, - methodInfo: any + methodInfo: PathItem[keyof PathItem], ): void { let methods = paths[path]; if (!methods) { @@ -399,7 +389,7 @@ export function parseOpenAPI(openapi: OpenAPI): OpenAPI { export function getPathItem( openapi: OpenAPI, - path: string + path: string, ): PathItem | undefined { return openapi.paths[path]; } @@ -425,7 +415,7 @@ export function getSchema(schema: Schema | undefined): Schema { export function getMethod( openapi: OpenAPI, path: string, - method: string + method: string, ): PathItem[keyof PathItem] | undefined { const pathItem = getPathItem(openapi, path); if (!pathItem) { @@ -437,7 +427,7 @@ export function getMethod( export function getParameters( openapi: OpenAPI, path: string, - method: string + method: string, ): Parameter[] | undefined { const methodItem = getMethod(openapi, path, method); if (!methodItem || !("parameters" in methodItem)) { @@ -447,7 +437,7 @@ export function getParameters( } export function getRequestBody( - methodInfo: PathItem[keyof PathItem] + methodInfo: PathItem[keyof PathItem], ): RequestBody | undefined { if (!methodInfo || !("requestBody" in methodInfo)) { return undefined; @@ -459,7 +449,7 @@ export function getRequestBody( export function getResponses( openapi: OpenAPI, path: string, - method: string + method: string, ): Record | undefined { const methodItem = getMethod(openapi, path, method); if (!methodItem || !("responses" in methodItem)) { diff --git a/src/api/types.ts b/src/api/types.ts index ba539a1..7dbca5d 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -1,8 +1,4 @@ -import type { - Contact, - Schema, - XAEPResourceRef, -} from "../openapi/types.js"; +import type { Contact, Schema, XAEPResourceRef } from "../openapi/types.js"; export interface API { serverURL: string; @@ -27,8 +23,7 @@ export interface Resource { customMethods: CustomMethod[]; } -export interface GetMethod {} - +export type GetMethod = object; export interface ListMethod { hasUnreachableResources: boolean; supportsFilter: boolean; @@ -39,9 +34,8 @@ export interface CreateMethod { supportsUserSettableCreate: boolean; } -export interface UpdateMethod {} - -export interface DeleteMethod {} +export type UpdateMethod = object; +export type DeleteMethod = object; export interface CustomMethod { name: string; diff --git a/src/client/client.test.ts b/src/client/client.test.ts index 3638474..c9048e4 100644 --- a/src/client/client.test.ts +++ b/src/client/client.test.ts @@ -5,7 +5,12 @@ import { Resource } from "../api/types.js"; describe("Client", () => { const baseUrl = "http://localhost:8081"; - const client = new Client(axios.create(), {}, () => {}, () => {}); + const client = new Client( + axios.create(), + {}, + () => {}, + () => {}, + ); beforeEach(() => { nock.cleanAll(); @@ -22,13 +27,13 @@ describe("Client", () => { schema: { type: "object", properties: { - price: { type: "string" } - } + price: { type: "string" }, + }, }, createMethod: { - supportsUserSettableCreate: false + supportsUserSettableCreate: false, }, - customMethods: [] + customMethods: [], }; const body = { @@ -48,7 +53,7 @@ describe("Client", () => { resource, baseUrl, body, - parameters + parameters, ); expect(result.path).toBe("/publishers/my-pub/books/1"); }); @@ -64,13 +69,13 @@ describe("Client", () => { type: "object", properties: { price: { type: "string" }, - id: { type: "string" } - } + id: { type: "string" }, + }, }, createMethod: { - supportsUserSettableCreate: true + supportsUserSettableCreate: true, }, - customMethods: [] + customMethods: [], }; const body = { @@ -91,7 +96,7 @@ describe("Client", () => { resource, baseUrl, body, - parameters + parameters, ); expect(result.path).toBe("/publishers/my-pub/books/my-book"); }); @@ -106,7 +111,7 @@ describe("Client", () => { const result = await client.get( {}, baseUrl, - "/publishers/my-pub/books/1" + "/publishers/my-pub/books/1", ); expect(result.path).toBe("/publishers/my-pub/books/1"); }); @@ -117,7 +122,7 @@ describe("Client", () => { nock(baseUrl).delete("/publishers/my-pub/books/1").reply(200); await expect( - client.delete({}, baseUrl, "/publishers/my-pub/books/1") + client.delete({}, baseUrl, "/publishers/my-pub/books/1"), ).resolves.not.toThrow(); }); }); @@ -134,7 +139,7 @@ describe("Client", () => { .reply(200, { path: "/publishers/my-pub/books/1", price: "2" }); await expect( - client.update({}, baseUrl, "/publishers/my-pub/books/1", body) + client.update({}, baseUrl, "/publishers/my-pub/books/1", body), ).resolves.not.toThrow(); }); }); @@ -150,15 +155,15 @@ describe("Client", () => { schema: { type: "object", properties: { - price: { type: "string" } - } + price: { type: "string" }, + }, }, listMethod: { hasUnreachableResources: false, supportsFilter: false, - supportsSkip: false + supportsSkip: false, }, - customMethods: [] + customMethods: [], }; const parameters = { diff --git a/src/client/client.ts b/src/client/client.ts index 514470c..0650156 100644 --- a/src/client/client.ts +++ b/src/client/client.ts @@ -1,8 +1,16 @@ -import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios"; +import { AxiosInstance, AxiosRequestConfig, isAxiosError } from "axios"; import { Resource } from "../api/types.js"; -type RequestLoggingFunction = (ctx: any, req: any, ...args: any[]) => void; -type ResponseLoggingFunction = (ctx: any, resp: any, ...args: any[]) => void; +type RequestLoggingFunction = ( + ctx: unknown, + req: AxiosRequestConfig, + ...args: unknown[] +) => void; +type ResponseLoggingFunction = ( + ctx: unknown, + resp: unknown, + ...args: unknown[] +) => void; export class Client { private headers: Record; @@ -10,7 +18,12 @@ export class Client { private requestLoggingFunction: RequestLoggingFunction; private responseLoggingFunction: ResponseLoggingFunction; - constructor(client: AxiosInstance, headers: Record, requestLoggingFunction: RequestLoggingFunction, responseLoggingFunction: ResponseLoggingFunction) { + constructor( + client: AxiosInstance, + headers: Record, + requestLoggingFunction: RequestLoggingFunction, + responseLoggingFunction: ResponseLoggingFunction, + ) { this.client = client; this.headers = headers; this.requestLoggingFunction = requestLoggingFunction; @@ -18,12 +31,12 @@ export class Client { } async create( - ctx: any, + ctx: unknown, resource: Resource, serverUrl: string, - body: Record, - parameters: Record - ): Promise> { + body: Record, + parameters: Record, + ): Promise> { let suffix = ""; if (resource.createMethod?.supportsUserSettableCreate) { const id = body.id; @@ -41,11 +54,11 @@ export class Client { } async list( - ctx: any, + ctx: unknown, resource: Resource, serverUrl: string, - parameters: Record - ): Promise[]> { + parameters: Record, + ): Promise[]> { const url = this.basePath(ctx, resource, serverUrl, parameters, ""); const response = await this.makeRequest(ctx, "GET", url); @@ -57,7 +70,9 @@ export class Client { for (const key of possibleKeys) { if (response[key] && Array.isArray(response[key])) { - return response[key].filter((item: any) => typeof item === "object"); + return response[key].filter( + (item: unknown) => typeof item === "object", + ) as Record[]; } } @@ -65,44 +80,44 @@ export class Client { } async get( - ctx: any, + ctx: unknown, serverUrl: string, - path: string - ): Promise> { + path: string, + ): Promise> { const url = `${serverUrl}/${path.replace(/^\//, "")}`; return this.makeRequest(ctx, "GET", url); } async getWithFullUrl( - ctx: any, - url: string - ): Promise> { + ctx: unknown, + url: string, + ): Promise> { return this.makeRequest(ctx, "GET", url); } - async delete(ctx: any, serverUrl: string, path: string): Promise { + async delete(ctx: unknown, serverUrl: string, path: string): Promise { const url = `${serverUrl}/${path.replace(/^\//, "")}`; await this.makeRequest(ctx, "DELETE", url); } async update( - ctx: any, + ctx: unknown, serverUrl: string, path: string, - body: Record - ): Promise> { + body: Record, + ): Promise> { const url = `${serverUrl}/${path.replace(/^\//, "")}`; return this.makeRequest(ctx, "PATCH", url, body); } private async makeRequest( - ctx: any, + ctx: unknown, method: string, url: string, - body?: Record - ): Promise> { + body?: Record, + ): Promise> { if (body) { - Object.keys(body).forEach(key => { + Object.keys(body).forEach((key) => { if (body[key] === null) { delete body[key]; } @@ -124,29 +139,29 @@ export class Client { const data = response.data; this.checkErrors(data); return data; - } catch (error: any) { - if (error.response) { + } catch (error: unknown) { + if (isAxiosError(error) && error.response) { this.responseLoggingFunction(ctx, error.response); throw new Error( - `Request failed: ${JSON.stringify(error.response.data)} for request ${JSON.stringify(config)}` + `Request failed: ${JSON.stringify(error.response.data)} for request ${JSON.stringify(config)}`, ); } throw error; } } - private checkErrors(response: Record): void { + private checkErrors(response: Record): void { if (response.error) { throw new Error(`Returned errors: ${JSON.stringify(response.error)}`); } } private basePath( - ctx: any, + ctx: unknown, resource: Resource, serverUrl: string, parameters: Record, - suffix: string + suffix: string, ): string { serverUrl = serverUrl.replace(/\/$/, ""); const urlElems = [serverUrl]; @@ -160,9 +175,7 @@ export class Client { const value = parameters[paramName]; if (!value) { throw new Error( - `Parameter ${paramName} not found in parameters ${JSON.stringify( - parameters - )}` + `Parameter ${paramName} not found in parameters ${JSON.stringify(parameters)}`, ); } diff --git a/src/index.ts b/src/index.ts index d84ddab..e284ecc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,11 +1,11 @@ // Main exports for the aep-lib-ts package -export * from './cases/cases.js'; -export * from './api/api.js'; -export * from './api/resource.js'; -export * from './openapi/openapi.js'; -export * from './client/client.js'; -export * from './constants/constants.js'; -export { logger } from './utils/logger.js'; +export * from "./cases/cases.js"; +export * from "./api/api.js"; +export * from "./api/resource.js"; +export * from "./openapi/openapi.js"; +export * from "./client/client.js"; +export * from "./constants/constants.js"; +export { logger } from "./utils/logger.js"; // Re-export types with explicit naming to avoid conflicts export type { @@ -18,7 +18,7 @@ export type { UpdateMethod, Resource, PatternInfo, -} from './api/types.js'; +} from "./api/types.js"; export type { Components, @@ -35,5 +35,5 @@ export type { Server, ServerVariable, XAEPResource, - XAEPResourceRef -} from './openapi/types.js'; \ No newline at end of file + XAEPResourceRef, +} from "./openapi/types.js"; diff --git a/src/openapi/openapi.ts b/src/openapi/openapi.ts index c7177e8..b456c80 100644 --- a/src/openapi/openapi.ts +++ b/src/openapi/openapi.ts @@ -74,7 +74,9 @@ export async function fetchOpenAPI(pathOrURL: string): Promise { const body = await readFileOrURL(pathOrURL); return parseYAML(body); } catch (error) { - throw new Error(`Failed to fetch or parse OpenAPI schema from ${pathOrURL}: ${error instanceof Error ? error.message : String(error)}`); + throw new Error( + `Failed to fetch or parse OpenAPI schema from ${pathOrURL}: ${error instanceof Error ? error.message : String(error)}`, + ); } } diff --git a/src/utils/logger.ts b/src/utils/logger.ts index f767b77..7ee7cde 100644 --- a/src/utils/logger.ts +++ b/src/utils/logger.ts @@ -1,9 +1,9 @@ -import { Logger } from 'tslog'; +import { Logger } from "tslog"; export const logger = new Logger({ - name: 'aep-lib-ts', + name: "aep-lib-ts", minLevel: 2, // 0: silly, 1: trace, 2: debug, 3: info, 4: warn, 5: error, 6: fatal - type: 'pretty', + type: "pretty", }); -export default logger; \ No newline at end of file +export default logger; diff --git a/tsconfig.json b/tsconfig.json index 153122d..1c8dc83 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,4 +20,4 @@ }, "include": ["src/**/*"], "exclude": ["node_modules", "dist", "**/*.test.ts"] -} \ No newline at end of file +}