diff --git a/package-lock.json b/package-lock.json index 4835206611..f8fc793b0f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1749,6 +1749,12 @@ "@types/node": "*" } }, + "node_modules/@types/caseless": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", + "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==", + "dev": true + }, "node_modules/@types/chai": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz", @@ -1779,6 +1785,18 @@ "@types/node": "*" } }, + "node_modules/@types/content-type": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@types/content-type/-/content-type-1.1.5.tgz", + "integrity": "sha512-dgMN+syt1xb7Hk8LU6AODOfPlvz5z1CbXpPuJE5ZrX9STfBOIXF09pEB8N7a97WT9dbngt3ksDCm6GW6yMrxfQ==", + "dev": true + }, + "node_modules/@types/cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==", + "dev": true + }, "node_modules/@types/debug": { "version": "4.1.7", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", @@ -1846,6 +1864,18 @@ "@types/range-parser": "*" } }, + "node_modules/@types/find-cache-dir": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/find-cache-dir/-/find-cache-dir-3.2.1.tgz", + "integrity": "sha512-frsJrz2t/CeGifcu/6uRo4b+SzAwT4NYCVPu1GN8IB9XTzrpPkGuV0tmh9mN+/L0PklAlsC3u5Fxt0ju00LXIw==", + "dev": true + }, + "node_modules/@types/flat-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/flat-cache/-/flat-cache-2.0.0.tgz", + "integrity": "sha512-fHeEsm9hvmZ+QHpw6Fkvf19KIhuqnYLU6vtWLjd5BsMd/qVi7iTkMioDZl0mQmfNRA1A6NwvhrSRNr9hGYZGww==", + "dev": true + }, "node_modules/@types/graceful-fs": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", @@ -1917,6 +1947,12 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "node_modules/@types/lodash": { + "version": "4.14.197", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.197.tgz", + "integrity": "sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g==", + "dev": true + }, "node_modules/@types/mdast": { "version": "3.0.10", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", @@ -2043,18 +2079,52 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, + "node_modules/@types/superagent": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.18.tgz", + "integrity": "sha512-LOWgpacIV8GHhrsQU+QMZuomfqXiqzz3ILLkCtKx3Us6AmomFViuzKT9D693QTKgyut2oCytMG8/efOop+DB+w==", + "dev": true, + "dependencies": { + "@types/cookiejar": "*", + "@types/node": "*" + } + }, + "node_modules/@types/supertest": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.12.tgz", + "integrity": "sha512-X3HPWTwXRerBZS7Mo1k6vMVR1Z6zmJcDVn5O/31whe0tnjE4te6ZJSJGq1RiqHPjzPdMTfjCFogDJmwng9xHaQ==", + "dev": true, + "dependencies": { + "@types/superagent": "*" + } + }, "node_modules/@types/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/@types/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-dPWnWsf+kzIG140B8z2w3fr5D03TLWbOAFQl45xUpI3vcizeXriNR5VYkWZ+WTMsUHqZ9Xlt3hrxGNANFyNQfw==", "dev": true }, + "node_modules/@types/type-is": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@types/type-is/-/type-is-1.6.3.tgz", + "integrity": "sha512-PNs5wHaNcBgCQG5nAeeZ7OvosrEsI9O4W2jAOO9BCCg4ux9ZZvH2+0iSCOIDBiKuQsiNS8CBlmfX9f5YBQ22cA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/unist": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==", "dev": true }, + "node_modules/@types/uuid": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.2.tgz", + "integrity": "sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==", + "dev": true + }, "node_modules/@types/yargs": { "version": "17.0.12", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.12.tgz", @@ -15174,7 +15244,7 @@ }, "packages/cloudflare-worker": { "name": "@readme/cloudflare-worker", - "version": "1.2.0", + "version": "1.2.1", "license": "ISC", "dependencies": { "minimatch": "^9.0.1" @@ -15197,7 +15267,7 @@ }, "packages/node": { "name": "readmeio", - "version": "6.1.0", + "version": "6.2.0", "license": "ISC", "dependencies": { "@types/har-format": "^1.2.10", @@ -15214,11 +15284,19 @@ }, "devDependencies": { "@readme/eslint-config": "^10.5.1", + "@types/caseless": "^0.12.2", "@types/chai": "^4.3.4", + "@types/content-type": "^1.1.5", + "@types/find-cache-dir": "^3.2.1", + "@types/flat-cache": "^2.0.0", + "@types/lodash": "^4.14.197", "@types/mocha": "^10.0.1", "@types/multer": "^1.4.7", "@types/node": "^20.2.5", "@types/ssri": "^7.1.1", + "@types/supertest": "^2.0.12", + "@types/type-is": "^1.6.3", + "@types/uuid": "^9.0.2", "caseless": "^0.12.0", "chai": "^4.3.7", "eslint": "^8.34.0", @@ -15261,7 +15339,7 @@ }, "packages/sdk-snippets": { "name": "@readme/metrics-sdk-snippets", - "version": "2.3.4", + "version": "2.4.0", "license": "ISC", "dependencies": { "@readme/httpsnippet": "^6.2.1" @@ -16660,6 +16738,12 @@ "@types/node": "*" } }, + "@types/caseless": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", + "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==", + "dev": true + }, "@types/chai": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz", @@ -16690,6 +16774,18 @@ "@types/node": "*" } }, + "@types/content-type": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@types/content-type/-/content-type-1.1.5.tgz", + "integrity": "sha512-dgMN+syt1xb7Hk8LU6AODOfPlvz5z1CbXpPuJE5ZrX9STfBOIXF09pEB8N7a97WT9dbngt3ksDCm6GW6yMrxfQ==", + "dev": true + }, + "@types/cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==", + "dev": true + }, "@types/debug": { "version": "4.1.7", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", @@ -16757,6 +16853,18 @@ "@types/range-parser": "*" } }, + "@types/find-cache-dir": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/find-cache-dir/-/find-cache-dir-3.2.1.tgz", + "integrity": "sha512-frsJrz2t/CeGifcu/6uRo4b+SzAwT4NYCVPu1GN8IB9XTzrpPkGuV0tmh9mN+/L0PklAlsC3u5Fxt0ju00LXIw==", + "dev": true + }, + "@types/flat-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/flat-cache/-/flat-cache-2.0.0.tgz", + "integrity": "sha512-fHeEsm9hvmZ+QHpw6Fkvf19KIhuqnYLU6vtWLjd5BsMd/qVi7iTkMioDZl0mQmfNRA1A6NwvhrSRNr9hGYZGww==", + "dev": true + }, "@types/graceful-fs": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", @@ -16828,6 +16936,12 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "@types/lodash": { + "version": "4.14.197", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.197.tgz", + "integrity": "sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g==", + "dev": true + }, "@types/mdast": { "version": "3.0.10", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", @@ -16954,18 +17068,52 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, + "@types/superagent": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.18.tgz", + "integrity": "sha512-LOWgpacIV8GHhrsQU+QMZuomfqXiqzz3ILLkCtKx3Us6AmomFViuzKT9D693QTKgyut2oCytMG8/efOop+DB+w==", + "dev": true, + "requires": { + "@types/cookiejar": "*", + "@types/node": "*" + } + }, + "@types/supertest": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.12.tgz", + "integrity": "sha512-X3HPWTwXRerBZS7Mo1k6vMVR1Z6zmJcDVn5O/31whe0tnjE4te6ZJSJGq1RiqHPjzPdMTfjCFogDJmwng9xHaQ==", + "dev": true, + "requires": { + "@types/superagent": "*" + } + }, "@types/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/@types/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-dPWnWsf+kzIG140B8z2w3fr5D03TLWbOAFQl45xUpI3vcizeXriNR5VYkWZ+WTMsUHqZ9Xlt3hrxGNANFyNQfw==", "dev": true }, + "@types/type-is": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@types/type-is/-/type-is-1.6.3.tgz", + "integrity": "sha512-PNs5wHaNcBgCQG5nAeeZ7OvosrEsI9O4W2jAOO9BCCg4ux9ZZvH2+0iSCOIDBiKuQsiNS8CBlmfX9f5YBQ22cA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/unist": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==", "dev": true }, + "@types/uuid": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.2.tgz", + "integrity": "sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==", + "dev": true + }, "@types/yargs": { "version": "17.0.12", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.12.tgz", @@ -24294,13 +24442,21 @@ "version": "file:packages/node", "requires": { "@readme/eslint-config": "^10.5.1", + "@types/caseless": "^0.12.2", "@types/chai": "^4.3.4", + "@types/content-type": "^1.1.5", + "@types/find-cache-dir": "^3.2.1", + "@types/flat-cache": "^2.0.0", "@types/har-format": "^1.2.10", + "@types/lodash": "^4.14.197", "@types/mocha": "^10.0.1", "@types/multer": "^1.4.7", "@types/node": "^20.2.5", "@types/node-fetch": "^2.6.2", "@types/ssri": "^7.1.1", + "@types/supertest": "^2.0.12", + "@types/type-is": "^1.6.3", + "@types/uuid": "^9.0.2", "caseless": "^0.12.0", "chai": "^4.3.7", "content-type": "^1.0.5", diff --git a/packages/node/package-lock.json b/packages/node/package-lock.json index 0be45fd99a..05cbe9bfac 100644 --- a/packages/node/package-lock.json +++ b/packages/node/package-lock.json @@ -6,7 +6,7 @@ "packages": { "": { "name": "readmeio", - "version": "6.1.0", + "version": "6.2.0", "license": "ISC", "dependencies": { "@types/har-format": "^1.2.10", @@ -23,11 +23,19 @@ }, "devDependencies": { "@readme/eslint-config": "^10.5.1", + "@types/caseless": "^0.12.2", "@types/chai": "^4.3.4", + "@types/content-type": "^1.1.5", + "@types/find-cache-dir": "^3.2.1", + "@types/flat-cache": "^2.0.0", + "@types/lodash": "^4.14.197", "@types/mocha": "^10.0.1", "@types/multer": "^1.4.7", "@types/node": "^20.2.5", "@types/ssri": "^7.1.1", + "@types/supertest": "^2.0.12", + "@types/type-is": "^1.6.3", + "@types/uuid": "^9.0.2", "caseless": "^0.12.0", "chai": "^4.3.7", "eslint": "^8.34.0", @@ -901,6 +909,12 @@ "@types/node": "*" } }, + "node_modules/@types/caseless": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", + "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==", + "dev": true + }, "node_modules/@types/chai": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz", @@ -916,6 +930,18 @@ "@types/node": "*" } }, + "node_modules/@types/content-type": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@types/content-type/-/content-type-1.1.5.tgz", + "integrity": "sha512-dgMN+syt1xb7Hk8LU6AODOfPlvz5z1CbXpPuJE5ZrX9STfBOIXF09pEB8N7a97WT9dbngt3ksDCm6GW6yMrxfQ==", + "dev": true + }, + "node_modules/@types/cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==", + "dev": true + }, "node_modules/@types/express": { "version": "4.17.13", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", @@ -939,6 +965,18 @@ "@types/range-parser": "*" } }, + "node_modules/@types/find-cache-dir": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/find-cache-dir/-/find-cache-dir-3.2.1.tgz", + "integrity": "sha512-frsJrz2t/CeGifcu/6uRo4b+SzAwT4NYCVPu1GN8IB9XTzrpPkGuV0tmh9mN+/L0PklAlsC3u5Fxt0ju00LXIw==", + "dev": true + }, + "node_modules/@types/flat-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/flat-cache/-/flat-cache-2.0.0.tgz", + "integrity": "sha512-fHeEsm9hvmZ+QHpw6Fkvf19KIhuqnYLU6vtWLjd5BsMd/qVi7iTkMioDZl0mQmfNRA1A6NwvhrSRNr9hGYZGww==", + "dev": true + }, "node_modules/@types/har-format": { "version": "1.2.11", "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.11.tgz", @@ -956,6 +994,12 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/lodash": { + "version": "4.14.197", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.197.tgz", + "integrity": "sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g==", + "dev": true + }, "node_modules/@types/mime": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", @@ -1047,6 +1091,40 @@ "@types/node": "*" } }, + "node_modules/@types/superagent": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.18.tgz", + "integrity": "sha512-LOWgpacIV8GHhrsQU+QMZuomfqXiqzz3ILLkCtKx3Us6AmomFViuzKT9D693QTKgyut2oCytMG8/efOop+DB+w==", + "dev": true, + "dependencies": { + "@types/cookiejar": "*", + "@types/node": "*" + } + }, + "node_modules/@types/supertest": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.12.tgz", + "integrity": "sha512-X3HPWTwXRerBZS7Mo1k6vMVR1Z6zmJcDVn5O/31whe0tnjE4te6ZJSJGq1RiqHPjzPdMTfjCFogDJmwng9xHaQ==", + "dev": true, + "dependencies": { + "@types/superagent": "*" + } + }, + "node_modules/@types/type-is": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@types/type-is/-/type-is-1.6.3.tgz", + "integrity": "sha512-PNs5wHaNcBgCQG5nAeeZ7OvosrEsI9O4W2jAOO9BCCg4ux9ZZvH2+0iSCOIDBiKuQsiNS8CBlmfX9f5YBQ22cA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/uuid": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.2.tgz", + "integrity": "sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==", + "dev": true + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.60.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.60.1.tgz", @@ -8682,6 +8760,12 @@ "@types/node": "*" } }, + "@types/caseless": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", + "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==", + "dev": true + }, "@types/chai": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz", @@ -8697,6 +8781,18 @@ "@types/node": "*" } }, + "@types/content-type": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@types/content-type/-/content-type-1.1.5.tgz", + "integrity": "sha512-dgMN+syt1xb7Hk8LU6AODOfPlvz5z1CbXpPuJE5ZrX9STfBOIXF09pEB8N7a97WT9dbngt3ksDCm6GW6yMrxfQ==", + "dev": true + }, + "@types/cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==", + "dev": true + }, "@types/express": { "version": "4.17.13", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", @@ -8720,6 +8816,18 @@ "@types/range-parser": "*" } }, + "@types/find-cache-dir": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/find-cache-dir/-/find-cache-dir-3.2.1.tgz", + "integrity": "sha512-frsJrz2t/CeGifcu/6uRo4b+SzAwT4NYCVPu1GN8IB9XTzrpPkGuV0tmh9mN+/L0PklAlsC3u5Fxt0ju00LXIw==", + "dev": true + }, + "@types/flat-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/flat-cache/-/flat-cache-2.0.0.tgz", + "integrity": "sha512-fHeEsm9hvmZ+QHpw6Fkvf19KIhuqnYLU6vtWLjd5BsMd/qVi7iTkMioDZl0mQmfNRA1A6NwvhrSRNr9hGYZGww==", + "dev": true + }, "@types/har-format": { "version": "1.2.11", "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.11.tgz", @@ -8737,6 +8845,12 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "@types/lodash": { + "version": "4.14.197", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.197.tgz", + "integrity": "sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g==", + "dev": true + }, "@types/mime": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", @@ -8827,6 +8941,40 @@ "@types/node": "*" } }, + "@types/superagent": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.18.tgz", + "integrity": "sha512-LOWgpacIV8GHhrsQU+QMZuomfqXiqzz3ILLkCtKx3Us6AmomFViuzKT9D693QTKgyut2oCytMG8/efOop+DB+w==", + "dev": true, + "requires": { + "@types/cookiejar": "*", + "@types/node": "*" + } + }, + "@types/supertest": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.12.tgz", + "integrity": "sha512-X3HPWTwXRerBZS7Mo1k6vMVR1Z6zmJcDVn5O/31whe0tnjE4te6ZJSJGq1RiqHPjzPdMTfjCFogDJmwng9xHaQ==", + "dev": true, + "requires": { + "@types/superagent": "*" + } + }, + "@types/type-is": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@types/type-is/-/type-is-1.6.3.tgz", + "integrity": "sha512-PNs5wHaNcBgCQG5nAeeZ7OvosrEsI9O4W2jAOO9BCCg4ux9ZZvH2+0iSCOIDBiKuQsiNS8CBlmfX9f5YBQ22cA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/uuid": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.2.tgz", + "integrity": "sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==", + "dev": true + }, "@typescript-eslint/eslint-plugin": { "version": "5.60.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.60.1.tgz", diff --git a/packages/node/package.json b/packages/node/package.json index 157b10abfa..fe079708a9 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -39,11 +39,19 @@ }, "devDependencies": { "@readme/eslint-config": "^10.5.1", + "@types/caseless": "^0.12.2", "@types/chai": "^4.3.4", + "@types/content-type": "^1.1.5", + "@types/find-cache-dir": "^3.2.1", + "@types/flat-cache": "^2.0.0", + "@types/lodash": "^4.14.197", "@types/mocha": "^10.0.1", "@types/multer": "^1.4.7", "@types/node": "^20.2.5", "@types/ssri": "^7.1.1", + "@types/supertest": "^2.0.12", + "@types/type-is": "^1.6.3", + "@types/uuid": "^9.0.2", "caseless": "^0.12.0", "chai": "^4.3.7", "eslint": "^8.34.0", diff --git a/packages/node/src/lib/construct-payload.ts b/packages/node/src/lib/construct-payload.ts index 266fd55198..df916ac4ce 100644 --- a/packages/node/src/lib/construct-payload.ts +++ b/packages/node/src/lib/construct-payload.ts @@ -1,4 +1,5 @@ import type { OutgoingLogBody } from './metrics-log'; +import type { UUID } from 'node:crypto'; import type { IncomingMessage, ServerResponse } from 'node:http'; import type { TLSSocket } from 'tls'; @@ -83,7 +84,7 @@ export interface PayloadData { * * @example {base_url}/logs/{logId} */ - logId?: string; + logId?: UUID; /** * Object or string | The incoming request body. You should provide this function a parsed object, @@ -123,7 +124,7 @@ export interface PayloadData { * * With the last 4 digits on the end for us to use to identify it later in a list. */ -export function mask(apiKey) { +export function mask(apiKey: string) { return ssri .fromData(apiKey, { algorithms: ['sha512'], @@ -141,14 +142,14 @@ export function constructPayload( const serverTime = payloadData.responseEndDateTime.getTime() - payloadData.startedDateTime.getTime(); return { - _id: payloadData.logId || uuidv4(), + _id: payloadData.logId || (uuidv4() as UUID), _version: 3, group: { id: mask(payloadData.apiKey), label: payloadData.label, email: payloadData.email, }, - clientIPAddress: req.socket.remoteAddress, + clientIPAddress: req.socket.remoteAddress || '', development: !!logOptions?.development, request: { log: { @@ -163,7 +164,7 @@ export function constructPayload( { pageref: payloadData.routePath ? payloadData.routePath - : new URL(req.url, `${getProto(req)}://${req.headers.host}`).toString(), + : new URL(req.url || '', `${getProto(req)}://${req.headers.host}`).toString(), startedDateTime: payloadData.startedDateTime.toISOString(), time: serverTime, request: processRequest(req, payloadData.requestBody, logOptions), diff --git a/packages/node/src/lib/get-project-base-url.ts b/packages/node/src/lib/get-project-base-url.ts index a80413a8f3..a2194e3474 100644 --- a/packages/node/src/lib/get-project-base-url.ts +++ b/packages/node/src/lib/get-project-base-url.ts @@ -8,7 +8,7 @@ import timeoutSignal from 'timeout-signal'; import pkg from '../../package.json'; import config from '../config'; -export function getCache(readmeApiKey) { +export function getCache(readmeApiKey: string) { const encodedApiKey = Buffer.from(`${readmeApiKey}:`).toString('base64'); const cacheDir = findCacheDir({ name: pkg.name, create: true }); const fsSafeApikey = crypto.createHash('md5').update(encodedApiKey).digest('hex'); @@ -34,7 +34,7 @@ export async function getProjectBaseUrl(readmeApiKey: string, requestTimeout = c ) { const signal = timeoutSignal(requestTimeout); - let baseUrl; + let baseUrl = ''; await fetch(`${config.readmeApiUrl}/v1/`, { method: 'get', headers: { diff --git a/packages/node/src/lib/log.ts b/packages/node/src/lib/log.ts index c8aad77226..b33abfab9a 100644 --- a/packages/node/src/lib/log.ts +++ b/packages/node/src/lib/log.ts @@ -1,5 +1,6 @@ import type { LogOptions } from './construct-payload'; import type { GroupingObject, OutgoingLogBody } from './metrics-log'; +import type { UUID } from 'node:crypto'; import type { IncomingMessage, ServerResponse } from 'node:http'; import * as url from 'url'; @@ -17,7 +18,7 @@ import { patchRequest } from './patch-request'; import { patchResponse } from './patch-response'; let queue: OutgoingLogBody[] = []; -function doSend(readmeApiKey, options) { +function doSend(readmeApiKey: string, options: Options) { // Copy the queue so we can send all the requests in one batch const json = [...queue]; // Clear out the queue so we don't resend any data in the future @@ -58,7 +59,7 @@ export interface ExtendedIncomingMessage extends IncomingMessage { } /* eslint-enable typescript-sort-keys/interface */ -interface ExtendedResponse extends ServerResponse { +export interface ExtendedResponse extends ServerResponse { _body?: string; } @@ -67,7 +68,7 @@ export interface Options extends LogOptions { bufferLength?: number; } -function setDocumentationHeader(res, baseLogUrl, logId) { +function setDocumentationHeader(res: ServerResponse, baseLogUrl: string, logId: string) { // This is to catch the potential race condition where `getProjectBaseUrl()` // takes longer to respond than the original req/res to finish. Without this // we would get an error that would be very difficult to trace. This could @@ -105,7 +106,7 @@ export function log( const bufferLength = clamp(options.bufferLength || config.bufferLength, 1, 30); const startedDateTime = new Date(); - const logId = uuidv4(); + const logId = uuidv4() as UUID; // baseLogUrl can be provided, but if it isn't then we // attempt to fetch it from the ReadMe API diff --git a/packages/node/src/lib/metrics-log.ts b/packages/node/src/lib/metrics-log.ts index 33bb1ee104..e1ae0b5bac 100644 --- a/packages/node/src/lib/metrics-log.ts +++ b/packages/node/src/lib/metrics-log.ts @@ -1,3 +1,4 @@ +import type { UUID } from 'crypto'; import type { Har } from 'har-format'; import type { Response } from 'node-fetch'; @@ -32,7 +33,7 @@ export interface GroupingObject { } export interface OutgoingLogBody { - _id?: string; + _id?: UUID; _version: number; clientIPAddress: string; development: boolean; @@ -41,14 +42,16 @@ export interface OutgoingLogBody { request: Har; } +type LogId = UUID | UUID[] | undefined; + export interface LogResponse { - ids: string | string[]; + ids: LogId; response?: Response; } const BACKOFF_SECONDS = 15; // when we need to backoff HTTP requests, pause for seconds -let backoffExpiresAt: Date; +let backoffExpiresAt: Date | undefined; // Exported for use in unit tests export function setBackoff(expiresAt: Date | undefined) { @@ -77,9 +80,9 @@ function shouldBackoff(response: Response) { } } -function getLogIds(body: OutgoingLogBody | OutgoingLogBody[]): string | string[] { +function getLogIds(body: OutgoingLogBody | OutgoingLogBody[]): LogId { if (Array.isArray(body)) { - return body.map(value => value._id); + return body.map(value => value._id) as UUID[]; } return body._id; @@ -96,7 +99,7 @@ export function metricsAPICall( const makeRequest = () => { if (backoffExpiresAt) { if (backoffExpiresAt > new Date()) { - return Promise.resolve(); + return Promise.resolve(undefined); } // after the backoff expires, erase the old expiration time backoffExpiresAt = undefined; @@ -130,7 +133,7 @@ export function metricsAPICall( if (fireAndForget) { makeRequest(); - return Promise.resolve({ + return Promise.resolve({ ids: getLogIds(body), }); } diff --git a/packages/node/src/lib/object-to-array.ts b/packages/node/src/lib/object-to-array.ts index 41121d36fb..be0c2020a0 100644 --- a/packages/node/src/lib/object-to-array.ts +++ b/packages/node/src/lib/object-to-array.ts @@ -1,5 +1,15 @@ import type { URLSearchParams } from 'url'; +type ParamArray = { + name: string; + value: unknown; +}[]; + +export function objectToArray( + object: Record, + opts: { castToString: true } +): { name: string; value: string }[]; +export function objectToArray(object: Record): ParamArray; export function objectToArray( object: Record, opts: { @@ -7,8 +17,8 @@ export function objectToArray( } = { castToString: false, } -): { name: string; value: string }[] { - return Object.entries(object).reduce((prev, [name, value]) => { +): ParamArray { + return Object.entries(object).reduce((prev, [name, value]) => { if (Array.isArray(value)) { value.forEach(val => { prev.push({ name, value: opts.castToString ? String(val) : val }); @@ -22,7 +32,7 @@ export function objectToArray( } export function searchToArray(search: URLSearchParams): { name: string; value: string }[] { - const final = []; + const final: { name: string; value: string }[] = []; search.forEach((value, name) => { final.push({ name, value }); diff --git a/packages/node/src/lib/patch-response.ts b/packages/node/src/lib/patch-response.ts index 5e4470bfe0..8f8c2984fe 100644 --- a/packages/node/src/lib/patch-response.ts +++ b/packages/node/src/lib/patch-response.ts @@ -2,17 +2,25 @@ // so we can send it off to the metrics server // It's unfortunate that this isn't accessible // natively. This may take up lots of memory on +import type { ExtendedResponse } from './log'; + // big responses, we can make it configurable in future -export function patchResponse(res) { +export function patchResponse(res: ExtendedResponse) { const { write, end } = res; res._body = ''; + // @ts-expect-error these lines are messing with Node internals and + // I'm not sure what exactly typing fix is needed here that doesn't have + // some sort of adverse impact on our response handling. res.write = (chunk, encoding, cb) => { res._body += chunk; write.call(res, chunk, encoding, cb); }; + // @ts-expect-error these lines are messing with Node internals and + // I'm not sure what exactly typing fix is needed here that doesn't have + // some sort of adverse impact on our response handling. res.end = (chunk, encoding, cb) => { // Chunk is optional in res.end // http://nodejs.org/dist/latest/docs/api/http.html#http_response_end_data_encoding_callback diff --git a/packages/node/src/lib/process-request.ts b/packages/node/src/lib/process-request.ts index 94816f4928..e23b45d201 100644 --- a/packages/node/src/lib/process-request.ts +++ b/packages/node/src/lib/process-request.ts @@ -1,6 +1,6 @@ import type { LogOptions } from './construct-payload'; import type { ExtendedIncomingMessage } from './log'; -import type { Entry } from 'har-format'; +import type { Cookie, Param, PostData, Request } from 'har-format'; import * as qs from 'querystring'; import url, { URL } from 'url'; @@ -38,7 +38,7 @@ export function fixHeader(header: string | number | string[]): string | undefine * @param value the value to be redacted * @returns A redacted string potentially containing the length of the original value, if it was a string */ -function redactValue(value: string) { +function redactValue(value: unknown) { const redactedVal = typeof value === 'string' ? ` ${value.length}` : ''; return `[REDACTED${redactedVal}]`; } @@ -50,7 +50,7 @@ function redactValue(value: string) { * @param redactedPaths a list of paths that point values which should be redacted * @returns An object with the redacted values */ -function redactProperties>(obj: T, redactedPaths = []): T { +function redactProperties>(obj: T, redactedPaths: string[] = []): T { const nextObj = { ...obj }; return redactedPaths.reduce((acc, path) => { const value = get(acc, path); @@ -64,11 +64,14 @@ function redactProperties>(obj: T, redactedPat * @param cb A callback that is invoked for each value found, the return value being the next value that is set in the returned object * @returns An object with the replaced values */ -function replaceEach(obj, cb): Record { - return Object.keys(obj).reduce((acc, key) => { +function replaceEach>( + obj: T, + cb: (input: unknown) => string +): Record { + return Object.keys(obj).reduce>((acc, key) => { const value = obj[key]; if (typeof value === 'object' && value !== null) { - acc[key] = replaceEach(value, cb); + acc[key] = replaceEach(value as Record, cb); } else if (value !== undefined) { acc[key] = cb(value); } @@ -83,13 +86,13 @@ function replaceEach(obj, cb): Record { * @param nonRedactedPaths A list of all object paths that shouldn't be redacted * @returns A merged objects that is entirely redacted except for the values of the nonRedactedPaths */ -function redactOtherProperties>(obj: T, nonRedactedPaths): T { +function redactOtherProperties>(obj: T, nonRedactedPaths: string[]): T { const allowedFields = pick(obj, nonRedactedPaths); const redactedFields = obj ? replaceEach(obj, redactValue) : obj; - return merge(redactedFields, allowedFields); + return merge(redactedFields, allowedFields) as T; } -function isApplicationJson(mimeType) { +function isApplicationJson(mimeType: string) { if (!mimeType) { return false; } @@ -129,20 +132,20 @@ export default function processRequest( req: ExtendedIncomingMessage, requestBody?: Record | string, options?: LogOptions -): Entry['request'] { - const protocol = fixHeader(req.headers['x-forwarded-proto'])?.toLowerCase() || getProto(req); - const host = fixHeader(req.headers['x-forwarded-host']) || req.headers.host; +): Request { + const protocol = fixHeader(req.headers['x-forwarded-proto'] || '')?.toLowerCase() || getProto(req); + const host = fixHeader(req.headers['x-forwarded-host'] || '') || req.headers.host; const denylist = options?.denylist || options?.blacklist; const allowlist = options?.allowlist || options?.whitelist; - let mimeType: string = null; + let mimeType = ''; try { - mimeType = contentType.parse(req.headers['content-type']).type; + mimeType = contentType.parse(req.headers['content-type'] || '').type; } catch (e) {} // eslint-disable-line no-empty let reqBody = typeof requestBody === 'string' ? parseRequestBody(requestBody, mimeType) : requestBody; - let postData: Entry['request']['postData'] = null; + let postData: PostData | undefined; if (denylist) { reqBody = typeof reqBody === 'object' ? redactProperties(reqBody, denylist) : reqBody; @@ -158,12 +161,12 @@ export default function processRequest( postData = { mimeType, // `reqBody` is likely to be an object, but can be empty if no HTTP body sent - params: objectToArray((reqBody || {}) as Record), + params: objectToArray((reqBody || {}) as Record) as Param[], }; } else if (isApplicationJson(mimeType)) { postData = { mimeType, - text: typeof reqBody === 'object' || Array.isArray(reqBody) ? JSON.stringify(reqBody) : reqBody, + text: typeof reqBody === 'object' || Array.isArray(reqBody) ? JSON.stringify(reqBody) : reqBody || '', }; } else if (mimeType) { let stringBody = ''; @@ -184,14 +187,14 @@ export default function processRequest( // We use a fake host here because we rely on the host header which could be redacted. // We only ever use this reqUrl with the fake hostname for the pathname and querystring. // req.originalUrl is express specific, req.url is node.js - const reqUrl = new URL(req.originalUrl || req.url, 'https://readme.io'); + const reqUrl = new URL(req.originalUrl || req.url || '', 'https://readme.io'); if (req.headers.authorization) { req.headers.authorization = mask(req.headers.authorization); } - const requestData = { - method: req.method, + const requestData: Request = { + method: req.method || '', url: url.format({ // Handle cases where some reverse proxies put two protocols into x-forwarded-proto // This line does the following: "https,http" -> "https" @@ -203,17 +206,19 @@ export default function processRequest( query: qs.parse(reqUrl.search.substring(1)), }), httpVersion: `${getProto(req).toUpperCase()}/${req.httpVersion}`, - headers: objectToArray(req.headers), + headers: objectToArray(req.headers, { castToString: true }), queryString: searchToArray(reqUrl.searchParams), postData, // TODO: When readme starts accepting these, send the correct values - cookies: [], + cookies: [] as Cookie[], headersSize: -1, bodySize: -1, - }; + } as const; - if (requestData.postData === null) { - delete requestData.postData; + if (typeof requestData.postData === 'undefined') { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { postData: postDataToBeOmitted, ...remainingRequestData } = requestData; + return remainingRequestData; } return requestData; diff --git a/packages/node/src/lib/process-response.ts b/packages/node/src/lib/process-response.ts index 797a5c27e4..5a70bf8c58 100644 --- a/packages/node/src/lib/process-response.ts +++ b/packages/node/src/lib/process-response.ts @@ -1,5 +1,5 @@ import type { LogOptions } from './construct-payload'; -import type { Entry } from 'har-format'; +import type { Response } from 'har-format'; import type { ServerResponse } from 'http'; import { STATUS_CODES } from 'http'; @@ -19,16 +19,12 @@ import { fixHeader } from './process-request'; * * @returns The HAR formatted response details */ -export default function processResponse( - res: ServerResponse, - responseBody?: string, - options?: LogOptions -): Entry['response'] { +export default function processResponse(res: ServerResponse, responseBody?: string, options?: LogOptions): Response { const denylist = options?.denylist || options?.blacklist; const allowlist = options?.allowlist || options?.whitelist; let body; try { - body = JSON.parse(responseBody); + body = JSON.parse(responseBody || ''); // Only apply blacklist/whitelist if it's an object if (denylist) { @@ -62,12 +58,12 @@ export default function processResponse( // // This is the same thing that Node.js does internally: // https://github.com/nodejs/node/blob/9b8ba2536044ae08a1cd747a3aa52df7d1815e7e/lib/_http_server.js#L318 - statusText: res.statusMessage || STATUS_CODES[res.statusCode], + statusText: res.statusMessage || STATUS_CODES[res.statusCode] || '', headers: objectToArray(headers, { castToString: true }), content: { text: JSON.stringify(body), size: Number(fixHeader(res.getHeader('content-length') || 0)), - mimeType: fixHeader(res.getHeader('content-type')) || 'text/plain', + mimeType: fixHeader(res.getHeader('content-type') || '') || 'text/plain', }, // TODO: Once readme starts accepting these, send the correct values httpVersion: '', diff --git a/packages/node/test/helpers/chai-plugins.ts b/packages/node/test/helpers/chai-plugins.ts index e409fa3b31..adc0678c82 100644 --- a/packages/node/test/helpers/chai-plugins.ts +++ b/packages/node/test/helpers/chai-plugins.ts @@ -40,13 +40,13 @@ declare global { * connection: 'close' * } */ -function arrayToObject(array) { +function arrayToObject(array: { name: string; value: string }[]) { return array.reduce((prev, next) => { return Object.assign(prev, { [next.name]: next.value }); }, {}); } -export default function chaiPlugins(_chai, utils) { +export default function chaiPlugins(_chai: Chai.ChaiStatic, utils: Chai.ChaiUtils) { /** * Assert that a request has our `x-documentation-url` header and that contains a valid v4 UUID. * @@ -55,7 +55,7 @@ export default function chaiPlugins(_chai, utils) { * * @param {string} baseLogUrl */ - utils.addMethod(chai.Assertion.prototype, 'documentationHeader', function (baseLogUrl) { + utils.addMethod(chai.Assertion.prototype, 'documentationHeader', function (baseLogUrl: string) { const headers = utils.flag(this, 'object'); // eslint-disable-next-line chai-friendly/no-unused-expressions @@ -82,11 +82,11 @@ export default function chaiPlugins(_chai, utils) { * @param {string} header * @param {string|RegExp} expected */ - utils.addMethod(chai.Assertion.prototype, 'header', function (header, expected) { + utils.addMethod(chai.Assertion.prototype, 'header', function (header: string, expected: RegExp | string[] | string) { const obj = utils.flag(this, 'object'); const headers = caseless(arrayToObject(obj)); - if (expected.constructor.name === 'RegExp') { + if (expected instanceof RegExp) { new chai.Assertion(headers.get(header)).to.match(expected); } else if (Array.isArray(expected)) { new chai.Assertion(headers.get(header)).to.oneOf(expected.map(e => e.toString())); diff --git a/packages/node/test/index.test.ts b/packages/node/test/index.test.ts index 3569c8acd1..b4d62b1e5a 100644 --- a/packages/node/test/index.test.ts +++ b/packages/node/test/index.test.ts @@ -1,3 +1,5 @@ +import type { Express } from 'express'; + import * as crypto from 'crypto'; import { createServer } from 'http'; @@ -53,8 +55,7 @@ describe('#metrics', function () { it('should throw an error if `apiKey` is missing', function () { const app = express(); app.use((req, res, next) => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore + // @ts-expect-error deliberately passing in bad data readmeio.log('', req, res, {}); return next(); }); @@ -74,8 +75,7 @@ describe('#metrics', function () { it('should throw an error if `group` is missing', function () { const app = express(); app.use((req, res, next) => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore + // @ts-expect-error deliberately passing in bad data readmeio.log(apiKey, req, res); return next(); }); @@ -93,9 +93,9 @@ describe('#metrics', function () { }); describe('tests for sending requests to the metrics server', function () { - let mock; - let metricsServerRequests; - let app; + let mock: nock.Scope; + let metricsServerRequests: number; + let app: Express; let metricsServerResponseCode = 202; beforeEach(function () { @@ -296,7 +296,7 @@ describe('#metrics', function () { app.get('/test', (req, res) => res.sendStatus(200)); // We need to make sure that the logId isn't being preserved between buffered requests. - let logUrl; + let logUrl: string; await request(app) .get('/test') @@ -340,7 +340,7 @@ describe('#metrics', function () { const numberOfMocks = 4; const bufferLength = numberOfLogs / numberOfMocks; - const seenLogs = []; + const seenLogs: string[] = []; const mocks = [...new Array(numberOfMocks).keys()].map(() => nock(config.host, { @@ -353,7 +353,7 @@ describe('#metrics', function () { expect(body).to.have.lengthOf(bufferLength); // Ensure that our executed requests and the buffered queue they're in remain unique. - body.forEach(req => { + body.forEach((req: unknown) => { const requestHash = crypto.createHash('md5').update(JSON.stringify(req)).digest('hex'); expect(seenLogs).not.to.contain(requestHash); seenLogs.push(requestHash); diff --git a/packages/node/test/lib/get-project-base-url.test.ts b/packages/node/test/lib/get-project-base-url.test.ts index 86a6df3a83..13c134504b 100644 --- a/packages/node/test/lib/get-project-base-url.test.ts +++ b/packages/node/test/lib/get-project-base-url.test.ts @@ -10,7 +10,7 @@ const apiKey = 'mockReadMeApiKey'; const baseLogUrl = 'https://docs.example.com'; // eslint-disable-next-line mocha/no-exports -export function getReadMeApiMock(numberOfTimes, baseUrl = baseLogUrl) { +export function getReadMeApiMock(numberOfTimes: number, baseUrl = baseLogUrl) { return nock(config.readmeApiUrl, { reqheaders: { 'User-Agent': `${pkg.name}/${pkg.version}`, @@ -22,7 +22,7 @@ export function getReadMeApiMock(numberOfTimes, baseUrl = baseLogUrl) { .reply(200, { baseUrl }); } -function hydrateCache(lastUpdated) { +function hydrateCache(lastUpdated: number) { const cache = getCache(apiKey); cache.setKey('lastUpdated', lastUpdated); diff --git a/packages/node/test/lib/is-request.test.ts b/packages/node/test/lib/is-request.test.ts index f3c143a31d..ca32a316da 100644 --- a/packages/node/test/lib/is-request.test.ts +++ b/packages/node/test/lib/is-request.test.ts @@ -1,4 +1,5 @@ import { expect } from 'chai'; +// @ts-expect-error I am for some reason unable to declare a module properly for this package import MockReq from 'mock-req'; import isRequest from '../../src/lib/is-request'; diff --git a/packages/node/test/lib/process-request.test.ts b/packages/node/test/lib/process-request.test.ts index 699ecad2d5..a3888c8c6d 100644 --- a/packages/node/test/lib/process-request.test.ts +++ b/packages/node/test/lib/process-request.test.ts @@ -12,7 +12,7 @@ import chaiPlugins from '../helpers/chai-plugins'; chai.use(chaiPlugins); -function createApp(reqOptions?: LogOptions, shouldPreParse = false, bodyOverride?) { +function createApp(reqOptions?: LogOptions, shouldPreParse = false, bodyOverride?: Record) { const requestListener = function (req: IncomingMessage, res: ServerResponse) { let body = ''; @@ -120,7 +120,7 @@ describe('process-request', function () { }); it('should fail gracefully with circular json objects', function () { - const obj = { foo: null }; + const obj: Record = { foo: null }; obj.foo = obj; const app = createApp({ denylist: ['password'] }, false, obj); @@ -478,8 +478,8 @@ describe('process-request', function () { .post('/') .set('a', '1') .expect(({ body }) => { - expect(body.headers.find(header => header.name === 'host').value).to.match(/127.0.0.1:\d+/); - expect(body.headers.filter(header => header.name !== 'host')).to.deep.equal([ + expect(body.headers.find((header: { name: string }) => header.name === 'host').value).to.match(/127.0.0.1:\d+/); + expect(body.headers.filter((header: { name: string }) => header.name !== 'host')).to.deep.equal([ { name: 'accept-encoding', value: 'gzip, deflate' }, { name: 'a', value: '1' }, { name: 'connection', value: 'close' }, diff --git a/packages/node/test/lib/verify-webhook.test.ts b/packages/node/test/lib/verify-webhook.test.ts index d0d8110470..916d67846c 100644 --- a/packages/node/test/lib/verify-webhook.test.ts +++ b/packages/node/test/lib/verify-webhook.test.ts @@ -47,10 +47,19 @@ describe('verifyWebhook', function () { it('should throw an error if signature is missing', function () { const body = { email: 'marc@readme.io' }; const secret = 'docs4dayz'; - const signature = undefined; + const signature = ''; expect(() => { verifyWebhook(body, signature, secret); }).to.throw(/Missing Signature/); }); + + it('should throw an error if signature is undefined', function () { + const body = { email: 'marc@readme.io' }; + const secret = 'docs4dayz'; + + expect(() => { + verifyWebhook(body, undefined, secret); + }).to.throw(/Missing Signature/); + }); }); diff --git a/packages/node/test/tsconfig.json b/packages/node/test/tsconfig.json index e1c447e2de..0ddcba12f6 100644 --- a/packages/node/test/tsconfig.json +++ b/packages/node/test/tsconfig.json @@ -1,7 +1,9 @@ { "extends": "../tsconfig.json", "compilerOptions": { - "downlevelIteration": true + "downlevelIteration": true, + "noImplicitAny": true, + "strict": false }, "include": ["./index.test.ts", "./lib/*.ts"] } diff --git a/packages/node/tsconfig.json b/packages/node/tsconfig.json index 12836c865c..584369bf43 100644 --- a/packages/node/tsconfig.json +++ b/packages/node/tsconfig.json @@ -7,7 +7,8 @@ "inlineSourceMap": true, "lib": ["es2019"], "outDir": "./dist", - "resolveJsonModule": true + "resolveJsonModule": true, + "strict": true }, "include": [ "src/**/*",