From f33094b9c0c4f9799b833fb78ae1f6397e035c4e Mon Sep 17 00:00:00 2001 From: adamhenson Date: Wed, 23 Nov 2022 08:34:00 -0500 Subject: [PATCH] chore: dependency upgrades --- node_modules/.package-lock.json | 25 +- .../lighthouse-check/.prettierrc | 19 + .../lighthouse-check/babel.config.js | 6 +- .../dist/bin/lighthouse-check-status.js | 6 +- .../dist/bin/lighthouse-check.js | 6 +- .../lighthouse-check/dist/fetch.js | 22 +- .../dist/fetchAndWaitForLighthouseAudits.js | 2 +- .../dist/fetchLighthouseAudits.js | 2 +- .../dist/helpers/arguments.test.js | 124 +++ .../lighthouse-check/dist/lighthouseCheck.js | 12 +- .../lighthouse-check/dist/localLighthouse.js | 6 +- .../lighthouse-check/dist/postPrComment.js | 6 +- .../lighthouse-check/dist/slackNotify.js | 2 +- .../node_modules/node-fetch/@types/index.d.ts | 219 ----- .../node_modules/node-fetch/LICENSE.md | 22 - .../node_modules/node-fetch/README.md | 871 ------------------ .../node_modules/node-fetch/package.json | 131 --- .../node_modules/node-fetch/src/body.js | 397 -------- .../node-fetch/src/errors/abort-error.js | 10 - .../node-fetch/src/errors/base.js | 17 - .../node-fetch/src/errors/fetch-error.js | 26 - .../node_modules/node-fetch/src/headers.js | 267 ------ .../node_modules/node-fetch/src/index.js | 417 --------- .../node_modules/node-fetch/src/request.js | 317 ------- .../node_modules/node-fetch/src/response.js | 160 ---- .../node-fetch/src/utils/get-search.js | 9 - .../node-fetch/src/utils/is-redirect.js | 11 - .../node_modules/node-fetch/src/utils/is.js | 87 -- .../node-fetch/src/utils/multipart-parser.js | 432 --------- .../node-fetch/src/utils/referrer.js | 340 ------- .../lighthouse-check/package.json | 6 +- .../src/bin/lighthouse-check-status.js | 26 +- .../src/bin/lighthouse-check.js | 78 +- .../lighthouse-check/src/fetch.js | 8 +- .../src/fetchAndWaitForLighthouseAudits.js | 26 +- .../src/fetchLighthouseAudits.js | 18 +- .../lighthouse-check/src/helpers/arguments.js | 4 +- .../src/helpers/arguments.test.js | 145 +++ .../src/helpers/getHelpText.js | 2 +- .../helpers/getLighthouseAuditTitlesByKey.js | 2 +- .../getLighthouseAuditTitlesByKey.test.js | 4 +- .../lighthouse-check/src/index.js | 4 +- .../src/lighthouseAuditTitles.js | 2 +- .../lighthouse-check/src/lighthouseCheck.js | 50 +- .../lighthouse-check/src/lighthouseConfig.js | 24 +- .../lighthouse-check/src/lighthouseOptions.js | 6 +- .../lighthouse-check/src/localLighthouse.js | 68 +- .../src/localLighthouse.test.js | 16 +- .../lighthouse-check/src/logResults.js | 14 +- .../lighthouse-check/src/postPrComment.js | 49 +- .../lighthouse-check/src/slackNotify.js | 22 +- .../src/triggerLighthouse.test.js | 96 +- .../lighthouse-check/src/validateStatus.js | 26 +- package-lock.json | 47 +- package.json | 2 +- 55 files changed, 610 insertions(+), 4106 deletions(-) create mode 100644 node_modules/@foo-software/lighthouse-check/.prettierrc create mode 100644 node_modules/@foo-software/lighthouse-check/dist/helpers/arguments.test.js delete mode 100644 node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/@types/index.d.ts delete mode 100644 node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/LICENSE.md delete mode 100644 node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/README.md delete mode 100644 node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/package.json delete mode 100644 node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/body.js delete mode 100644 node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/errors/abort-error.js delete mode 100644 node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/errors/base.js delete mode 100644 node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/errors/fetch-error.js delete mode 100644 node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/headers.js delete mode 100644 node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/index.js delete mode 100644 node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/request.js delete mode 100644 node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/response.js delete mode 100644 node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/utils/get-search.js delete mode 100644 node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/utils/is-redirect.js delete mode 100644 node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/utils/is.js delete mode 100644 node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/utils/multipart-parser.js delete mode 100644 node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/utils/referrer.js create mode 100644 node_modules/@foo-software/lighthouse-check/src/helpers/arguments.test.js diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json index f09430d2c..2d08b7867 100644 --- a/node_modules/.package-lock.json +++ b/node_modules/.package-lock.json @@ -642,16 +642,16 @@ } }, "node_modules/@foo-software/lighthouse-check": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/@foo-software/lighthouse-check/-/lighthouse-check-8.0.4.tgz", - "integrity": "sha512-3v5dX3QxnG2LaHuVs4+t73Ksq4C52iRyeWDyO/t4oTBmdb/ttZK/CClad1tttY3Kf1SGvXK615T7VIfOcfEFMw==", + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/@foo-software/lighthouse-check/-/lighthouse-check-8.0.6.tgz", + "integrity": "sha512-SBG5Qu1C8BzbLHoIIqs9kWS1lOBk2ZlxZ7vlK73sy2LzXqO5mOhF4tKsMcH6/0RoQQklPqRTAbzjFjM4WDaUqA==", "dependencies": { "@foo-software/lighthouse-persist": "^6.2.0", "@slack/webhook": "^6.1.0", "babel-jest": "^29.3.1", "lodash.get": "^4.4.2", "meow": "^11.0.0", - "node-fetch": "^3.3.0", + "node-fetch": "^2.6.7", "ora": "^6.1.2", "table": "^6.8.1" }, @@ -663,23 +663,6 @@ "node": ">= 16.0.0" } }, - "node_modules/@foo-software/lighthouse-check/node_modules/node-fetch": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.0.tgz", - "integrity": "sha512-BKwRP/O0UvoMKp7GNdwPlObhYGB5DQqwhEDQlNKuoqwVYSxkSZCSbHjnFFmUEtwSKRPU4kNK8PbDYYitwaE3QA==", - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, "node_modules/@foo-software/lighthouse-persist": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/@foo-software/lighthouse-persist/-/lighthouse-persist-6.2.0.tgz", diff --git a/node_modules/@foo-software/lighthouse-check/.prettierrc b/node_modules/@foo-software/lighthouse-check/.prettierrc new file mode 100644 index 000000000..b6d799d75 --- /dev/null +++ b/node_modules/@foo-software/lighthouse-check/.prettierrc @@ -0,0 +1,19 @@ +{ + "importOrder": [ + "^react", + "", + "(?=^[.]+/)(?!.*.css$)", + "^.*.css$" + ], + "jsxSingleQuote": false, + "singleQuote": true, + "trailingComma": "all", + "overrides": [ + { + "files": "*.ts", + "options": { + "parser": "typescript" + } + } + ] +} diff --git a/node_modules/@foo-software/lighthouse-check/babel.config.js b/node_modules/@foo-software/lighthouse-check/babel.config.js index 392abb66d..4f5d536ff 100644 --- a/node_modules/@foo-software/lighthouse-check/babel.config.js +++ b/node_modules/@foo-software/lighthouse-check/babel.config.js @@ -1,12 +1,14 @@ module.exports = { presets: [ [ - "@babel/preset-env", + '@babel/preset-env', { targets: { - node: "current", + node: 'current', }, + modules: 'commonjs', }, ], ], + ignore: [/node_modules\/(?!node-fetch)/], }; diff --git a/node_modules/@foo-software/lighthouse-check/dist/bin/lighthouse-check-status.js b/node_modules/@foo-software/lighthouse-check/dist/bin/lighthouse-check-status.js index 4388ecbcb..92a641f1c 100755 --- a/node_modules/@foo-software/lighthouse-check/dist/bin/lighthouse-check-status.js +++ b/node_modules/@foo-software/lighthouse-check/dist/bin/lighthouse-check-status.js @@ -2,11 +2,11 @@ "use strict"; var _ora = _interopRequireDefault(require("ora")); -var _getHelpText = _interopRequireDefault(require("../helpers/getHelpText")); -var _validateStatus = _interopRequireDefault(require("../validateStatus")); var _constants = require("../constants"); -var _arguments = require("../helpers/arguments"); var _errorCodes = require("../errorCodes"); +var _arguments = require("../helpers/arguments"); +var _getHelpText = _interopRequireDefault(require("../helpers/getHelpText")); +var _validateStatus = _interopRequireDefault(require("../validateStatus")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const defaultOptions = { minAccessibilityScore: { diff --git a/node_modules/@foo-software/lighthouse-check/dist/bin/lighthouse-check.js b/node_modules/@foo-software/lighthouse-check/dist/bin/lighthouse-check.js index dee42f6ce..e078a8e4b 100755 --- a/node_modules/@foo-software/lighthouse-check/dist/bin/lighthouse-check.js +++ b/node_modules/@foo-software/lighthouse-check/dist/bin/lighthouse-check.js @@ -1,13 +1,13 @@ #! /usr/bin/env node "use strict"; -var _ora = _interopRequireDefault(require("ora")); var _fs = _interopRequireDefault(require("fs")); +var _ora = _interopRequireDefault(require("ora")); var _path = _interopRequireDefault(require("path")); -var _getHelpText = _interopRequireDefault(require("../helpers/getHelpText")); -var _lighthouseCheck = _interopRequireDefault(require("../lighthouseCheck")); var _constants = require("../constants"); var _arguments = require("../helpers/arguments"); +var _getHelpText = _interopRequireDefault(require("../helpers/getHelpText")); +var _lighthouseCheck = _interopRequireDefault(require("../lighthouseCheck")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const defaultOptions = { author: { diff --git a/node_modules/@foo-software/lighthouse-check/dist/fetch.js b/node_modules/@foo-software/lighthouse-check/dist/fetch.js index b60998c6f..e47b1a84b 100644 --- a/node_modules/@foo-software/lighthouse-check/dist/fetch.js +++ b/node_modules/@foo-software/lighthouse-check/dist/fetch.js @@ -3,17 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true }); -exports.default = void 0; -function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } -function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } +Object.defineProperty(exports, "default", { + enumerable: true, + get: function () { + return _nodeFetch.default; + } +}); +var _nodeFetch = _interopRequireDefault(require("node-fetch")); +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // this should only be defined when working locally. if (process.env.API_URL) { - process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0; -} - -// https://stackoverflow.com/a/69331469 -const fetch = (...args) => Promise.resolve().then(() => _interopRequireWildcard(require("node-fetch"))).then(({ - default: fetch -}) => fetch(...args)); -var _default = fetch; -exports.default = _default; \ No newline at end of file + process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0; +} \ No newline at end of file diff --git a/node_modules/@foo-software/lighthouse-check/dist/fetchAndWaitForLighthouseAudits.js b/node_modules/@foo-software/lighthouse-check/dist/fetchAndWaitForLighthouseAudits.js index ba558ce94..fad1f24e6 100644 --- a/node_modules/@foo-software/lighthouse-check/dist/fetchAndWaitForLighthouseAudits.js +++ b/node_modules/@foo-software/lighthouse-check/dist/fetchAndWaitForLighthouseAudits.js @@ -4,10 +4,10 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; -var _fetchLighthouseAudits = _interopRequireDefault(require("./fetchLighthouseAudits")); var _LighthouseCheckError = _interopRequireDefault(require("./LighthouseCheckError")); var _constants = require("./constants"); var _errorCodes = require("./errorCodes"); +var _fetchLighthouseAudits = _interopRequireDefault(require("./fetchLighthouseAudits")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var _default = ({ apiToken, diff --git a/node_modules/@foo-software/lighthouse-check/dist/fetchLighthouseAudits.js b/node_modules/@foo-software/lighthouse-check/dist/fetchLighthouseAudits.js index 14909c7db..5493566cd 100644 --- a/node_modules/@foo-software/lighthouse-check/dist/fetchLighthouseAudits.js +++ b/node_modules/@foo-software/lighthouse-check/dist/fetchLighthouseAudits.js @@ -5,10 +5,10 @@ Object.defineProperty(exports, "__esModule", { }); exports.default = void 0; var _lodash = _interopRequireDefault(require("lodash.get")); -var _fetch = _interopRequireDefault(require("./fetch")); var _LighthouseCheckError = _interopRequireDefault(require("./LighthouseCheckError")); var _constants = require("./constants"); var _errorCodes = require("./errorCodes"); +var _fetch = _interopRequireDefault(require("./fetch")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var _default = async ({ apiToken, diff --git a/node_modules/@foo-software/lighthouse-check/dist/helpers/arguments.test.js b/node_modules/@foo-software/lighthouse-check/dist/helpers/arguments.test.js new file mode 100644 index 000000000..18b7459ce --- /dev/null +++ b/node_modules/@foo-software/lighthouse-check/dist/helpers/arguments.test.js @@ -0,0 +1,124 @@ +"use strict"; + +var _arguments = require("./arguments"); +describe('convertOptionsFromArguments', () => { + const ARGV = process.argv; + beforeEach(() => { + // clear the cache + jest.resetModules(); + process.argv = ['/usr/local/bin/node', 'lighthouse-check', '--verbose', '--ipsum', 'lorem', '--hello', 'world', '--foo', 'bar', '--some-string', '--some-array']; + }); + afterEach(() => { + process.argv = ARGV; + }); + it('should use default values when arguments are non-existent', () => { + const expected = { + nonexistent: 'lorem', + nonexistent2: false + }; + const actual = (0, _arguments.convertOptionsFromArguments)({ + nonexistent: { + type: 'string', + value: 'lorem' + }, + nonexistent2: { + type: 'boolean', + value: false + } + }); + expect(actual).toEqual(expected); + }); + it('should override options from arguments', () => { + const expected = { + ipsum: 'lorem', + another: 'one', + hello: 'world' + }; + const actual = (0, _arguments.convertOptionsFromArguments)({ + ipsum: { + type: 'string', + value: 'foobar' + }, + another: { + type: 'string', + value: 'one' + }, + hello: { + type: 'string', + value: 'something' + } + }); + expect(actual).toEqual(expected); + }); + it('should treat explicitly defined boolean types as "true" when a value is empty', () => { + const actual = (0, _arguments.convertOptionsFromArguments)({ + verbose: { + type: 'boolean' + } + }); + expect(actual.verbose).toEqual(true); + }); + it('should ignore empty flag values that are not explicitly defined as boolean types', () => { + const actual = (0, _arguments.convertOptionsFromArguments)({ + 'some-string': { + type: 'string' + } + }); + expect(actual['some-string']).toBeUndefined(); + }); + it('should ignore empty flag values that are explicitly defined as array types', () => { + const actual = (0, _arguments.convertOptionsFromArguments)({ + 'some-array': { + type: 'array' + } + }); + expect(actual['some-array']).toBeUndefined(); + }); + it('should create correct types from CLI string argument', () => { + const options = (0, _arguments.convertOptionsFromArguments)({ + myEmptyString: { + type: 'string', + value: '' + }, + myString: { + type: 'string', + value: 'foobar' + }, + myBoolean: { + type: 'boolean', + value: 'true' + }, + myBooleanFalse: { + type: 'boolean', + value: 'false' + }, + myBooleanEmpty: { + type: 'boolean', + value: '' + }, + myNumber: { + type: 'number', + value: '100' + }, + myArray: { + type: 'array', + value: 'one,two' + }, + myObject: { + type: 'object', + value: '{"hello":"world","ipsum":"lorem"}' + } + }); + expect(typeof options.myEmptyString).toEqual('undefined'); + expect(options.myString).toEqual('foobar'); + expect(options.myBoolean).toEqual(true); + expect(options.myBooleanFalse).toEqual(false); + + // the CLI argument present with no arguments is interpretted as `true` + expect(options.myBooleanEmpty).toEqual(true); + expect(options.myNumber).toEqual(100); + expect(options.myArray).toEqual(['one', 'two']); + expect(options.myObject.hello).toEqual('world'); + expect(options.myObject.ipsum).toEqual('lorem'); + }); +}); \ No newline at end of file diff --git a/node_modules/@foo-software/lighthouse-check/dist/lighthouseCheck.js b/node_modules/@foo-software/lighthouse-check/dist/lighthouseCheck.js index 44a040f76..1d205834a 100644 --- a/node_modules/@foo-software/lighthouse-check/dist/lighthouseCheck.js +++ b/node_modules/@foo-software/lighthouse-check/dist/lighthouseCheck.js @@ -5,16 +5,16 @@ Object.defineProperty(exports, "__esModule", { }); exports.default = void 0; var _path = _interopRequireDefault(require("path")); -var _fetchAndWaitForLighthouseAudits = _interopRequireDefault(require("./fetchAndWaitForLighthouseAudits")); var _LighthouseCheckError = _interopRequireDefault(require("./LighthouseCheckError")); -var _triggerLighthouse = _interopRequireDefault(require("./triggerLighthouse")); -var _localLighthouse = _interopRequireDefault(require("./localLighthouse")); -var _postPrComment = _interopRequireDefault(require("./postPrComment")); -var _slackNotify = _interopRequireDefault(require("./slackNotify")); -var _writeResults = _interopRequireDefault(require("./helpers/writeResults")); var _constants = require("./constants"); var _errorCodes = require("./errorCodes"); +var _fetchAndWaitForLighthouseAudits = _interopRequireDefault(require("./fetchAndWaitForLighthouseAudits")); +var _writeResults = _interopRequireDefault(require("./helpers/writeResults")); +var _localLighthouse = _interopRequireDefault(require("./localLighthouse")); var _logResults = _interopRequireDefault(require("./logResults")); +var _postPrComment = _interopRequireDefault(require("./postPrComment")); +var _slackNotify = _interopRequireDefault(require("./slackNotify")); +var _triggerLighthouse = _interopRequireDefault(require("./triggerLighthouse")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var _default = ({ apiToken, diff --git a/node_modules/@foo-software/lighthouse-check/dist/localLighthouse.js b/node_modules/@foo-software/lighthouse-check/dist/localLighthouse.js index 42c76e7ae..1070be752 100644 --- a/node_modules/@foo-software/lighthouse-check/dist/localLighthouse.js +++ b/node_modules/@foo-software/lighthouse-check/dist/localLighthouse.js @@ -4,13 +4,13 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.localLighthouse = exports.getLocalLighthouseResultsWithRetries = exports.default = void 0; +var _lighthousePersist = _interopRequireDefault(require("@foo-software/lighthouse-persist")); var _fs = _interopRequireDefault(require("fs")); var _lodash = _interopRequireDefault(require("lodash.get")); -var _lighthousePersist = _interopRequireDefault(require("@foo-software/lighthouse-persist")); +var _constants = require("./constants"); +var _writeResults = _interopRequireDefault(require("./helpers/writeResults")); var _lighthouseConfig = require("./lighthouseConfig"); var _lighthouseOptions = _interopRequireDefault(require("./lighthouseOptions")); -var _writeResults = _interopRequireDefault(require("./helpers/writeResults")); -var _constants = require("./constants"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const defaultLighthouseConfigs = { desktop: _lighthouseConfig.desktop, diff --git a/node_modules/@foo-software/lighthouse-check/dist/postPrComment.js b/node_modules/@foo-software/lighthouse-check/dist/postPrComment.js index 7e8d95cb1..3d457378d 100644 --- a/node_modules/@foo-software/lighthouse-check/dist/postPrComment.js +++ b/node_modules/@foo-software/lighthouse-check/dist/postPrComment.js @@ -4,12 +4,12 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; +var _LighthouseCheckError = _interopRequireDefault(require("./LighthouseCheckError")); +var _constants = require("./constants"); +var _errorCodes = require("./errorCodes"); var _fetch = _interopRequireDefault(require("./fetch")); var _getLighthouseScoreColor = _interopRequireDefault(require("./helpers/getLighthouseScoreColor")); var _lighthouseAuditTitles = _interopRequireDefault(require("./lighthouseAuditTitles")); -var _LighthouseCheckError = _interopRequireDefault(require("./LighthouseCheckError")); -var _errorCodes = require("./errorCodes"); -var _constants = require("./constants"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const getBadge = ({ title, diff --git a/node_modules/@foo-software/lighthouse-check/dist/slackNotify.js b/node_modules/@foo-software/lighthouse-check/dist/slackNotify.js index 95581d1b8..eda49654b 100644 --- a/node_modules/@foo-software/lighthouse-check/dist/slackNotify.js +++ b/node_modules/@foo-software/lighthouse-check/dist/slackNotify.js @@ -5,9 +5,9 @@ Object.defineProperty(exports, "__esModule", { }); exports.default = void 0; var _webhook = require("@slack/webhook"); +var _constants = require("./constants"); var _getLighthouseScoreColor = _interopRequireDefault(require("./helpers/getLighthouseScoreColor")); var _lighthouseAuditTitles = _interopRequireDefault(require("./lighthouseAuditTitles")); -var _constants = require("./constants"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var _default = async ({ author, diff --git a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/@types/index.d.ts b/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/@types/index.d.ts deleted file mode 100644 index f68dd28e2..000000000 --- a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/@types/index.d.ts +++ /dev/null @@ -1,219 +0,0 @@ -/// - -import {RequestOptions} from 'http'; -import {FormData} from 'formdata-polyfill/esm.min.js'; -import { - Blob, - blobFrom, - blobFromSync, - File, - fileFrom, - fileFromSync -} from 'fetch-blob/from.js'; - -type AbortSignal = { - readonly aborted: boolean; - - addEventListener: (type: 'abort', listener: (this: AbortSignal) => void) => void; - removeEventListener: (type: 'abort', listener: (this: AbortSignal) => void) => void; -}; - -export type HeadersInit = Headers | Record | Iterable | Iterable>; - -export { - FormData, - Blob, - blobFrom, - blobFromSync, - File, - fileFrom, - fileFromSync -}; - -/** - * This Fetch API interface allows you to perform various actions on HTTP request and response headers. - * These actions include retrieving, setting, adding to, and removing. - * A Headers object has an associated header list, which is initially empty and consists of zero or more name and value pairs. - * You can add to this using methods like append() (see Examples.) - * In all methods of this interface, header names are matched by case-insensitive byte sequence. - * */ -export class Headers { - constructor(init?: HeadersInit); - - append(name: string, value: string): void; - delete(name: string): void; - get(name: string): string | null; - has(name: string): boolean; - set(name: string, value: string): void; - forEach( - callbackfn: (value: string, key: string, parent: Headers) => void, - thisArg?: any - ): void; - - [Symbol.iterator](): IterableIterator<[string, string]>; - /** - * Returns an iterator allowing to go through all key/value pairs contained in this object. - */ - entries(): IterableIterator<[string, string]>; - /** - * Returns an iterator allowing to go through all keys of the key/value pairs contained in this object. - */ - keys(): IterableIterator; - /** - * Returns an iterator allowing to go through all values of the key/value pairs contained in this object. - */ - values(): IterableIterator; - - /** Node-fetch extension */ - raw(): Record; -} - -export interface RequestInit { - /** - * A BodyInit object or null to set request's body. - */ - body?: BodyInit | null; - /** - * A Headers object, an object literal, or an array of two-item arrays to set request's headers. - */ - headers?: HeadersInit; - /** - * A string to set request's method. - */ - method?: string; - /** - * A string indicating whether request follows redirects, results in an error upon encountering a redirect, or returns the redirect (in an opaque fashion). Sets request's redirect. - */ - redirect?: RequestRedirect; - /** - * An AbortSignal to set request's signal. - */ - signal?: AbortSignal | null; - /** - * A string whose value is a same-origin URL, "about:client", or the empty string, to set request’s referrer. - */ - referrer?: string; - /** - * A referrer policy to set request’s referrerPolicy. - */ - referrerPolicy?: ReferrerPolicy; - - // Node-fetch extensions to the whatwg/fetch spec - agent?: RequestOptions['agent'] | ((parsedUrl: URL) => RequestOptions['agent']); - compress?: boolean; - counter?: number; - follow?: number; - hostname?: string; - port?: number; - protocol?: string; - size?: number; - highWaterMark?: number; - insecureHTTPParser?: boolean; -} - -export interface ResponseInit { - headers?: HeadersInit; - status?: number; - statusText?: string; -} - -export type BodyInit = - | Blob - | Buffer - | URLSearchParams - | FormData - | NodeJS.ReadableStream - | string; -declare class BodyMixin { - constructor(body?: BodyInit, options?: {size?: number}); - - readonly body: NodeJS.ReadableStream | null; - readonly bodyUsed: boolean; - readonly size: number; - - /** @deprecated Use `body.arrayBuffer()` instead. */ - buffer(): Promise; - arrayBuffer(): Promise; - formData(): Promise; - blob(): Promise; - json(): Promise; - text(): Promise; -} - -// `Body` must not be exported as a class since it's not exported from the JavaScript code. -export interface Body extends Pick {} - -export type RequestRedirect = 'error' | 'follow' | 'manual'; -export type ReferrerPolicy = '' | 'no-referrer' | 'no-referrer-when-downgrade' | 'same-origin' | 'origin' | 'strict-origin' | 'origin-when-cross-origin' | 'strict-origin-when-cross-origin' | 'unsafe-url'; -export type RequestInfo = string | Request; -export class Request extends BodyMixin { - constructor(input: RequestInfo, init?: RequestInit); - - /** - * Returns a Headers object consisting of the headers associated with request. Note that headers added in the network layer by the user agent will not be accounted for in this object, e.g., the "Host" header. - */ - readonly headers: Headers; - /** - * Returns request's HTTP method, which is "GET" by default. - */ - readonly method: string; - /** - * Returns the redirect mode associated with request, which is a string indicating how redirects for the request will be handled during fetching. A request will follow redirects by default. - */ - readonly redirect: RequestRedirect; - /** - * Returns the signal associated with request, which is an AbortSignal object indicating whether or not request has been aborted, and its abort event handler. - */ - readonly signal: AbortSignal; - /** - * Returns the URL of request as a string. - */ - readonly url: string; - /** - * A string whose value is a same-origin URL, "about:client", or the empty string, to set request’s referrer. - */ - readonly referrer: string; - /** - * A referrer policy to set request’s referrerPolicy. - */ - readonly referrerPolicy: ReferrerPolicy; - clone(): Request; -} - -type ResponseType = 'basic' | 'cors' | 'default' | 'error' | 'opaque' | 'opaqueredirect'; - -export class Response extends BodyMixin { - constructor(body?: BodyInit | null, init?: ResponseInit); - - readonly headers: Headers; - readonly ok: boolean; - readonly redirected: boolean; - readonly status: number; - readonly statusText: string; - readonly type: ResponseType; - readonly url: string; - clone(): Response; - - static error(): Response; - static redirect(url: string, status?: number): Response; - static json(data: any, init?: ResponseInit): Response; -} - -export class FetchError extends Error { - constructor(message: string, type: string, systemError?: Record); - - name: 'FetchError'; - [Symbol.toStringTag]: 'FetchError'; - type: string; - code?: string; - errno?: string; -} - -export class AbortError extends Error { - type: string; - name: 'AbortError'; - [Symbol.toStringTag]: 'AbortError'; -} - -export function isRedirect(code: number): boolean; -export default function fetch(url: RequestInfo, init?: RequestInit): Promise; diff --git a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/LICENSE.md b/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/LICENSE.md deleted file mode 100644 index 41ca1b6eb..000000000 --- a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/LICENSE.md +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 - 2020 Node Fetch Team - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/README.md b/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/README.md deleted file mode 100644 index d62c9c64d..000000000 --- a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/README.md +++ /dev/null @@ -1,871 +0,0 @@ -
- Node Fetch -
-

A light-weight module that brings Fetch API to Node.js.

- Build status - Coverage status - Current version - Install size - Mentioned in Awesome Node.js - Discord -
-
- Consider supporting us on our Open Collective: -
-
- Open Collective -
- ---- - -**You might be looking for the [v2 docs](https://github.com/node-fetch/node-fetch/tree/2.x#readme)** - - - -- [Motivation](#motivation) -- [Features](#features) -- [Difference from client-side fetch](#difference-from-client-side-fetch) -- [Installation](#installation) -- [Loading and configuring the module](#loading-and-configuring-the-module) -- [Upgrading](#upgrading) -- [Common Usage](#common-usage) - - [Plain text or HTML](#plain-text-or-html) - - [JSON](#json) - - [Simple Post](#simple-post) - - [Post with JSON](#post-with-json) - - [Post with form parameters](#post-with-form-parameters) - - [Handling exceptions](#handling-exceptions) - - [Handling client and server errors](#handling-client-and-server-errors) - - [Handling cookies](#handling-cookies) -- [Advanced Usage](#advanced-usage) - - [Streams](#streams) - - [Accessing Headers and other Metadata](#accessing-headers-and-other-metadata) - - [Extract Set-Cookie Header](#extract-set-cookie-header) - - [Post data using a file](#post-data-using-a-file) - - [Request cancellation with AbortSignal](#request-cancellation-with-abortsignal) -- [API](#api) - - [fetch(url[, options])](#fetchurl-options) - - [Options](#options) - - [Default Headers](#default-headers) - - [Custom Agent](#custom-agent) - - [Custom highWaterMark](#custom-highwatermark) - - [Insecure HTTP Parser](#insecure-http-parser) - - [Class: Request](#class-request) - - [new Request(input[, options])](#new-requestinput-options) - - [Class: Response](#class-response) - - [new Response([body[, options]])](#new-responsebody-options) - - [response.ok](#responseok) - - [response.redirected](#responseredirected) - - [response.type](#responsetype) - - [Class: Headers](#class-headers) - - [new Headers([init])](#new-headersinit) - - [Interface: Body](#interface-body) - - [body.body](#bodybody) - - [body.bodyUsed](#bodybodyused) - - [body.arrayBuffer()](#bodyarraybuffer) - - [body.blob()](#bodyblob) - - [body.formData()](#formdata) - - [body.json()](#bodyjson) - - [body.text()](#bodytext) - - [Class: FetchError](#class-fetcherror) - - [Class: AbortError](#class-aborterror) -- [TypeScript](#typescript) -- [Acknowledgement](#acknowledgement) -- [Team](#team) - - [Former](#former) -- [License](#license) - - - -## Motivation - -Instead of implementing `XMLHttpRequest` in Node.js to run browser-specific [Fetch polyfill](https://github.com/github/fetch), why not go from native `http` to `fetch` API directly? Hence, `node-fetch`, minimal code for a `window.fetch` compatible API on Node.js runtime. - -See Jason Miller's [isomorphic-unfetch](https://www.npmjs.com/package/isomorphic-unfetch) or Leonardo Quixada's [cross-fetch](https://github.com/lquixada/cross-fetch) for isomorphic usage (exports `node-fetch` for server-side, `whatwg-fetch` for client-side). - -## Features - -- Stay consistent with `window.fetch` API. -- Make conscious trade-off when following [WHATWG fetch spec][whatwg-fetch] and [stream spec](https://streams.spec.whatwg.org/) implementation details, document known differences. -- Use native promise and async functions. -- Use native Node streams for body, on both request and response. -- Decode content encoding (gzip/deflate/brotli) properly, and convert string output (such as `res.text()` and `res.json()`) to UTF-8 automatically. -- Useful extensions such as redirect limit, response size limit, [explicit errors][error-handling.md] for troubleshooting. - -## Difference from client-side fetch - -- See known differences: - - [As of v3.x](docs/v3-LIMITS.md) - - [As of v2.x](docs/v2-LIMITS.md) -- If you happen to use a missing feature that `window.fetch` offers, feel free to open an issue. -- Pull requests are welcomed too! - -## Installation - -Current stable release (`3.x`) requires at least Node.js 12.20.0. - -```sh -npm install node-fetch -``` - -## Loading and configuring the module - -### ES Modules (ESM) - -```js -import fetch from 'node-fetch'; -``` - -### CommonJS - -`node-fetch` from v3 is an ESM-only module - you are not able to import it with `require()`. - -If you cannot switch to ESM, please use v2 which remains compatible with CommonJS. Critical bug fixes will continue to be published for v2. - -```sh -npm install node-fetch@2 -``` - -Alternatively, you can use the async `import()` function from CommonJS to load `node-fetch` asynchronously: - -```js -// mod.cjs -const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args)); -``` - -### Providing global access - -To use `fetch()` without importing it, you can patch the `global` object in node: - -```js -// fetch-polyfill.js -import fetch, { - Blob, - blobFrom, - blobFromSync, - File, - fileFrom, - fileFromSync, - FormData, - Headers, - Request, - Response, -} from 'node-fetch' - -if (!globalThis.fetch) { - globalThis.fetch = fetch - globalThis.Headers = Headers - globalThis.Request = Request - globalThis.Response = Response -} - -// index.js -import './fetch-polyfill' - -// ... -``` - -## Upgrading - -Using an old version of node-fetch? Check out the following files: - -- [2.x to 3.x upgrade guide](docs/v3-UPGRADE-GUIDE.md) -- [1.x to 2.x upgrade guide](docs/v2-UPGRADE-GUIDE.md) -- [Changelog](https://github.com/node-fetch/node-fetch/releases) - -## Common Usage - -NOTE: The documentation below is up-to-date with `3.x` releases, if you are using an older version, please check how to [upgrade](#upgrading). - -### Plain text or HTML - -```js -import fetch from 'node-fetch'; - -const response = await fetch('https://github.com/'); -const body = await response.text(); - -console.log(body); -``` - -### JSON - -```js -import fetch from 'node-fetch'; - -const response = await fetch('https://api.github.com/users/github'); -const data = await response.json(); - -console.log(data); -``` - -### Simple Post - -```js -import fetch from 'node-fetch'; - -const response = await fetch('https://httpbin.org/post', {method: 'POST', body: 'a=1'}); -const data = await response.json(); - -console.log(data); -``` - -### Post with JSON - -```js -import fetch from 'node-fetch'; - -const body = {a: 1}; - -const response = await fetch('https://httpbin.org/post', { - method: 'post', - body: JSON.stringify(body), - headers: {'Content-Type': 'application/json'} -}); -const data = await response.json(); - -console.log(data); -``` - -### Post with form parameters - -`URLSearchParams` is available on the global object in Node.js as of v10.0.0. See [official documentation](https://nodejs.org/api/url.html#url_class_urlsearchparams) for more usage methods. - -NOTE: The `Content-Type` header is only set automatically to `x-www-form-urlencoded` when an instance of `URLSearchParams` is given as such: - -```js -import fetch from 'node-fetch'; - -const params = new URLSearchParams(); -params.append('a', 1); - -const response = await fetch('https://httpbin.org/post', {method: 'POST', body: params}); -const data = await response.json(); - -console.log(data); -``` - -### Handling exceptions - -NOTE: 3xx-5xx responses are _NOT_ exceptions, and should be handled in `then()`, see the next section. - -Wrapping the fetch function into a `try/catch` block will catch _all_ exceptions, such as errors originating from node core libraries, like network errors, and operational errors which are instances of FetchError. See the [error handling document][error-handling.md] for more details. - -```js -import fetch from 'node-fetch'; - -try { - await fetch('https://domain.invalid/'); -} catch (error) { - console.log(error); -} -``` - -### Handling client and server errors - -It is common to create a helper function to check that the response contains no client (4xx) or server (5xx) error responses: - -```js -import fetch from 'node-fetch'; - -class HTTPResponseError extends Error { - constructor(response) { - super(`HTTP Error Response: ${response.status} ${response.statusText}`); - this.response = response; - } -} - -const checkStatus = response => { - if (response.ok) { - // response.status >= 200 && response.status < 300 - return response; - } else { - throw new HTTPResponseError(response); - } -} - -const response = await fetch('https://httpbin.org/status/400'); - -try { - checkStatus(response); -} catch (error) { - console.error(error); - - const errorBody = await error.response.text(); - console.error(`Error body: ${errorBody}`); -} -``` - -### Handling cookies - -Cookies are not stored by default. However, cookies can be extracted and passed by manipulating request and response headers. See [Extract Set-Cookie Header](#extract-set-cookie-header) for details. - -## Advanced Usage - -### Streams - -The "Node.js way" is to use streams when possible. You can pipe `res.body` to another stream. This example uses [stream.pipeline](https://nodejs.org/api/stream.html#stream_stream_pipeline_streams_callback) to attach stream error handlers and wait for the download to complete. - -```js -import {createWriteStream} from 'node:fs'; -import {pipeline} from 'node:stream'; -import {promisify} from 'node:util' -import fetch from 'node-fetch'; - -const streamPipeline = promisify(pipeline); - -const response = await fetch('https://github.githubassets.com/images/modules/logos_page/Octocat.png'); - -if (!response.ok) throw new Error(`unexpected response ${response.statusText}`); - -await streamPipeline(response.body, createWriteStream('./octocat.png')); -``` - -In Node.js 14 you can also use async iterators to read `body`; however, be careful to catch -errors -- the longer a response runs, the more likely it is to encounter an error. - -```js -import fetch from 'node-fetch'; - -const response = await fetch('https://httpbin.org/stream/3'); - -try { - for await (const chunk of response.body) { - console.dir(JSON.parse(chunk.toString())); - } -} catch (err) { - console.error(err.stack); -} -``` - -In Node.js 12 you can also use async iterators to read `body`; however, async iterators with streams -did not mature until Node.js 14, so you need to do some extra work to ensure you handle errors -directly from the stream and wait on it response to fully close. - -```js -import fetch from 'node-fetch'; - -const read = async body => { - let error; - body.on('error', err => { - error = err; - }); - - for await (const chunk of body) { - console.dir(JSON.parse(chunk.toString())); - } - - return new Promise((resolve, reject) => { - body.on('close', () => { - error ? reject(error) : resolve(); - }); - }); -}; - -try { - const response = await fetch('https://httpbin.org/stream/3'); - await read(response.body); -} catch (err) { - console.error(err.stack); -} -``` - -### Accessing Headers and other Metadata - -```js -import fetch from 'node-fetch'; - -const response = await fetch('https://github.com/'); - -console.log(response.ok); -console.log(response.status); -console.log(response.statusText); -console.log(response.headers.raw()); -console.log(response.headers.get('content-type')); -``` - -### Extract Set-Cookie Header - -Unlike browsers, you can access raw `Set-Cookie` headers manually using `Headers.raw()`. This is a `node-fetch` only API. - -```js -import fetch from 'node-fetch'; - -const response = await fetch('https://example.com'); - -// Returns an array of values, instead of a string of comma-separated values -console.log(response.headers.raw()['set-cookie']); -``` - -### Post data using a file - -```js -import fetch, { - Blob, - blobFrom, - blobFromSync, - File, - fileFrom, - fileFromSync, -} from 'node-fetch' - -const mimetype = 'text/plain' -const blob = fileFromSync('./input.txt', mimetype) -const url = 'https://httpbin.org/post' - -const response = await fetch(url, { method: 'POST', body: blob }) -const data = await response.json() - -console.log(data) -``` - -node-fetch comes with a spec-compliant [FormData] implementations for posting -multipart/form-data payloads - -```js -import fetch, { FormData, File, fileFrom } from 'node-fetch' - -const httpbin = 'https://httpbin.org/post' -const formData = new FormData() -const binary = new Uint8Array([ 97, 98, 99 ]) -const abc = new File([binary], 'abc.txt', { type: 'text/plain' }) - -formData.set('greeting', 'Hello, world!') -formData.set('file-upload', abc, 'new name.txt') - -const response = await fetch(httpbin, { method: 'POST', body: formData }) -const data = await response.json() - -console.log(data) -``` - -If you for some reason need to post a stream coming from any arbitrary place, -then you can append a [Blob] or a [File] look-a-like item. - -The minimum requirement is that it has: -1. A `Symbol.toStringTag` getter or property that is either `Blob` or `File` -2. A known size. -3. And either a `stream()` method or a `arrayBuffer()` method that returns a ArrayBuffer. - -The `stream()` must return any async iterable object as long as it yields Uint8Array (or Buffer) -so Node.Readable streams and whatwg streams works just fine. - -```js -formData.append('upload', { - [Symbol.toStringTag]: 'Blob', - size: 3, - *stream() { - yield new Uint8Array([97, 98, 99]) - }, - arrayBuffer() { - return new Uint8Array([97, 98, 99]).buffer - } -}, 'abc.txt') -``` - -### Request cancellation with AbortSignal - -You may cancel requests with `AbortController`. A suggested implementation is [`abort-controller`](https://www.npmjs.com/package/abort-controller). - -An example of timing out a request after 150ms could be achieved as the following: - -```js -import fetch, { AbortError } from 'node-fetch'; - -// AbortController was added in node v14.17.0 globally -const AbortController = globalThis.AbortController || await import('abort-controller') - -const controller = new AbortController(); -const timeout = setTimeout(() => { - controller.abort(); -}, 150); - -try { - const response = await fetch('https://example.com', {signal: controller.signal}); - const data = await response.json(); -} catch (error) { - if (error instanceof AbortError) { - console.log('request was aborted'); - } -} finally { - clearTimeout(timeout); -} -``` - -See [test cases](https://github.com/node-fetch/node-fetch/blob/master/test/) for more examples. - -## API - -### fetch(url[, options]) - -- `url` A string representing the URL for fetching -- `options` [Options](#fetch-options) for the HTTP(S) request -- Returns: Promise<[Response](#class-response)> - -Perform an HTTP(S) fetch. - -`url` should be an absolute URL, such as `https://example.com/`. A path-relative URL (`/file/under/root`) or protocol-relative URL (`//can-be-http-or-https.com/`) will result in a rejected `Promise`. - - - -### Options - -The default values are shown after each option key. - -```js -{ - // These properties are part of the Fetch Standard - method: 'GET', - headers: {}, // Request headers. format is the identical to that accepted by the Headers constructor (see below) - body: null, // Request body. can be null, or a Node.js Readable stream - redirect: 'follow', // Set to `manual` to extract redirect headers, `error` to reject redirect - signal: null, // Pass an instance of AbortSignal to optionally abort requests - - // The following properties are node-fetch extensions - follow: 20, // maximum redirect count. 0 to not follow redirect - compress: true, // support gzip/deflate content encoding. false to disable - size: 0, // maximum response body size in bytes. 0 to disable - agent: null, // http(s).Agent instance or function that returns an instance (see below) - highWaterMark: 16384, // the maximum number of bytes to store in the internal buffer before ceasing to read from the underlying resource. - insecureHTTPParser: false // Use an insecure HTTP parser that accepts invalid HTTP headers when `true`. -} -``` - -#### Default Headers - -If no values are set, the following request headers will be sent automatically: - -| Header | Value | -| ------------------- | ------------------------------------------------------ | -| `Accept-Encoding` | `gzip, deflate, br` (when `options.compress === true`) | -| `Accept` | `*/*` | -| `Connection` | `close` _(when no `options.agent` is present)_ | -| `Content-Length` | _(automatically calculated, if possible)_ | -| `Host` | _(host and port information from the target URI)_ | -| `Transfer-Encoding` | `chunked` _(when `req.body` is a stream)_ | -| `User-Agent` | `node-fetch` | - - -Note: when `body` is a `Stream`, `Content-Length` is not set automatically. - -#### Custom Agent - -The `agent` option allows you to specify networking related options which are out of the scope of Fetch, including and not limited to the following: - -- Support self-signed certificate -- Use only IPv4 or IPv6 -- Custom DNS Lookup - -See [`http.Agent`](https://nodejs.org/api/http.html#http_new_agent_options) for more information. - -In addition, the `agent` option accepts a function that returns `http`(s)`.Agent` instance given current [URL](https://nodejs.org/api/url.html), this is useful during a redirection chain across HTTP and HTTPS protocol. - -```js -import http from 'node:http'; -import https from 'node:https'; - -const httpAgent = new http.Agent({ - keepAlive: true -}); -const httpsAgent = new https.Agent({ - keepAlive: true -}); - -const options = { - agent: function(_parsedURL) { - if (_parsedURL.protocol == 'http:') { - return httpAgent; - } else { - return httpsAgent; - } - } -}; -``` - - - -#### Custom highWaterMark - -Stream on Node.js have a smaller internal buffer size (16kB, aka `highWaterMark`) from client-side browsers (>1MB, not consistent across browsers). Because of that, when you are writing an isomorphic app and using `res.clone()`, it will hang with large response in Node. - -The recommended way to fix this problem is to resolve cloned response in parallel: - -```js -import fetch from 'node-fetch'; - -const response = await fetch('https://example.com'); -const r1 = response.clone(); - -const results = await Promise.all([response.json(), r1.text()]); - -console.log(results[0]); -console.log(results[1]); -``` - -If for some reason you don't like the solution above, since `3.x` you are able to modify the `highWaterMark` option: - -```js -import fetch from 'node-fetch'; - -const response = await fetch('https://example.com', { - // About 1MB - highWaterMark: 1024 * 1024 -}); - -const result = await res.clone().arrayBuffer(); -console.dir(result); -``` - -#### Insecure HTTP Parser - -Passed through to the `insecureHTTPParser` option on http(s).request. See [`http.request`](https://nodejs.org/api/http.html#http_http_request_url_options_callback) for more information. - -#### Manual Redirect - -The `redirect: 'manual'` option for node-fetch is different from the browser & specification, which -results in an [opaque-redirect filtered response](https://fetch.spec.whatwg.org/#concept-filtered-response-opaque-redirect). -node-fetch gives you the typical [basic filtered response](https://fetch.spec.whatwg.org/#concept-filtered-response-basic) instead. - -```js -const fetch = require('node-fetch'); - -const response = await fetch('https://httpbin.org/status/301', { redirect: 'manual' }); - -if (response.status === 301 || response.status === 302) { - const locationURL = new URL(response.headers.get('location'), response.url); - const response2 = await fetch(locationURL, { redirect: 'manual' }); - console.dir(response2); -} -``` - - - -### Class: Request - -An HTTP(S) request containing information about URL, method, headers, and the body. This class implements the [Body](#iface-body) interface. - -Due to the nature of Node.js, the following properties are not implemented at this moment: - -- `type` -- `destination` -- `mode` -- `credentials` -- `cache` -- `integrity` -- `keepalive` - -The following node-fetch extension properties are provided: - -- `follow` -- `compress` -- `counter` -- `agent` -- `highWaterMark` - -See [options](#fetch-options) for exact meaning of these extensions. - -#### new Request(input[, options]) - -_(spec-compliant)_ - -- `input` A string representing a URL, or another `Request` (which will be cloned) -- `options` [Options](#fetch-options) for the HTTP(S) request - -Constructs a new `Request` object. The constructor is identical to that in the [browser](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request). - -In most cases, directly `fetch(url, options)` is simpler than creating a `Request` object. - - - -### Class: Response - -An HTTP(S) response. This class implements the [Body](#iface-body) interface. - -The following properties are not implemented in node-fetch at this moment: - -- `trailer` - -#### new Response([body[, options]]) - -_(spec-compliant)_ - -- `body` A `String` or [`Readable` stream][node-readable] -- `options` A [`ResponseInit`][response-init] options dictionary - -Constructs a new `Response` object. The constructor is identical to that in the [browser](https://developer.mozilla.org/en-US/docs/Web/API/Response/Response). - -Because Node.js does not implement service workers (for which this class was designed), one rarely has to construct a `Response` directly. - -#### response.ok - -_(spec-compliant)_ - -Convenience property representing if the request ended normally. Will evaluate to true if the response status was greater than or equal to 200 but smaller than 300. - -#### response.redirected - -_(spec-compliant)_ - -Convenience property representing if the request has been redirected at least once. Will evaluate to true if the internal redirect counter is greater than 0. - -#### response.type - -_(deviation from spec)_ - -Convenience property representing the response's type. node-fetch only supports `'default'` and `'error'` and does not make use of [filtered responses](https://fetch.spec.whatwg.org/#concept-filtered-response). - - - -### Class: Headers - -This class allows manipulating and iterating over a set of HTTP headers. All methods specified in the [Fetch Standard][whatwg-fetch] are implemented. - -#### new Headers([init]) - -_(spec-compliant)_ - -- `init` Optional argument to pre-fill the `Headers` object - -Construct a new `Headers` object. `init` can be either `null`, a `Headers` object, an key-value map object or any iterable object. - -```js -// Example adapted from https://fetch.spec.whatwg.org/#example-headers-class -import {Headers} from 'node-fetch'; - -const meta = { - 'Content-Type': 'text/xml' -}; -const headers = new Headers(meta); - -// The above is equivalent to -const meta = [['Content-Type', 'text/xml']]; -const headers = new Headers(meta); - -// You can in fact use any iterable objects, like a Map or even another Headers -const meta = new Map(); -meta.set('Content-Type', 'text/xml'); -const headers = new Headers(meta); -const copyOfHeaders = new Headers(headers); -``` - - - -### Interface: Body - -`Body` is an abstract interface with methods that are applicable to both `Request` and `Response` classes. - -#### body.body - -_(deviation from spec)_ - -- Node.js [`Readable` stream][node-readable] - -Data are encapsulated in the `Body` object. Note that while the [Fetch Standard][whatwg-fetch] requires the property to always be a WHATWG `ReadableStream`, in node-fetch it is a Node.js [`Readable` stream][node-readable]. - -#### body.bodyUsed - -_(spec-compliant)_ - -- `Boolean` - -A boolean property for if this body has been consumed. Per the specs, a consumed body cannot be used again. - -#### body.arrayBuffer() - -#### body.formData() - -#### body.blob() - -#### body.json() - -#### body.text() - -`fetch` comes with methods to parse `multipart/form-data` payloads as well as -`x-www-form-urlencoded` bodies using `.formData()` this comes from the idea that -Service Worker can intercept such messages before it's sent to the server to -alter them. This is useful for anybody building a server so you can use it to -parse & consume payloads. - -
-Code example - -```js -import http from 'node:http' -import { Response } from 'node-fetch' - -http.createServer(async function (req, res) { - const formData = await new Response(req, { - headers: req.headers // Pass along the boundary value - }).formData() - const allFields = [...formData] - - const file = formData.get('uploaded-files') - const arrayBuffer = await file.arrayBuffer() - const text = await file.text() - const whatwgReadableStream = file.stream() - - // other was to consume the request could be to do: - const json = await new Response(req).json() - const text = await new Response(req).text() - const arrayBuffer = await new Response(req).arrayBuffer() - const blob = await new Response(req, { - headers: req.headers // So that `type` inherits `Content-Type` - }.blob() -}) -``` - -
- - - -### Class: FetchError - -_(node-fetch extension)_ - -An operational error in the fetching process. See [ERROR-HANDLING.md][] for more info. - - - -### Class: AbortError - -_(node-fetch extension)_ - -An Error thrown when the request is aborted in response to an `AbortSignal`'s `abort` event. It has a `name` property of `AbortError`. See [ERROR-HANDLING.MD][] for more info. - -## TypeScript - -**Since `3.x` types are bundled with `node-fetch`, so you don't need to install any additional packages.** - -For older versions please use the type definitions from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped): - -```sh -npm install --save-dev @types/node-fetch@2.x -``` - -## Acknowledgement - -Thanks to [github/fetch](https://github.com/github/fetch) for providing a solid implementation reference. - -## Team - -| [![David Frank](https://github.com/bitinn.png?size=100)](https://github.com/bitinn) | [![Jimmy Wärting](https://github.com/jimmywarting.png?size=100)](https://github.com/jimmywarting) | [![Antoni Kepinski](https://github.com/xxczaki.png?size=100)](https://github.com/xxczaki) | [![Richie Bendall](https://github.com/Richienb.png?size=100)](https://github.com/Richienb) | [![Gregor Martynus](https://github.com/gr2m.png?size=100)](https://github.com/gr2m) | -| ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------- | -| [David Frank](https://bitinn.net/) | [Jimmy Wärting](https://jimmy.warting.se/) | [Antoni Kepinski](https://kepinski.ch) | [Richie Bendall](https://www.richie-bendall.ml/) | [Gregor Martynus](https://twitter.com/gr2m) | - -###### Former - -- [Timothy Gu](https://github.com/timothygu) -- [Jared Kantrowitz](https://github.com/jkantr) - -## License - -[MIT](LICENSE.md) - -[whatwg-fetch]: https://fetch.spec.whatwg.org/ -[response-init]: https://fetch.spec.whatwg.org/#responseinit -[node-readable]: https://nodejs.org/api/stream.html#stream_readable_streams -[mdn-headers]: https://developer.mozilla.org/en-US/docs/Web/API/Headers -[error-handling.md]: https://github.com/node-fetch/node-fetch/blob/master/docs/ERROR-HANDLING.md -[FormData]: https://developer.mozilla.org/en-US/docs/Web/API/FormData -[Blob]: https://developer.mozilla.org/en-US/docs/Web/API/Blob -[File]: https://developer.mozilla.org/en-US/docs/Web/API/File diff --git a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/package.json b/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/package.json deleted file mode 100644 index 441a027f9..000000000 --- a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/package.json +++ /dev/null @@ -1,131 +0,0 @@ -{ - "name": "node-fetch", - "version": "3.3.0", - "description": "A light-weight module that brings Fetch API to node.js", - "main": "./src/index.js", - "sideEffects": false, - "type": "module", - "files": [ - "src", - "@types/index.d.ts" - ], - "types": "./@types/index.d.ts", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "scripts": { - "test": "mocha", - "coverage": "c8 report --reporter=text-lcov | coveralls", - "test-types": "tsd", - "lint": "xo" - }, - "repository": { - "type": "git", - "url": "https://github.com/node-fetch/node-fetch.git" - }, - "keywords": [ - "fetch", - "http", - "promise", - "request", - "curl", - "wget", - "xhr", - "whatwg" - ], - "author": "David Frank", - "license": "MIT", - "bugs": { - "url": "https://github.com/node-fetch/node-fetch/issues" - }, - "homepage": "https://github.com/node-fetch/node-fetch", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - }, - "devDependencies": { - "abort-controller": "^3.0.0", - "abortcontroller-polyfill": "^1.7.1", - "busboy": "^1.4.0", - "c8": "^7.7.2", - "chai": "^4.3.4", - "chai-as-promised": "^7.1.1", - "chai-iterator": "^3.0.2", - "chai-string": "^1.5.0", - "coveralls": "^3.1.0", - "form-data": "^4.0.0", - "formdata-node": "^4.2.4", - "mocha": "^9.1.3", - "p-timeout": "^5.0.0", - "stream-consumers": "^1.0.1", - "tsd": "^0.14.0", - "xo": "^0.39.1" - }, - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "tsd": { - "cwd": "@types", - "compilerOptions": { - "esModuleInterop": true - } - }, - "xo": { - "envs": [ - "node", - "browser" - ], - "ignores": [ - "example.js" - ], - "rules": { - "complexity": 0, - "import/extensions": 0, - "import/no-useless-path-segments": 0, - "import/no-anonymous-default-export": 0, - "import/no-named-as-default": 0, - "unicorn/import-index": 0, - "unicorn/no-array-reduce": 0, - "unicorn/prefer-node-protocol": 0, - "unicorn/numeric-separators-style": 0, - "unicorn/explicit-length-check": 0, - "capitalized-comments": 0, - "node/no-unsupported-features/es-syntax": 0, - "@typescript-eslint/member-ordering": 0 - }, - "overrides": [ - { - "files": "test/**/*.js", - "envs": [ - "node", - "mocha" - ], - "rules": { - "max-nested-callbacks": 0, - "no-unused-expressions": 0, - "no-warning-comments": 0, - "new-cap": 0, - "guard-for-in": 0, - "unicorn/no-array-for-each": 0, - "unicorn/prevent-abbreviations": 0, - "promise/prefer-await-to-then": 0, - "ava/no-import-test-files": 0 - } - } - ] - }, - "runkitExampleFilename": "example.js", - "release": { - "branches": [ - "+([0-9]).x", - "main", - "next", - { - "name": "beta", - "prerelease": true - } - ] - } -} diff --git a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/body.js b/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/body.js deleted file mode 100644 index 714e27ec4..000000000 --- a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/body.js +++ /dev/null @@ -1,397 +0,0 @@ - -/** - * Body.js - * - * Body interface provides common methods for Request and Response - */ - -import Stream, {PassThrough} from 'node:stream'; -import {types, deprecate, promisify} from 'node:util'; -import {Buffer} from 'node:buffer'; - -import Blob from 'fetch-blob'; -import {FormData, formDataToBlob} from 'formdata-polyfill/esm.min.js'; - -import {FetchError} from './errors/fetch-error.js'; -import {FetchBaseError} from './errors/base.js'; -import {isBlob, isURLSearchParameters} from './utils/is.js'; - -const pipeline = promisify(Stream.pipeline); -const INTERNALS = Symbol('Body internals'); - -/** - * Body mixin - * - * Ref: https://fetch.spec.whatwg.org/#body - * - * @param Stream body Readable stream - * @param Object opts Response options - * @return Void - */ -export default class Body { - constructor(body, { - size = 0 - } = {}) { - let boundary = null; - - if (body === null) { - // Body is undefined or null - body = null; - } else if (isURLSearchParameters(body)) { - // Body is a URLSearchParams - body = Buffer.from(body.toString()); - } else if (isBlob(body)) { - // Body is blob - } else if (Buffer.isBuffer(body)) { - // Body is Buffer - } else if (types.isAnyArrayBuffer(body)) { - // Body is ArrayBuffer - body = Buffer.from(body); - } else if (ArrayBuffer.isView(body)) { - // Body is ArrayBufferView - body = Buffer.from(body.buffer, body.byteOffset, body.byteLength); - } else if (body instanceof Stream) { - // Body is stream - } else if (body instanceof FormData) { - // Body is FormData - body = formDataToBlob(body); - boundary = body.type.split('=')[1]; - } else { - // None of the above - // coerce to string then buffer - body = Buffer.from(String(body)); - } - - let stream = body; - - if (Buffer.isBuffer(body)) { - stream = Stream.Readable.from(body); - } else if (isBlob(body)) { - stream = Stream.Readable.from(body.stream()); - } - - this[INTERNALS] = { - body, - stream, - boundary, - disturbed: false, - error: null - }; - this.size = size; - - if (body instanceof Stream) { - body.on('error', error_ => { - const error = error_ instanceof FetchBaseError ? - error_ : - new FetchError(`Invalid response body while trying to fetch ${this.url}: ${error_.message}`, 'system', error_); - this[INTERNALS].error = error; - }); - } - } - - get body() { - return this[INTERNALS].stream; - } - - get bodyUsed() { - return this[INTERNALS].disturbed; - } - - /** - * Decode response as ArrayBuffer - * - * @return Promise - */ - async arrayBuffer() { - const {buffer, byteOffset, byteLength} = await consumeBody(this); - return buffer.slice(byteOffset, byteOffset + byteLength); - } - - async formData() { - const ct = this.headers.get('content-type'); - - if (ct.startsWith('application/x-www-form-urlencoded')) { - const formData = new FormData(); - const parameters = new URLSearchParams(await this.text()); - - for (const [name, value] of parameters) { - formData.append(name, value); - } - - return formData; - } - - const {toFormData} = await import('./utils/multipart-parser.js'); - return toFormData(this.body, ct); - } - - /** - * Return raw response as Blob - * - * @return Promise - */ - async blob() { - const ct = (this.headers && this.headers.get('content-type')) || (this[INTERNALS].body && this[INTERNALS].body.type) || ''; - const buf = await this.arrayBuffer(); - - return new Blob([buf], { - type: ct - }); - } - - /** - * Decode response as json - * - * @return Promise - */ - async json() { - const text = await this.text(); - return JSON.parse(text); - } - - /** - * Decode response as text - * - * @return Promise - */ - async text() { - const buffer = await consumeBody(this); - return new TextDecoder().decode(buffer); - } - - /** - * Decode response as buffer (non-spec api) - * - * @return Promise - */ - buffer() { - return consumeBody(this); - } -} - -Body.prototype.buffer = deprecate(Body.prototype.buffer, 'Please use \'response.arrayBuffer()\' instead of \'response.buffer()\'', 'node-fetch#buffer'); - -// In browsers, all properties are enumerable. -Object.defineProperties(Body.prototype, { - body: {enumerable: true}, - bodyUsed: {enumerable: true}, - arrayBuffer: {enumerable: true}, - blob: {enumerable: true}, - json: {enumerable: true}, - text: {enumerable: true}, - data: {get: deprecate(() => {}, - 'data doesn\'t exist, use json(), text(), arrayBuffer(), or body instead', - 'https://github.com/node-fetch/node-fetch/issues/1000 (response)')} -}); - -/** - * Consume and convert an entire Body to a Buffer. - * - * Ref: https://fetch.spec.whatwg.org/#concept-body-consume-body - * - * @return Promise - */ -async function consumeBody(data) { - if (data[INTERNALS].disturbed) { - throw new TypeError(`body used already for: ${data.url}`); - } - - data[INTERNALS].disturbed = true; - - if (data[INTERNALS].error) { - throw data[INTERNALS].error; - } - - const {body} = data; - - // Body is null - if (body === null) { - return Buffer.alloc(0); - } - - /* c8 ignore next 3 */ - if (!(body instanceof Stream)) { - return Buffer.alloc(0); - } - - // Body is stream - // get ready to actually consume the body - const accum = []; - let accumBytes = 0; - - try { - for await (const chunk of body) { - if (data.size > 0 && accumBytes + chunk.length > data.size) { - const error = new FetchError(`content size at ${data.url} over limit: ${data.size}`, 'max-size'); - body.destroy(error); - throw error; - } - - accumBytes += chunk.length; - accum.push(chunk); - } - } catch (error) { - const error_ = error instanceof FetchBaseError ? error : new FetchError(`Invalid response body while trying to fetch ${data.url}: ${error.message}`, 'system', error); - throw error_; - } - - if (body.readableEnded === true || body._readableState.ended === true) { - try { - if (accum.every(c => typeof c === 'string')) { - return Buffer.from(accum.join('')); - } - - return Buffer.concat(accum, accumBytes); - } catch (error) { - throw new FetchError(`Could not create Buffer from response body for ${data.url}: ${error.message}`, 'system', error); - } - } else { - throw new FetchError(`Premature close of server response while trying to fetch ${data.url}`); - } -} - -/** - * Clone body given Res/Req instance - * - * @param Mixed instance Response or Request instance - * @param String highWaterMark highWaterMark for both PassThrough body streams - * @return Mixed - */ -export const clone = (instance, highWaterMark) => { - let p1; - let p2; - let {body} = instance[INTERNALS]; - - // Don't allow cloning a used body - if (instance.bodyUsed) { - throw new Error('cannot clone body after it is used'); - } - - // Check that body is a stream and not form-data object - // note: we can't clone the form-data object without having it as a dependency - if ((body instanceof Stream) && (typeof body.getBoundary !== 'function')) { - // Tee instance body - p1 = new PassThrough({highWaterMark}); - p2 = new PassThrough({highWaterMark}); - body.pipe(p1); - body.pipe(p2); - // Set instance body to teed body and return the other teed body - instance[INTERNALS].stream = p1; - body = p2; - } - - return body; -}; - -const getNonSpecFormDataBoundary = deprecate( - body => body.getBoundary(), - 'form-data doesn\'t follow the spec and requires special treatment. Use alternative package', - 'https://github.com/node-fetch/node-fetch/issues/1167' -); - -/** - * Performs the operation "extract a `Content-Type` value from |object|" as - * specified in the specification: - * https://fetch.spec.whatwg.org/#concept-bodyinit-extract - * - * This function assumes that instance.body is present. - * - * @param {any} body Any options.body input - * @returns {string | null} - */ -export const extractContentType = (body, request) => { - // Body is null or undefined - if (body === null) { - return null; - } - - // Body is string - if (typeof body === 'string') { - return 'text/plain;charset=UTF-8'; - } - - // Body is a URLSearchParams - if (isURLSearchParameters(body)) { - return 'application/x-www-form-urlencoded;charset=UTF-8'; - } - - // Body is blob - if (isBlob(body)) { - return body.type || null; - } - - // Body is a Buffer (Buffer, ArrayBuffer or ArrayBufferView) - if (Buffer.isBuffer(body) || types.isAnyArrayBuffer(body) || ArrayBuffer.isView(body)) { - return null; - } - - if (body instanceof FormData) { - return `multipart/form-data; boundary=${request[INTERNALS].boundary}`; - } - - // Detect form data input from form-data module - if (body && typeof body.getBoundary === 'function') { - return `multipart/form-data;boundary=${getNonSpecFormDataBoundary(body)}`; - } - - // Body is stream - can't really do much about this - if (body instanceof Stream) { - return null; - } - - // Body constructor defaults other things to string - return 'text/plain;charset=UTF-8'; -}; - -/** - * The Fetch Standard treats this as if "total bytes" is a property on the body. - * For us, we have to explicitly get it with a function. - * - * ref: https://fetch.spec.whatwg.org/#concept-body-total-bytes - * - * @param {any} obj.body Body object from the Body instance. - * @returns {number | null} - */ -export const getTotalBytes = request => { - const {body} = request[INTERNALS]; - - // Body is null or undefined - if (body === null) { - return 0; - } - - // Body is Blob - if (isBlob(body)) { - return body.size; - } - - // Body is Buffer - if (Buffer.isBuffer(body)) { - return body.length; - } - - // Detect form data input from form-data module - if (body && typeof body.getLengthSync === 'function') { - return body.hasKnownLength && body.hasKnownLength() ? body.getLengthSync() : null; - } - - // Body is stream - return null; -}; - -/** - * Write a Body to a Node.js WritableStream (e.g. http.Request) object. - * - * @param {Stream.Writable} dest The stream to write to. - * @param obj.body Body object from the Body instance. - * @returns {Promise} - */ -export const writeToStream = async (dest, {body}) => { - if (body === null) { - // Body is null - dest.end(); - } else { - // Body is stream - await pipeline(body, dest); - } -}; diff --git a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/errors/abort-error.js b/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/errors/abort-error.js deleted file mode 100644 index 0b62f1cd3..000000000 --- a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/errors/abort-error.js +++ /dev/null @@ -1,10 +0,0 @@ -import {FetchBaseError} from './base.js'; - -/** - * AbortError interface for cancelled requests - */ -export class AbortError extends FetchBaseError { - constructor(message, type = 'aborted') { - super(message, type); - } -} diff --git a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/errors/base.js b/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/errors/base.js deleted file mode 100644 index 4e66e1bfb..000000000 --- a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/errors/base.js +++ /dev/null @@ -1,17 +0,0 @@ -export class FetchBaseError extends Error { - constructor(message, type) { - super(message); - // Hide custom error implementation details from end-users - Error.captureStackTrace(this, this.constructor); - - this.type = type; - } - - get name() { - return this.constructor.name; - } - - get [Symbol.toStringTag]() { - return this.constructor.name; - } -} diff --git a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/errors/fetch-error.js b/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/errors/fetch-error.js deleted file mode 100644 index f7ae5cc4a..000000000 --- a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/errors/fetch-error.js +++ /dev/null @@ -1,26 +0,0 @@ - -import {FetchBaseError} from './base.js'; - -/** - * @typedef {{ address?: string, code: string, dest?: string, errno: number, info?: object, message: string, path?: string, port?: number, syscall: string}} SystemError -*/ - -/** - * FetchError interface for operational errors - */ -export class FetchError extends FetchBaseError { - /** - * @param {string} message - Error message for human - * @param {string} [type] - Error type for machine - * @param {SystemError} [systemError] - For Node.js system error - */ - constructor(message, type, systemError) { - super(message, type); - // When err.type is `system`, err.erroredSysCall contains system error and err.code contains system error code - if (systemError) { - // eslint-disable-next-line no-multi-assign - this.code = this.errno = systemError.code; - this.erroredSysCall = systemError.syscall; - } - } -} diff --git a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/headers.js b/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/headers.js deleted file mode 100644 index cd6945580..000000000 --- a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/headers.js +++ /dev/null @@ -1,267 +0,0 @@ -/** - * Headers.js - * - * Headers class offers convenient helpers - */ - -import {types} from 'node:util'; -import http from 'node:http'; - -/* c8 ignore next 9 */ -const validateHeaderName = typeof http.validateHeaderName === 'function' ? - http.validateHeaderName : - name => { - if (!/^[\^`\-\w!#$%&'*+.|~]+$/.test(name)) { - const error = new TypeError(`Header name must be a valid HTTP token [${name}]`); - Object.defineProperty(error, 'code', {value: 'ERR_INVALID_HTTP_TOKEN'}); - throw error; - } - }; - -/* c8 ignore next 9 */ -const validateHeaderValue = typeof http.validateHeaderValue === 'function' ? - http.validateHeaderValue : - (name, value) => { - if (/[^\t\u0020-\u007E\u0080-\u00FF]/.test(value)) { - const error = new TypeError(`Invalid character in header content ["${name}"]`); - Object.defineProperty(error, 'code', {value: 'ERR_INVALID_CHAR'}); - throw error; - } - }; - -/** - * @typedef {Headers | Record | Iterable | Iterable>} HeadersInit - */ - -/** - * This Fetch API interface allows you to perform various actions on HTTP request and response headers. - * These actions include retrieving, setting, adding to, and removing. - * A Headers object has an associated header list, which is initially empty and consists of zero or more name and value pairs. - * You can add to this using methods like append() (see Examples.) - * In all methods of this interface, header names are matched by case-insensitive byte sequence. - * - */ -export default class Headers extends URLSearchParams { - /** - * Headers class - * - * @constructor - * @param {HeadersInit} [init] - Response headers - */ - constructor(init) { - // Validate and normalize init object in [name, value(s)][] - /** @type {string[][]} */ - let result = []; - if (init instanceof Headers) { - const raw = init.raw(); - for (const [name, values] of Object.entries(raw)) { - result.push(...values.map(value => [name, value])); - } - } else if (init == null) { // eslint-disable-line no-eq-null, eqeqeq - // No op - } else if (typeof init === 'object' && !types.isBoxedPrimitive(init)) { - const method = init[Symbol.iterator]; - // eslint-disable-next-line no-eq-null, eqeqeq - if (method == null) { - // Record - result.push(...Object.entries(init)); - } else { - if (typeof method !== 'function') { - throw new TypeError('Header pairs must be iterable'); - } - - // Sequence> - // Note: per spec we have to first exhaust the lists then process them - result = [...init] - .map(pair => { - if ( - typeof pair !== 'object' || types.isBoxedPrimitive(pair) - ) { - throw new TypeError('Each header pair must be an iterable object'); - } - - return [...pair]; - }).map(pair => { - if (pair.length !== 2) { - throw new TypeError('Each header pair must be a name/value tuple'); - } - - return [...pair]; - }); - } - } else { - throw new TypeError('Failed to construct \'Headers\': The provided value is not of type \'(sequence> or record)'); - } - - // Validate and lowercase - result = - result.length > 0 ? - result.map(([name, value]) => { - validateHeaderName(name); - validateHeaderValue(name, String(value)); - return [String(name).toLowerCase(), String(value)]; - }) : - undefined; - - super(result); - - // Returning a Proxy that will lowercase key names, validate parameters and sort keys - // eslint-disable-next-line no-constructor-return - return new Proxy(this, { - get(target, p, receiver) { - switch (p) { - case 'append': - case 'set': - return (name, value) => { - validateHeaderName(name); - validateHeaderValue(name, String(value)); - return URLSearchParams.prototype[p].call( - target, - String(name).toLowerCase(), - String(value) - ); - }; - - case 'delete': - case 'has': - case 'getAll': - return name => { - validateHeaderName(name); - return URLSearchParams.prototype[p].call( - target, - String(name).toLowerCase() - ); - }; - - case 'keys': - return () => { - target.sort(); - return new Set(URLSearchParams.prototype.keys.call(target)).keys(); - }; - - default: - return Reflect.get(target, p, receiver); - } - } - }); - /* c8 ignore next */ - } - - get [Symbol.toStringTag]() { - return this.constructor.name; - } - - toString() { - return Object.prototype.toString.call(this); - } - - get(name) { - const values = this.getAll(name); - if (values.length === 0) { - return null; - } - - let value = values.join(', '); - if (/^content-encoding$/i.test(name)) { - value = value.toLowerCase(); - } - - return value; - } - - forEach(callback, thisArg = undefined) { - for (const name of this.keys()) { - Reflect.apply(callback, thisArg, [this.get(name), name, this]); - } - } - - * values() { - for (const name of this.keys()) { - yield this.get(name); - } - } - - /** - * @type {() => IterableIterator<[string, string]>} - */ - * entries() { - for (const name of this.keys()) { - yield [name, this.get(name)]; - } - } - - [Symbol.iterator]() { - return this.entries(); - } - - /** - * Node-fetch non-spec method - * returning all headers and their values as array - * @returns {Record} - */ - raw() { - return [...this.keys()].reduce((result, key) => { - result[key] = this.getAll(key); - return result; - }, {}); - } - - /** - * For better console.log(headers) and also to convert Headers into Node.js Request compatible format - */ - [Symbol.for('nodejs.util.inspect.custom')]() { - return [...this.keys()].reduce((result, key) => { - const values = this.getAll(key); - // Http.request() only supports string as Host header. - // This hack makes specifying custom Host header possible. - if (key === 'host') { - result[key] = values[0]; - } else { - result[key] = values.length > 1 ? values : values[0]; - } - - return result; - }, {}); - } -} - -/** - * Re-shaping object for Web IDL tests - * Only need to do it for overridden methods - */ -Object.defineProperties( - Headers.prototype, - ['get', 'entries', 'forEach', 'values'].reduce((result, property) => { - result[property] = {enumerable: true}; - return result; - }, {}) -); - -/** - * Create a Headers object from an http.IncomingMessage.rawHeaders, ignoring those that do - * not conform to HTTP grammar productions. - * @param {import('http').IncomingMessage['rawHeaders']} headers - */ -export function fromRawHeaders(headers = []) { - return new Headers( - headers - // Split into pairs - .reduce((result, value, index, array) => { - if (index % 2 === 0) { - result.push(array.slice(index, index + 2)); - } - - return result; - }, []) - .filter(([name, value]) => { - try { - validateHeaderName(name); - validateHeaderValue(name, String(value)); - return true; - } catch { - return false; - } - }) - - ); -} diff --git a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/index.js b/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/index.js deleted file mode 100644 index 7c4aee87b..000000000 --- a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/index.js +++ /dev/null @@ -1,417 +0,0 @@ -/** - * Index.js - * - * a request API compatible with window.fetch - * - * All spec algorithm step numbers are based on https://fetch.spec.whatwg.org/commit-snapshots/ae716822cb3a61843226cd090eefc6589446c1d2/. - */ - -import http from 'node:http'; -import https from 'node:https'; -import zlib from 'node:zlib'; -import Stream, {PassThrough, pipeline as pump} from 'node:stream'; -import {Buffer} from 'node:buffer'; - -import dataUriToBuffer from 'data-uri-to-buffer'; - -import {writeToStream, clone} from './body.js'; -import Response from './response.js'; -import Headers, {fromRawHeaders} from './headers.js'; -import Request, {getNodeRequestOptions} from './request.js'; -import {FetchError} from './errors/fetch-error.js'; -import {AbortError} from './errors/abort-error.js'; -import {isRedirect} from './utils/is-redirect.js'; -import {FormData} from 'formdata-polyfill/esm.min.js'; -import {isDomainOrSubdomain, isSameProtocol} from './utils/is.js'; -import {parseReferrerPolicyFromHeader} from './utils/referrer.js'; -import { - Blob, - File, - fileFromSync, - fileFrom, - blobFromSync, - blobFrom -} from 'fetch-blob/from.js'; - -export {FormData, Headers, Request, Response, FetchError, AbortError, isRedirect}; -export {Blob, File, fileFromSync, fileFrom, blobFromSync, blobFrom}; - -const supportedSchemas = new Set(['data:', 'http:', 'https:']); - -/** - * Fetch function - * - * @param {string | URL | import('./request').default} url - Absolute url or Request instance - * @param {*} [options_] - Fetch options - * @return {Promise} - */ -export default async function fetch(url, options_) { - return new Promise((resolve, reject) => { - // Build request object - const request = new Request(url, options_); - const {parsedURL, options} = getNodeRequestOptions(request); - if (!supportedSchemas.has(parsedURL.protocol)) { - throw new TypeError(`node-fetch cannot load ${url}. URL scheme "${parsedURL.protocol.replace(/:$/, '')}" is not supported.`); - } - - if (parsedURL.protocol === 'data:') { - const data = dataUriToBuffer(request.url); - const response = new Response(data, {headers: {'Content-Type': data.typeFull}}); - resolve(response); - return; - } - - // Wrap http.request into fetch - const send = (parsedURL.protocol === 'https:' ? https : http).request; - const {signal} = request; - let response = null; - - const abort = () => { - const error = new AbortError('The operation was aborted.'); - reject(error); - if (request.body && request.body instanceof Stream.Readable) { - request.body.destroy(error); - } - - if (!response || !response.body) { - return; - } - - response.body.emit('error', error); - }; - - if (signal && signal.aborted) { - abort(); - return; - } - - const abortAndFinalize = () => { - abort(); - finalize(); - }; - - // Send request - const request_ = send(parsedURL.toString(), options); - - if (signal) { - signal.addEventListener('abort', abortAndFinalize); - } - - const finalize = () => { - request_.abort(); - if (signal) { - signal.removeEventListener('abort', abortAndFinalize); - } - }; - - request_.on('error', error => { - reject(new FetchError(`request to ${request.url} failed, reason: ${error.message}`, 'system', error)); - finalize(); - }); - - fixResponseChunkedTransferBadEnding(request_, error => { - if (response && response.body) { - response.body.destroy(error); - } - }); - - /* c8 ignore next 18 */ - if (process.version < 'v14') { - // Before Node.js 14, pipeline() does not fully support async iterators and does not always - // properly handle when the socket close/end events are out of order. - request_.on('socket', s => { - let endedWithEventsCount; - s.prependListener('end', () => { - endedWithEventsCount = s._eventsCount; - }); - s.prependListener('close', hadError => { - // if end happened before close but the socket didn't emit an error, do it now - if (response && endedWithEventsCount < s._eventsCount && !hadError) { - const error = new Error('Premature close'); - error.code = 'ERR_STREAM_PREMATURE_CLOSE'; - response.body.emit('error', error); - } - }); - }); - } - - request_.on('response', response_ => { - request_.setTimeout(0); - const headers = fromRawHeaders(response_.rawHeaders); - - // HTTP fetch step 5 - if (isRedirect(response_.statusCode)) { - // HTTP fetch step 5.2 - const location = headers.get('Location'); - - // HTTP fetch step 5.3 - let locationURL = null; - try { - locationURL = location === null ? null : new URL(location, request.url); - } catch { - // error here can only be invalid URL in Location: header - // do not throw when options.redirect == manual - // let the user extract the errorneous redirect URL - if (request.redirect !== 'manual') { - reject(new FetchError(`uri requested responds with an invalid redirect URL: ${location}`, 'invalid-redirect')); - finalize(); - return; - } - } - - // HTTP fetch step 5.5 - switch (request.redirect) { - case 'error': - reject(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${request.url}`, 'no-redirect')); - finalize(); - return; - case 'manual': - // Nothing to do - break; - case 'follow': { - // HTTP-redirect fetch step 2 - if (locationURL === null) { - break; - } - - // HTTP-redirect fetch step 5 - if (request.counter >= request.follow) { - reject(new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect')); - finalize(); - return; - } - - // HTTP-redirect fetch step 6 (counter increment) - // Create a new Request object. - const requestOptions = { - headers: new Headers(request.headers), - follow: request.follow, - counter: request.counter + 1, - agent: request.agent, - compress: request.compress, - method: request.method, - body: clone(request), - signal: request.signal, - size: request.size, - referrer: request.referrer, - referrerPolicy: request.referrerPolicy - }; - - // when forwarding sensitive headers like "Authorization", - // "WWW-Authenticate", and "Cookie" to untrusted targets, - // headers will be ignored when following a redirect to a domain - // that is not a subdomain match or exact match of the initial domain. - // For example, a redirect from "foo.com" to either "foo.com" or "sub.foo.com" - // will forward the sensitive headers, but a redirect to "bar.com" will not. - // headers will also be ignored when following a redirect to a domain using - // a different protocol. For example, a redirect from "https://foo.com" to "http://foo.com" - // will not forward the sensitive headers - if (!isDomainOrSubdomain(request.url, locationURL) || !isSameProtocol(request.url, locationURL)) { - for (const name of ['authorization', 'www-authenticate', 'cookie', 'cookie2']) { - requestOptions.headers.delete(name); - } - } - - // HTTP-redirect fetch step 9 - if (response_.statusCode !== 303 && request.body && options_.body instanceof Stream.Readable) { - reject(new FetchError('Cannot follow redirect with body being a readable stream', 'unsupported-redirect')); - finalize(); - return; - } - - // HTTP-redirect fetch step 11 - if (response_.statusCode === 303 || ((response_.statusCode === 301 || response_.statusCode === 302) && request.method === 'POST')) { - requestOptions.method = 'GET'; - requestOptions.body = undefined; - requestOptions.headers.delete('content-length'); - } - - // HTTP-redirect fetch step 14 - const responseReferrerPolicy = parseReferrerPolicyFromHeader(headers); - if (responseReferrerPolicy) { - requestOptions.referrerPolicy = responseReferrerPolicy; - } - - // HTTP-redirect fetch step 15 - resolve(fetch(new Request(locationURL, requestOptions))); - finalize(); - return; - } - - default: - return reject(new TypeError(`Redirect option '${request.redirect}' is not a valid value of RequestRedirect`)); - } - } - - // Prepare response - if (signal) { - response_.once('end', () => { - signal.removeEventListener('abort', abortAndFinalize); - }); - } - - let body = pump(response_, new PassThrough(), error => { - if (error) { - reject(error); - } - }); - // see https://github.com/nodejs/node/pull/29376 - /* c8 ignore next 3 */ - if (process.version < 'v12.10') { - response_.on('aborted', abortAndFinalize); - } - - const responseOptions = { - url: request.url, - status: response_.statusCode, - statusText: response_.statusMessage, - headers, - size: request.size, - counter: request.counter, - highWaterMark: request.highWaterMark - }; - - // HTTP-network fetch step 12.1.1.3 - const codings = headers.get('Content-Encoding'); - - // HTTP-network fetch step 12.1.1.4: handle content codings - - // in following scenarios we ignore compression support - // 1. compression support is disabled - // 2. HEAD request - // 3. no Content-Encoding header - // 4. no content response (204) - // 5. content not modified response (304) - if (!request.compress || request.method === 'HEAD' || codings === null || response_.statusCode === 204 || response_.statusCode === 304) { - response = new Response(body, responseOptions); - resolve(response); - return; - } - - // For Node v6+ - // Be less strict when decoding compressed responses, since sometimes - // servers send slightly invalid responses that are still accepted - // by common browsers. - // Always using Z_SYNC_FLUSH is what cURL does. - const zlibOptions = { - flush: zlib.Z_SYNC_FLUSH, - finishFlush: zlib.Z_SYNC_FLUSH - }; - - // For gzip - if (codings === 'gzip' || codings === 'x-gzip') { - body = pump(body, zlib.createGunzip(zlibOptions), error => { - if (error) { - reject(error); - } - }); - response = new Response(body, responseOptions); - resolve(response); - return; - } - - // For deflate - if (codings === 'deflate' || codings === 'x-deflate') { - // Handle the infamous raw deflate response from old servers - // a hack for old IIS and Apache servers - const raw = pump(response_, new PassThrough(), error => { - if (error) { - reject(error); - } - }); - raw.once('data', chunk => { - // See http://stackoverflow.com/questions/37519828 - if ((chunk[0] & 0x0F) === 0x08) { - body = pump(body, zlib.createInflate(), error => { - if (error) { - reject(error); - } - }); - } else { - body = pump(body, zlib.createInflateRaw(), error => { - if (error) { - reject(error); - } - }); - } - - response = new Response(body, responseOptions); - resolve(response); - }); - raw.once('end', () => { - // Some old IIS servers return zero-length OK deflate responses, so - // 'data' is never emitted. See https://github.com/node-fetch/node-fetch/pull/903 - if (!response) { - response = new Response(body, responseOptions); - resolve(response); - } - }); - return; - } - - // For br - if (codings === 'br') { - body = pump(body, zlib.createBrotliDecompress(), error => { - if (error) { - reject(error); - } - }); - response = new Response(body, responseOptions); - resolve(response); - return; - } - - // Otherwise, use response as-is - response = new Response(body, responseOptions); - resolve(response); - }); - - // eslint-disable-next-line promise/prefer-await-to-then - writeToStream(request_, request).catch(reject); - }); -} - -function fixResponseChunkedTransferBadEnding(request, errorCallback) { - const LAST_CHUNK = Buffer.from('0\r\n\r\n'); - - let isChunkedTransfer = false; - let properLastChunkReceived = false; - let previousChunk; - - request.on('response', response => { - const {headers} = response; - isChunkedTransfer = headers['transfer-encoding'] === 'chunked' && !headers['content-length']; - }); - - request.on('socket', socket => { - const onSocketClose = () => { - if (isChunkedTransfer && !properLastChunkReceived) { - const error = new Error('Premature close'); - error.code = 'ERR_STREAM_PREMATURE_CLOSE'; - errorCallback(error); - } - }; - - const onData = buf => { - properLastChunkReceived = Buffer.compare(buf.slice(-5), LAST_CHUNK) === 0; - - // Sometimes final 0-length chunk and end of message code are in separate packets - if (!properLastChunkReceived && previousChunk) { - properLastChunkReceived = ( - Buffer.compare(previousChunk.slice(-3), LAST_CHUNK.slice(0, 3)) === 0 && - Buffer.compare(buf.slice(-2), LAST_CHUNK.slice(3)) === 0 - ); - } - - previousChunk = buf; - }; - - socket.prependListener('close', onSocketClose); - socket.on('data', onData); - - request.on('close', () => { - socket.removeListener('close', onSocketClose); - socket.removeListener('data', onData); - }); - }); -} diff --git a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/request.js b/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/request.js deleted file mode 100644 index 7a1a954fe..000000000 --- a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/request.js +++ /dev/null @@ -1,317 +0,0 @@ -/** - * Request.js - * - * Request class contains server only options - * - * All spec algorithm step numbers are based on https://fetch.spec.whatwg.org/commit-snapshots/ae716822cb3a61843226cd090eefc6589446c1d2/. - */ - -import {format as formatUrl} from 'node:url'; -import {deprecate} from 'node:util'; -import Headers from './headers.js'; -import Body, {clone, extractContentType, getTotalBytes} from './body.js'; -import {isAbortSignal} from './utils/is.js'; -import {getSearch} from './utils/get-search.js'; -import { - validateReferrerPolicy, determineRequestsReferrer, DEFAULT_REFERRER_POLICY -} from './utils/referrer.js'; - -const INTERNALS = Symbol('Request internals'); - -/** - * Check if `obj` is an instance of Request. - * - * @param {*} object - * @return {boolean} - */ -const isRequest = object => { - return ( - typeof object === 'object' && - typeof object[INTERNALS] === 'object' - ); -}; - -const doBadDataWarn = deprecate(() => {}, - '.data is not a valid RequestInit property, use .body instead', - 'https://github.com/node-fetch/node-fetch/issues/1000 (request)'); - -/** - * Request class - * - * Ref: https://fetch.spec.whatwg.org/#request-class - * - * @param Mixed input Url or Request instance - * @param Object init Custom options - * @return Void - */ -export default class Request extends Body { - constructor(input, init = {}) { - let parsedURL; - - // Normalize input and force URL to be encoded as UTF-8 (https://github.com/node-fetch/node-fetch/issues/245) - if (isRequest(input)) { - parsedURL = new URL(input.url); - } else { - parsedURL = new URL(input); - input = {}; - } - - if (parsedURL.username !== '' || parsedURL.password !== '') { - throw new TypeError(`${parsedURL} is an url with embedded credentials.`); - } - - let method = init.method || input.method || 'GET'; - if (/^(delete|get|head|options|post|put)$/i.test(method)) { - method = method.toUpperCase(); - } - - if (!isRequest(init) && 'data' in init) { - doBadDataWarn(); - } - - // eslint-disable-next-line no-eq-null, eqeqeq - if ((init.body != null || (isRequest(input) && input.body !== null)) && - (method === 'GET' || method === 'HEAD')) { - throw new TypeError('Request with GET/HEAD method cannot have body'); - } - - const inputBody = init.body ? - init.body : - (isRequest(input) && input.body !== null ? - clone(input) : - null); - - super(inputBody, { - size: init.size || input.size || 0 - }); - - const headers = new Headers(init.headers || input.headers || {}); - - if (inputBody !== null && !headers.has('Content-Type')) { - const contentType = extractContentType(inputBody, this); - if (contentType) { - headers.set('Content-Type', contentType); - } - } - - let signal = isRequest(input) ? - input.signal : - null; - if ('signal' in init) { - signal = init.signal; - } - - // eslint-disable-next-line no-eq-null, eqeqeq - if (signal != null && !isAbortSignal(signal)) { - throw new TypeError('Expected signal to be an instanceof AbortSignal or EventTarget'); - } - - // §5.4, Request constructor steps, step 15.1 - // eslint-disable-next-line no-eq-null, eqeqeq - let referrer = init.referrer == null ? input.referrer : init.referrer; - if (referrer === '') { - // §5.4, Request constructor steps, step 15.2 - referrer = 'no-referrer'; - } else if (referrer) { - // §5.4, Request constructor steps, step 15.3.1, 15.3.2 - const parsedReferrer = new URL(referrer); - // §5.4, Request constructor steps, step 15.3.3, 15.3.4 - referrer = /^about:(\/\/)?client$/.test(parsedReferrer) ? 'client' : parsedReferrer; - } else { - referrer = undefined; - } - - this[INTERNALS] = { - method, - redirect: init.redirect || input.redirect || 'follow', - headers, - parsedURL, - signal, - referrer - }; - - // Node-fetch-only options - this.follow = init.follow === undefined ? (input.follow === undefined ? 20 : input.follow) : init.follow; - this.compress = init.compress === undefined ? (input.compress === undefined ? true : input.compress) : init.compress; - this.counter = init.counter || input.counter || 0; - this.agent = init.agent || input.agent; - this.highWaterMark = init.highWaterMark || input.highWaterMark || 16384; - this.insecureHTTPParser = init.insecureHTTPParser || input.insecureHTTPParser || false; - - // §5.4, Request constructor steps, step 16. - // Default is empty string per https://fetch.spec.whatwg.org/#concept-request-referrer-policy - this.referrerPolicy = init.referrerPolicy || input.referrerPolicy || ''; - } - - /** @returns {string} */ - get method() { - return this[INTERNALS].method; - } - - /** @returns {string} */ - get url() { - return formatUrl(this[INTERNALS].parsedURL); - } - - /** @returns {Headers} */ - get headers() { - return this[INTERNALS].headers; - } - - get redirect() { - return this[INTERNALS].redirect; - } - - /** @returns {AbortSignal} */ - get signal() { - return this[INTERNALS].signal; - } - - // https://fetch.spec.whatwg.org/#dom-request-referrer - get referrer() { - if (this[INTERNALS].referrer === 'no-referrer') { - return ''; - } - - if (this[INTERNALS].referrer === 'client') { - return 'about:client'; - } - - if (this[INTERNALS].referrer) { - return this[INTERNALS].referrer.toString(); - } - - return undefined; - } - - get referrerPolicy() { - return this[INTERNALS].referrerPolicy; - } - - set referrerPolicy(referrerPolicy) { - this[INTERNALS].referrerPolicy = validateReferrerPolicy(referrerPolicy); - } - - /** - * Clone this request - * - * @return Request - */ - clone() { - return new Request(this); - } - - get [Symbol.toStringTag]() { - return 'Request'; - } -} - -Object.defineProperties(Request.prototype, { - method: {enumerable: true}, - url: {enumerable: true}, - headers: {enumerable: true}, - redirect: {enumerable: true}, - clone: {enumerable: true}, - signal: {enumerable: true}, - referrer: {enumerable: true}, - referrerPolicy: {enumerable: true} -}); - -/** - * Convert a Request to Node.js http request options. - * - * @param {Request} request - A Request instance - * @return The options object to be passed to http.request - */ -export const getNodeRequestOptions = request => { - const {parsedURL} = request[INTERNALS]; - const headers = new Headers(request[INTERNALS].headers); - - // Fetch step 1.3 - if (!headers.has('Accept')) { - headers.set('Accept', '*/*'); - } - - // HTTP-network-or-cache fetch steps 2.4-2.7 - let contentLengthValue = null; - if (request.body === null && /^(post|put)$/i.test(request.method)) { - contentLengthValue = '0'; - } - - if (request.body !== null) { - const totalBytes = getTotalBytes(request); - // Set Content-Length if totalBytes is a number (that is not NaN) - if (typeof totalBytes === 'number' && !Number.isNaN(totalBytes)) { - contentLengthValue = String(totalBytes); - } - } - - if (contentLengthValue) { - headers.set('Content-Length', contentLengthValue); - } - - // 4.1. Main fetch, step 2.6 - // > If request's referrer policy is the empty string, then set request's referrer policy to the - // > default referrer policy. - if (request.referrerPolicy === '') { - request.referrerPolicy = DEFAULT_REFERRER_POLICY; - } - - // 4.1. Main fetch, step 2.7 - // > If request's referrer is not "no-referrer", set request's referrer to the result of invoking - // > determine request's referrer. - if (request.referrer && request.referrer !== 'no-referrer') { - request[INTERNALS].referrer = determineRequestsReferrer(request); - } else { - request[INTERNALS].referrer = 'no-referrer'; - } - - // 4.5. HTTP-network-or-cache fetch, step 6.9 - // > If httpRequest's referrer is a URL, then append `Referer`/httpRequest's referrer, serialized - // > and isomorphic encoded, to httpRequest's header list. - if (request[INTERNALS].referrer instanceof URL) { - headers.set('Referer', request.referrer); - } - - // HTTP-network-or-cache fetch step 2.11 - if (!headers.has('User-Agent')) { - headers.set('User-Agent', 'node-fetch'); - } - - // HTTP-network-or-cache fetch step 2.15 - if (request.compress && !headers.has('Accept-Encoding')) { - headers.set('Accept-Encoding', 'gzip, deflate, br'); - } - - let {agent} = request; - if (typeof agent === 'function') { - agent = agent(parsedURL); - } - - if (!headers.has('Connection') && !agent) { - headers.set('Connection', 'close'); - } - - // HTTP-network fetch step 4.2 - // chunked encoding is handled by Node.js - - const search = getSearch(parsedURL); - - // Pass the full URL directly to request(), but overwrite the following - // options: - const options = { - // Overwrite search to retain trailing ? (issue #776) - path: parsedURL.pathname + search, - // The following options are not expressed in the URL - method: request.method, - headers: headers[Symbol.for('nodejs.util.inspect.custom')](), - insecureHTTPParser: request.insecureHTTPParser, - agent - }; - - return { - /** @type {URL} */ - parsedURL, - options - }; -}; diff --git a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/response.js b/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/response.js deleted file mode 100644 index 9806c0cba..000000000 --- a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/response.js +++ /dev/null @@ -1,160 +0,0 @@ -/** - * Response.js - * - * Response class provides content decoding - */ - -import Headers from './headers.js'; -import Body, {clone, extractContentType} from './body.js'; -import {isRedirect} from './utils/is-redirect.js'; - -const INTERNALS = Symbol('Response internals'); - -/** - * Response class - * - * Ref: https://fetch.spec.whatwg.org/#response-class - * - * @param Stream body Readable stream - * @param Object opts Response options - * @return Void - */ -export default class Response extends Body { - constructor(body = null, options = {}) { - super(body, options); - - // eslint-disable-next-line no-eq-null, eqeqeq, no-negated-condition - const status = options.status != null ? options.status : 200; - - const headers = new Headers(options.headers); - - if (body !== null && !headers.has('Content-Type')) { - const contentType = extractContentType(body, this); - if (contentType) { - headers.append('Content-Type', contentType); - } - } - - this[INTERNALS] = { - type: 'default', - url: options.url, - status, - statusText: options.statusText || '', - headers, - counter: options.counter, - highWaterMark: options.highWaterMark - }; - } - - get type() { - return this[INTERNALS].type; - } - - get url() { - return this[INTERNALS].url || ''; - } - - get status() { - return this[INTERNALS].status; - } - - /** - * Convenience property representing if the request ended normally - */ - get ok() { - return this[INTERNALS].status >= 200 && this[INTERNALS].status < 300; - } - - get redirected() { - return this[INTERNALS].counter > 0; - } - - get statusText() { - return this[INTERNALS].statusText; - } - - get headers() { - return this[INTERNALS].headers; - } - - get highWaterMark() { - return this[INTERNALS].highWaterMark; - } - - /** - * Clone this response - * - * @return Response - */ - clone() { - return new Response(clone(this, this.highWaterMark), { - type: this.type, - url: this.url, - status: this.status, - statusText: this.statusText, - headers: this.headers, - ok: this.ok, - redirected: this.redirected, - size: this.size, - highWaterMark: this.highWaterMark - }); - } - - /** - * @param {string} url The URL that the new response is to originate from. - * @param {number} status An optional status code for the response (e.g., 302.) - * @returns {Response} A Response object. - */ - static redirect(url, status = 302) { - if (!isRedirect(status)) { - throw new RangeError('Failed to execute "redirect" on "response": Invalid status code'); - } - - return new Response(null, { - headers: { - location: new URL(url).toString() - }, - status - }); - } - - static error() { - const response = new Response(null, {status: 0, statusText: ''}); - response[INTERNALS].type = 'error'; - return response; - } - - static json(data = undefined, init = {}) { - const body = JSON.stringify(data); - - if (body === undefined) { - throw new TypeError('data is not JSON serializable'); - } - - const headers = new Headers(init && init.headers); - - if (!headers.has('content-type')) { - headers.set('content-type', 'application/json'); - } - - return new Response(body, { - ...init, - headers - }); - } - - get [Symbol.toStringTag]() { - return 'Response'; - } -} - -Object.defineProperties(Response.prototype, { - type: {enumerable: true}, - url: {enumerable: true}, - status: {enumerable: true}, - ok: {enumerable: true}, - redirected: {enumerable: true}, - statusText: {enumerable: true}, - headers: {enumerable: true}, - clone: {enumerable: true} -}); diff --git a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/utils/get-search.js b/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/utils/get-search.js deleted file mode 100644 index d067e7c7f..000000000 --- a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/utils/get-search.js +++ /dev/null @@ -1,9 +0,0 @@ -export const getSearch = parsedURL => { - if (parsedURL.search) { - return parsedURL.search; - } - - const lastOffset = parsedURL.href.length - 1; - const hash = parsedURL.hash || (parsedURL.href[lastOffset] === '#' ? '#' : ''); - return parsedURL.href[lastOffset - hash.length] === '?' ? '?' : ''; -}; diff --git a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/utils/is-redirect.js b/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/utils/is-redirect.js deleted file mode 100644 index d1347f005..000000000 --- a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/utils/is-redirect.js +++ /dev/null @@ -1,11 +0,0 @@ -const redirectStatus = new Set([301, 302, 303, 307, 308]); - -/** - * Redirect code matching - * - * @param {number} code - Status code - * @return {boolean} - */ -export const isRedirect = code => { - return redirectStatus.has(code); -}; diff --git a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/utils/is.js b/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/utils/is.js deleted file mode 100644 index f9e467e45..000000000 --- a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/utils/is.js +++ /dev/null @@ -1,87 +0,0 @@ -/** - * Is.js - * - * Object type checks. - */ - -const NAME = Symbol.toStringTag; - -/** - * Check if `obj` is a URLSearchParams object - * ref: https://github.com/node-fetch/node-fetch/issues/296#issuecomment-307598143 - * @param {*} object - Object to check for - * @return {boolean} - */ -export const isURLSearchParameters = object => { - return ( - typeof object === 'object' && - typeof object.append === 'function' && - typeof object.delete === 'function' && - typeof object.get === 'function' && - typeof object.getAll === 'function' && - typeof object.has === 'function' && - typeof object.set === 'function' && - typeof object.sort === 'function' && - object[NAME] === 'URLSearchParams' - ); -}; - -/** - * Check if `object` is a W3C `Blob` object (which `File` inherits from) - * @param {*} object - Object to check for - * @return {boolean} - */ -export const isBlob = object => { - return ( - object && - typeof object === 'object' && - typeof object.arrayBuffer === 'function' && - typeof object.type === 'string' && - typeof object.stream === 'function' && - typeof object.constructor === 'function' && - /^(Blob|File)$/.test(object[NAME]) - ); -}; - -/** - * Check if `obj` is an instance of AbortSignal. - * @param {*} object - Object to check for - * @return {boolean} - */ -export const isAbortSignal = object => { - return ( - typeof object === 'object' && ( - object[NAME] === 'AbortSignal' || - object[NAME] === 'EventTarget' - ) - ); -}; - -/** - * isDomainOrSubdomain reports whether sub is a subdomain (or exact match) of - * the parent domain. - * - * Both domains must already be in canonical form. - * @param {string|URL} original - * @param {string|URL} destination - */ -export const isDomainOrSubdomain = (destination, original) => { - const orig = new URL(original).hostname; - const dest = new URL(destination).hostname; - - return orig === dest || orig.endsWith(`.${dest}`); -}; - -/** - * isSameProtocol reports whether the two provided URLs use the same protocol. - * - * Both domains must already be in canonical form. - * @param {string|URL} original - * @param {string|URL} destination - */ -export const isSameProtocol = (destination, original) => { - const orig = new URL(original).protocol; - const dest = new URL(destination).protocol; - - return orig === dest; -}; diff --git a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/utils/multipart-parser.js b/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/utils/multipart-parser.js deleted file mode 100644 index 5ad06f98e..000000000 --- a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/utils/multipart-parser.js +++ /dev/null @@ -1,432 +0,0 @@ -import {File} from 'fetch-blob/from.js'; -import {FormData} from 'formdata-polyfill/esm.min.js'; - -let s = 0; -const S = { - START_BOUNDARY: s++, - HEADER_FIELD_START: s++, - HEADER_FIELD: s++, - HEADER_VALUE_START: s++, - HEADER_VALUE: s++, - HEADER_VALUE_ALMOST_DONE: s++, - HEADERS_ALMOST_DONE: s++, - PART_DATA_START: s++, - PART_DATA: s++, - END: s++ -}; - -let f = 1; -const F = { - PART_BOUNDARY: f, - LAST_BOUNDARY: f *= 2 -}; - -const LF = 10; -const CR = 13; -const SPACE = 32; -const HYPHEN = 45; -const COLON = 58; -const A = 97; -const Z = 122; - -const lower = c => c | 0x20; - -const noop = () => {}; - -class MultipartParser { - /** - * @param {string} boundary - */ - constructor(boundary) { - this.index = 0; - this.flags = 0; - - this.onHeaderEnd = noop; - this.onHeaderField = noop; - this.onHeadersEnd = noop; - this.onHeaderValue = noop; - this.onPartBegin = noop; - this.onPartData = noop; - this.onPartEnd = noop; - - this.boundaryChars = {}; - - boundary = '\r\n--' + boundary; - const ui8a = new Uint8Array(boundary.length); - for (let i = 0; i < boundary.length; i++) { - ui8a[i] = boundary.charCodeAt(i); - this.boundaryChars[ui8a[i]] = true; - } - - this.boundary = ui8a; - this.lookbehind = new Uint8Array(this.boundary.length + 8); - this.state = S.START_BOUNDARY; - } - - /** - * @param {Uint8Array} data - */ - write(data) { - let i = 0; - const length_ = data.length; - let previousIndex = this.index; - let {lookbehind, boundary, boundaryChars, index, state, flags} = this; - const boundaryLength = this.boundary.length; - const boundaryEnd = boundaryLength - 1; - const bufferLength = data.length; - let c; - let cl; - - const mark = name => { - this[name + 'Mark'] = i; - }; - - const clear = name => { - delete this[name + 'Mark']; - }; - - const callback = (callbackSymbol, start, end, ui8a) => { - if (start === undefined || start !== end) { - this[callbackSymbol](ui8a && ui8a.subarray(start, end)); - } - }; - - const dataCallback = (name, clear) => { - const markSymbol = name + 'Mark'; - if (!(markSymbol in this)) { - return; - } - - if (clear) { - callback(name, this[markSymbol], i, data); - delete this[markSymbol]; - } else { - callback(name, this[markSymbol], data.length, data); - this[markSymbol] = 0; - } - }; - - for (i = 0; i < length_; i++) { - c = data[i]; - - switch (state) { - case S.START_BOUNDARY: - if (index === boundary.length - 2) { - if (c === HYPHEN) { - flags |= F.LAST_BOUNDARY; - } else if (c !== CR) { - return; - } - - index++; - break; - } else if (index - 1 === boundary.length - 2) { - if (flags & F.LAST_BOUNDARY && c === HYPHEN) { - state = S.END; - flags = 0; - } else if (!(flags & F.LAST_BOUNDARY) && c === LF) { - index = 0; - callback('onPartBegin'); - state = S.HEADER_FIELD_START; - } else { - return; - } - - break; - } - - if (c !== boundary[index + 2]) { - index = -2; - } - - if (c === boundary[index + 2]) { - index++; - } - - break; - case S.HEADER_FIELD_START: - state = S.HEADER_FIELD; - mark('onHeaderField'); - index = 0; - // falls through - case S.HEADER_FIELD: - if (c === CR) { - clear('onHeaderField'); - state = S.HEADERS_ALMOST_DONE; - break; - } - - index++; - if (c === HYPHEN) { - break; - } - - if (c === COLON) { - if (index === 1) { - // empty header field - return; - } - - dataCallback('onHeaderField', true); - state = S.HEADER_VALUE_START; - break; - } - - cl = lower(c); - if (cl < A || cl > Z) { - return; - } - - break; - case S.HEADER_VALUE_START: - if (c === SPACE) { - break; - } - - mark('onHeaderValue'); - state = S.HEADER_VALUE; - // falls through - case S.HEADER_VALUE: - if (c === CR) { - dataCallback('onHeaderValue', true); - callback('onHeaderEnd'); - state = S.HEADER_VALUE_ALMOST_DONE; - } - - break; - case S.HEADER_VALUE_ALMOST_DONE: - if (c !== LF) { - return; - } - - state = S.HEADER_FIELD_START; - break; - case S.HEADERS_ALMOST_DONE: - if (c !== LF) { - return; - } - - callback('onHeadersEnd'); - state = S.PART_DATA_START; - break; - case S.PART_DATA_START: - state = S.PART_DATA; - mark('onPartData'); - // falls through - case S.PART_DATA: - previousIndex = index; - - if (index === 0) { - // boyer-moore derrived algorithm to safely skip non-boundary data - i += boundaryEnd; - while (i < bufferLength && !(data[i] in boundaryChars)) { - i += boundaryLength; - } - - i -= boundaryEnd; - c = data[i]; - } - - if (index < boundary.length) { - if (boundary[index] === c) { - if (index === 0) { - dataCallback('onPartData', true); - } - - index++; - } else { - index = 0; - } - } else if (index === boundary.length) { - index++; - if (c === CR) { - // CR = part boundary - flags |= F.PART_BOUNDARY; - } else if (c === HYPHEN) { - // HYPHEN = end boundary - flags |= F.LAST_BOUNDARY; - } else { - index = 0; - } - } else if (index - 1 === boundary.length) { - if (flags & F.PART_BOUNDARY) { - index = 0; - if (c === LF) { - // unset the PART_BOUNDARY flag - flags &= ~F.PART_BOUNDARY; - callback('onPartEnd'); - callback('onPartBegin'); - state = S.HEADER_FIELD_START; - break; - } - } else if (flags & F.LAST_BOUNDARY) { - if (c === HYPHEN) { - callback('onPartEnd'); - state = S.END; - flags = 0; - } else { - index = 0; - } - } else { - index = 0; - } - } - - if (index > 0) { - // when matching a possible boundary, keep a lookbehind reference - // in case it turns out to be a false lead - lookbehind[index - 1] = c; - } else if (previousIndex > 0) { - // if our boundary turned out to be rubbish, the captured lookbehind - // belongs to partData - const _lookbehind = new Uint8Array(lookbehind.buffer, lookbehind.byteOffset, lookbehind.byteLength); - callback('onPartData', 0, previousIndex, _lookbehind); - previousIndex = 0; - mark('onPartData'); - - // reconsider the current character even so it interrupted the sequence - // it could be the beginning of a new sequence - i--; - } - - break; - case S.END: - break; - default: - throw new Error(`Unexpected state entered: ${state}`); - } - } - - dataCallback('onHeaderField'); - dataCallback('onHeaderValue'); - dataCallback('onPartData'); - - // Update properties for the next call - this.index = index; - this.state = state; - this.flags = flags; - } - - end() { - if ((this.state === S.HEADER_FIELD_START && this.index === 0) || - (this.state === S.PART_DATA && this.index === this.boundary.length)) { - this.onPartEnd(); - } else if (this.state !== S.END) { - throw new Error('MultipartParser.end(): stream ended unexpectedly'); - } - } -} - -function _fileName(headerValue) { - // matches either a quoted-string or a token (RFC 2616 section 19.5.1) - const m = headerValue.match(/\bfilename=("(.*?)"|([^()<>@,;:\\"/[\]?={}\s\t]+))($|;\s)/i); - if (!m) { - return; - } - - const match = m[2] || m[3] || ''; - let filename = match.slice(match.lastIndexOf('\\') + 1); - filename = filename.replace(/%22/g, '"'); - filename = filename.replace(/&#(\d{4});/g, (m, code) => { - return String.fromCharCode(code); - }); - return filename; -} - -export async function toFormData(Body, ct) { - if (!/multipart/i.test(ct)) { - throw new TypeError('Failed to fetch'); - } - - const m = ct.match(/boundary=(?:"([^"]+)"|([^;]+))/i); - - if (!m) { - throw new TypeError('no or bad content-type header, no multipart boundary'); - } - - const parser = new MultipartParser(m[1] || m[2]); - - let headerField; - let headerValue; - let entryValue; - let entryName; - let contentType; - let filename; - const entryChunks = []; - const formData = new FormData(); - - const onPartData = ui8a => { - entryValue += decoder.decode(ui8a, {stream: true}); - }; - - const appendToFile = ui8a => { - entryChunks.push(ui8a); - }; - - const appendFileToFormData = () => { - const file = new File(entryChunks, filename, {type: contentType}); - formData.append(entryName, file); - }; - - const appendEntryToFormData = () => { - formData.append(entryName, entryValue); - }; - - const decoder = new TextDecoder('utf-8'); - decoder.decode(); - - parser.onPartBegin = function () { - parser.onPartData = onPartData; - parser.onPartEnd = appendEntryToFormData; - - headerField = ''; - headerValue = ''; - entryValue = ''; - entryName = ''; - contentType = ''; - filename = null; - entryChunks.length = 0; - }; - - parser.onHeaderField = function (ui8a) { - headerField += decoder.decode(ui8a, {stream: true}); - }; - - parser.onHeaderValue = function (ui8a) { - headerValue += decoder.decode(ui8a, {stream: true}); - }; - - parser.onHeaderEnd = function () { - headerValue += decoder.decode(); - headerField = headerField.toLowerCase(); - - if (headerField === 'content-disposition') { - // matches either a quoted-string or a token (RFC 2616 section 19.5.1) - const m = headerValue.match(/\bname=("([^"]*)"|([^()<>@,;:\\"/[\]?={}\s\t]+))/i); - - if (m) { - entryName = m[2] || m[3] || ''; - } - - filename = _fileName(headerValue); - - if (filename) { - parser.onPartData = appendToFile; - parser.onPartEnd = appendFileToFormData; - } - } else if (headerField === 'content-type') { - contentType = headerValue; - } - - headerValue = ''; - headerField = ''; - }; - - for await (const chunk of Body) { - parser.write(chunk); - } - - parser.end(); - - return formData; -} diff --git a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/utils/referrer.js b/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/utils/referrer.js deleted file mode 100644 index 6741f2fcc..000000000 --- a/node_modules/@foo-software/lighthouse-check/node_modules/node-fetch/src/utils/referrer.js +++ /dev/null @@ -1,340 +0,0 @@ -import {isIP} from 'node:net'; - -/** - * @external URL - * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/URL|URL} - */ - -/** - * @module utils/referrer - * @private - */ - -/** - * @see {@link https://w3c.github.io/webappsec-referrer-policy/#strip-url|Referrer Policy §8.4. Strip url for use as a referrer} - * @param {string} URL - * @param {boolean} [originOnly=false] - */ -export function stripURLForUseAsAReferrer(url, originOnly = false) { - // 1. If url is null, return no referrer. - if (url == null) { // eslint-disable-line no-eq-null, eqeqeq - return 'no-referrer'; - } - - url = new URL(url); - - // 2. If url's scheme is a local scheme, then return no referrer. - if (/^(about|blob|data):$/.test(url.protocol)) { - return 'no-referrer'; - } - - // 3. Set url's username to the empty string. - url.username = ''; - - // 4. Set url's password to null. - // Note: `null` appears to be a mistake as this actually results in the password being `"null"`. - url.password = ''; - - // 5. Set url's fragment to null. - // Note: `null` appears to be a mistake as this actually results in the fragment being `"#null"`. - url.hash = ''; - - // 6. If the origin-only flag is true, then: - if (originOnly) { - // 6.1. Set url's path to null. - // Note: `null` appears to be a mistake as this actually results in the path being `"/null"`. - url.pathname = ''; - - // 6.2. Set url's query to null. - // Note: `null` appears to be a mistake as this actually results in the query being `"?null"`. - url.search = ''; - } - - // 7. Return url. - return url; -} - -/** - * @see {@link https://w3c.github.io/webappsec-referrer-policy/#enumdef-referrerpolicy|enum ReferrerPolicy} - */ -export const ReferrerPolicy = new Set([ - '', - 'no-referrer', - 'no-referrer-when-downgrade', - 'same-origin', - 'origin', - 'strict-origin', - 'origin-when-cross-origin', - 'strict-origin-when-cross-origin', - 'unsafe-url' -]); - -/** - * @see {@link https://w3c.github.io/webappsec-referrer-policy/#default-referrer-policy|default referrer policy} - */ -export const DEFAULT_REFERRER_POLICY = 'strict-origin-when-cross-origin'; - -/** - * @see {@link https://w3c.github.io/webappsec-referrer-policy/#referrer-policies|Referrer Policy §3. Referrer Policies} - * @param {string} referrerPolicy - * @returns {string} referrerPolicy - */ -export function validateReferrerPolicy(referrerPolicy) { - if (!ReferrerPolicy.has(referrerPolicy)) { - throw new TypeError(`Invalid referrerPolicy: ${referrerPolicy}`); - } - - return referrerPolicy; -} - -/** - * @see {@link https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy|Referrer Policy §3.2. Is origin potentially trustworthy?} - * @param {external:URL} url - * @returns `true`: "Potentially Trustworthy", `false`: "Not Trustworthy" - */ -export function isOriginPotentiallyTrustworthy(url) { - // 1. If origin is an opaque origin, return "Not Trustworthy". - // Not applicable - - // 2. Assert: origin is a tuple origin. - // Not for implementations - - // 3. If origin's scheme is either "https" or "wss", return "Potentially Trustworthy". - if (/^(http|ws)s:$/.test(url.protocol)) { - return true; - } - - // 4. If origin's host component matches one of the CIDR notations 127.0.0.0/8 or ::1/128 [RFC4632], return "Potentially Trustworthy". - const hostIp = url.host.replace(/(^\[)|(]$)/g, ''); - const hostIPVersion = isIP(hostIp); - - if (hostIPVersion === 4 && /^127\./.test(hostIp)) { - return true; - } - - if (hostIPVersion === 6 && /^(((0+:){7})|(::(0+:){0,6}))0*1$/.test(hostIp)) { - return true; - } - - // 5. If origin's host component is "localhost" or falls within ".localhost", and the user agent conforms to the name resolution rules in [let-localhost-be-localhost], return "Potentially Trustworthy". - // We are returning FALSE here because we cannot ensure conformance to - // let-localhost-be-loalhost (https://tools.ietf.org/html/draft-west-let-localhost-be-localhost) - if (url.host === 'localhost' || url.host.endsWith('.localhost')) { - return false; - } - - // 6. If origin's scheme component is file, return "Potentially Trustworthy". - if (url.protocol === 'file:') { - return true; - } - - // 7. If origin's scheme component is one which the user agent considers to be authenticated, return "Potentially Trustworthy". - // Not supported - - // 8. If origin has been configured as a trustworthy origin, return "Potentially Trustworthy". - // Not supported - - // 9. Return "Not Trustworthy". - return false; -} - -/** - * @see {@link https://w3c.github.io/webappsec-secure-contexts/#is-url-trustworthy|Referrer Policy §3.3. Is url potentially trustworthy?} - * @param {external:URL} url - * @returns `true`: "Potentially Trustworthy", `false`: "Not Trustworthy" - */ -export function isUrlPotentiallyTrustworthy(url) { - // 1. If url is "about:blank" or "about:srcdoc", return "Potentially Trustworthy". - if (/^about:(blank|srcdoc)$/.test(url)) { - return true; - } - - // 2. If url's scheme is "data", return "Potentially Trustworthy". - if (url.protocol === 'data:') { - return true; - } - - // Note: The origin of blob: and filesystem: URLs is the origin of the context in which they were - // created. Therefore, blobs created in a trustworthy origin will themselves be potentially - // trustworthy. - if (/^(blob|filesystem):$/.test(url.protocol)) { - return true; - } - - // 3. Return the result of executing §3.2 Is origin potentially trustworthy? on url's origin. - return isOriginPotentiallyTrustworthy(url); -} - -/** - * Modifies the referrerURL to enforce any extra security policy considerations. - * @see {@link https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer|Referrer Policy §8.3. Determine request's Referrer}, step 7 - * @callback module:utils/referrer~referrerURLCallback - * @param {external:URL} referrerURL - * @returns {external:URL} modified referrerURL - */ - -/** - * Modifies the referrerOrigin to enforce any extra security policy considerations. - * @see {@link https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer|Referrer Policy §8.3. Determine request's Referrer}, step 7 - * @callback module:utils/referrer~referrerOriginCallback - * @param {external:URL} referrerOrigin - * @returns {external:URL} modified referrerOrigin - */ - -/** - * @see {@link https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer|Referrer Policy §8.3. Determine request's Referrer} - * @param {Request} request - * @param {object} o - * @param {module:utils/referrer~referrerURLCallback} o.referrerURLCallback - * @param {module:utils/referrer~referrerOriginCallback} o.referrerOriginCallback - * @returns {external:URL} Request's referrer - */ -export function determineRequestsReferrer(request, {referrerURLCallback, referrerOriginCallback} = {}) { - // There are 2 notes in the specification about invalid pre-conditions. We return null, here, for - // these cases: - // > Note: If request's referrer is "no-referrer", Fetch will not call into this algorithm. - // > Note: If request's referrer policy is the empty string, Fetch will not call into this - // > algorithm. - if (request.referrer === 'no-referrer' || request.referrerPolicy === '') { - return null; - } - - // 1. Let policy be request's associated referrer policy. - const policy = request.referrerPolicy; - - // 2. Let environment be request's client. - // not applicable to node.js - - // 3. Switch on request's referrer: - if (request.referrer === 'about:client') { - return 'no-referrer'; - } - - // "a URL": Let referrerSource be request's referrer. - const referrerSource = request.referrer; - - // 4. Let request's referrerURL be the result of stripping referrerSource for use as a referrer. - let referrerURL = stripURLForUseAsAReferrer(referrerSource); - - // 5. Let referrerOrigin be the result of stripping referrerSource for use as a referrer, with the - // origin-only flag set to true. - let referrerOrigin = stripURLForUseAsAReferrer(referrerSource, true); - - // 6. If the result of serializing referrerURL is a string whose length is greater than 4096, set - // referrerURL to referrerOrigin. - if (referrerURL.toString().length > 4096) { - referrerURL = referrerOrigin; - } - - // 7. The user agent MAY alter referrerURL or referrerOrigin at this point to enforce arbitrary - // policy considerations in the interests of minimizing data leakage. For example, the user - // agent could strip the URL down to an origin, modify its host, replace it with an empty - // string, etc. - if (referrerURLCallback) { - referrerURL = referrerURLCallback(referrerURL); - } - - if (referrerOriginCallback) { - referrerOrigin = referrerOriginCallback(referrerOrigin); - } - - // 8.Execute the statements corresponding to the value of policy: - const currentURL = new URL(request.url); - - switch (policy) { - case 'no-referrer': - return 'no-referrer'; - - case 'origin': - return referrerOrigin; - - case 'unsafe-url': - return referrerURL; - - case 'strict-origin': - // 1. If referrerURL is a potentially trustworthy URL and request's current URL is not a - // potentially trustworthy URL, then return no referrer. - if (isUrlPotentiallyTrustworthy(referrerURL) && !isUrlPotentiallyTrustworthy(currentURL)) { - return 'no-referrer'; - } - - // 2. Return referrerOrigin. - return referrerOrigin.toString(); - - case 'strict-origin-when-cross-origin': - // 1. If the origin of referrerURL and the origin of request's current URL are the same, then - // return referrerURL. - if (referrerURL.origin === currentURL.origin) { - return referrerURL; - } - - // 2. If referrerURL is a potentially trustworthy URL and request's current URL is not a - // potentially trustworthy URL, then return no referrer. - if (isUrlPotentiallyTrustworthy(referrerURL) && !isUrlPotentiallyTrustworthy(currentURL)) { - return 'no-referrer'; - } - - // 3. Return referrerOrigin. - return referrerOrigin; - - case 'same-origin': - // 1. If the origin of referrerURL and the origin of request's current URL are the same, then - // return referrerURL. - if (referrerURL.origin === currentURL.origin) { - return referrerURL; - } - - // 2. Return no referrer. - return 'no-referrer'; - - case 'origin-when-cross-origin': - // 1. If the origin of referrerURL and the origin of request's current URL are the same, then - // return referrerURL. - if (referrerURL.origin === currentURL.origin) { - return referrerURL; - } - - // Return referrerOrigin. - return referrerOrigin; - - case 'no-referrer-when-downgrade': - // 1. If referrerURL is a potentially trustworthy URL and request's current URL is not a - // potentially trustworthy URL, then return no referrer. - if (isUrlPotentiallyTrustworthy(referrerURL) && !isUrlPotentiallyTrustworthy(currentURL)) { - return 'no-referrer'; - } - - // 2. Return referrerURL. - return referrerURL; - - default: - throw new TypeError(`Invalid referrerPolicy: ${policy}`); - } -} - -/** - * @see {@link https://w3c.github.io/webappsec-referrer-policy/#parse-referrer-policy-from-header|Referrer Policy §8.1. Parse a referrer policy from a Referrer-Policy header} - * @param {Headers} headers Response headers - * @returns {string} policy - */ -export function parseReferrerPolicyFromHeader(headers) { - // 1. Let policy-tokens be the result of extracting header list values given `Referrer-Policy` - // and response’s header list. - const policyTokens = (headers.get('referrer-policy') || '').split(/[,\s]+/); - - // 2. Let policy be the empty string. - let policy = ''; - - // 3. For each token in policy-tokens, if token is a referrer policy and token is not the empty - // string, then set policy to token. - // Note: This algorithm loops over multiple policy values to allow deployment of new policy - // values with fallbacks for older user agents, as described in § 11.1 Unknown Policy Values. - for (const token of policyTokens) { - if (token && ReferrerPolicy.has(token)) { - policy = token; - } - } - - // 4. Return policy. - return policy; -} diff --git a/node_modules/@foo-software/lighthouse-check/package.json b/node_modules/@foo-software/lighthouse-check/package.json index 208fe229c..4535acf06 100644 --- a/node_modules/@foo-software/lighthouse-check/package.json +++ b/node_modules/@foo-software/lighthouse-check/package.json @@ -1,6 +1,6 @@ { "name": "@foo-software/lighthouse-check", - "version": "8.0.4", + "version": "8.0.6", "description": "An NPM module and CLI for automated Lighthouse audits.", "main": "dist/index.js", "engines": { @@ -49,6 +49,7 @@ "codecov": "codecov", "build": "babel ./src --out-dir dist", "prepare": "npm run clean && npm run build && husky install", + "prettier": "prettier --single-quote --write ./src", "test": "jest" }, "lint-staged": { @@ -64,7 +65,7 @@ "babel-jest": "^29.3.1", "lodash.get": "^4.4.2", "meow": "^11.0.0", - "node-fetch": "^3.3.0", + "node-fetch": "^2.6.7", "ora": "^6.1.2", "table": "^6.8.1" }, @@ -75,6 +76,7 @@ "@babel/plugin-transform-modules-commonjs": "^7.19.6", "@babel/preset-env": "^7.20.2", "@babel/register": "^7.18.9", + "@trivago/prettier-plugin-sort-imports": "^3.4.0", "codecov": "^3.8.3", "husky": "^8.0.2", "jest": "^29.3.1", diff --git a/node_modules/@foo-software/lighthouse-check/src/bin/lighthouse-check-status.js b/node_modules/@foo-software/lighthouse-check/src/bin/lighthouse-check-status.js index 7bd174964..b692b3660 100755 --- a/node_modules/@foo-software/lighthouse-check/src/bin/lighthouse-check-status.js +++ b/node_modules/@foo-software/lighthouse-check/src/bin/lighthouse-check-status.js @@ -1,44 +1,44 @@ #! /usr/bin/env node import ora from 'ora'; -import getHelpText from '../helpers/getHelpText'; -import validateStatus from '../validateStatus'; import { NAME, NAME_STATUS } from '../constants'; -import { convertOptionsFromArguments } from '../helpers/arguments'; import { ERROR_INVALID } from '../errorCodes'; +import { convertOptionsFromArguments } from '../helpers/arguments'; +import getHelpText from '../helpers/getHelpText'; +import validateStatus from '../validateStatus'; const defaultOptions = { minAccessibilityScore: { type: 'number', - value: undefined + value: undefined, }, minBestPracticesScore: { type: 'number', - value: undefined + value: undefined, }, minPerformanceScore: { type: 'number', - value: undefined + value: undefined, }, minProgressiveWebAppScore: { type: 'number', - value: undefined + value: undefined, }, minSeoScore: { type: 'number', - value: undefined + value: undefined, }, help: { type: 'boolean', - value: undefined + value: undefined, }, outputDirectory: { type: 'string', - value: undefined + value: undefined, }, verbose: { type: 'boolean', - value: false - } + value: false, + }, }; // override options with any that are passed in as arguments @@ -68,7 +68,7 @@ const init = async () => { } else { console.log( '❌ Something went wrong while attempting to enqueue URLs for Lighthouse. See the error below.\n\n', - error + error, ); } diff --git a/node_modules/@foo-software/lighthouse-check/src/bin/lighthouse-check.js b/node_modules/@foo-software/lighthouse-check/src/bin/lighthouse-check.js index c2380f548..d281bd8b1 100755 --- a/node_modules/@foo-software/lighthouse-check/src/bin/lighthouse-check.js +++ b/node_modules/@foo-software/lighthouse-check/src/bin/lighthouse-check.js @@ -1,145 +1,145 @@ #! /usr/bin/env node -import ora from 'ora'; import fs from 'fs'; +import ora from 'ora'; import path from 'path'; -import getHelpText from '../helpers/getHelpText'; -import lighthouseCheck from '../lighthouseCheck'; import { NAME } from '../constants'; import { convertOptionsFromArguments } from '../helpers/arguments'; +import getHelpText from '../helpers/getHelpText'; +import lighthouseCheck from '../lighthouseCheck'; const defaultOptions = { author: { type: 'string', - value: undefined + value: undefined, }, apiToken: { type: 'string', - value: undefined + value: undefined, }, awsAccessKeyId: { type: 'string', - value: undefined + value: undefined, }, awsBucket: { type: 'string', - value: undefined + value: undefined, }, awsRegion: { type: 'string', - value: undefined + value: undefined, }, awsSecretAccessKey: { type: 'string', - value: undefined + value: undefined, }, branch: { type: 'string', - value: undefined + value: undefined, }, configFile: { type: 'string', - value: undefined + value: undefined, }, device: { type: 'string', - value: undefined + value: undefined, }, emulatedFormFactor: { type: 'string', - value: undefined + value: undefined, }, extraHeaders: { type: 'object', - value: undefined + value: undefined, }, locale: { type: 'string', - value: undefined + value: undefined, }, help: { type: 'boolean', - value: undefined + value: undefined, }, isGitHubAction: { type: 'boolean', - value: undefined + value: undefined, }, isOrb: { type: 'boolean', - value: undefined + value: undefined, }, maxRetries: { type: 'number', - value: 0 + value: 0, }, maxWaitForLoad: { type: 'number', - value: undefined + value: undefined, }, outputDirectory: { type: 'string', - value: undefined + value: undefined, }, overridesJsonFile: { type: 'string', - value: undefined + value: undefined, }, pr: { type: 'string', - value: undefined + value: undefined, }, prCommentAccessToken: { type: 'string', - value: undefined + value: undefined, }, prCommentEnabled: { type: 'boolean', - value: true + value: true, }, prCommentSaveOld: { type: 'boolean', - value: false + value: false, }, prCommentUrl: { type: 'string', - value: undefined + value: undefined, }, sha: { type: 'string', - value: undefined + value: undefined, }, slackWebhookUrl: { type: 'string', - value: undefined + value: undefined, }, tag: { type: 'string', - value: undefined + value: undefined, }, timeout: { type: 'number', - value: undefined + value: undefined, }, throttling: { type: 'string', - value: undefined + value: undefined, }, throttlingMethod: { type: 'string', - value: undefined + value: undefined, }, urls: { type: 'array', - value: undefined + value: undefined, }, verbose: { type: 'boolean', - value: false + value: false, }, wait: { type: 'boolean', - value: undefined - } + value: undefined, + }, }; // override options with any that are passed in as arguments @@ -157,7 +157,7 @@ const init = async () => { // extend params with config json file contents params = { ...params, - ...configJson + ...configJson, }; } @@ -178,7 +178,7 @@ const init = async () => { console.log( '❌ Something went wrong while attempting to enqueue URLs for Lighthouse. See the error below.\n\n', - error + error, ); console.log('\n'); process.exit(1); diff --git a/node_modules/@foo-software/lighthouse-check/src/fetch.js b/node_modules/@foo-software/lighthouse-check/src/fetch.js index 3a0fbe8d4..54447fca9 100644 --- a/node_modules/@foo-software/lighthouse-check/src/fetch.js +++ b/node_modules/@foo-software/lighthouse-check/src/fetch.js @@ -1,10 +1,6 @@ // this should only be defined when working locally. if (process.env.API_URL) { - process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0; + process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0; } -// https://stackoverflow.com/a/69331469 -const fetch = (...args) => - import("node-fetch").then(({ default: fetch }) => fetch(...args)); - -export default fetch; +export { default } from 'node-fetch'; diff --git a/node_modules/@foo-software/lighthouse-check/src/fetchAndWaitForLighthouseAudits.js b/node_modules/@foo-software/lighthouse-check/src/fetchAndWaitForLighthouseAudits.js index cde2173f1..86be953cc 100644 --- a/node_modules/@foo-software/lighthouse-check/src/fetchAndWaitForLighthouseAudits.js +++ b/node_modules/@foo-software/lighthouse-check/src/fetchAndWaitForLighthouseAudits.js @@ -1,38 +1,38 @@ -import fetchLighthouseAudits from './fetchLighthouseAudits'; import LighthouseCheckError from './LighthouseCheckError'; import { DEFAULT_FETCH_AND_WAIT_TIMEOUT_MINUTES, FETCH_POLL_INTERVAL, FETCH_POLL_INTERVAL_SECONDS, - NAME + NAME, } from './constants'; import { ERROR_NO_RESULTS, ERROR_TIMEOUT } from './errorCodes'; +import fetchLighthouseAudits from './fetchLighthouseAudits'; export default ({ apiToken, queueIds, timeout = DEFAULT_FETCH_AND_WAIT_TIMEOUT_MINUTES, - verbose = true + verbose = true, }) => new Promise((resolve, reject) => { const timeoutMilliseconds = 60000 * timeout; const startTime = Date.now(); let fetchIndex = 0; - const fetchData = interval => + const fetchData = (interval) => setTimeout(async () => { fetchIndex++; if (verbose) { console.log( `${NAME}:`, - `Starting Lighthouse fetch attempt ${fetchIndex}.` + `Starting Lighthouse fetch attempt ${fetchIndex}.`, ); } const result = await fetchLighthouseAudits({ apiToken, - queueIds + queueIds, }); // do we have the expected number of results @@ -57,13 +57,13 @@ export default ({ console.log( `${NAME}:`, 'An unexpected error occurred:\n', - result.error + result.error, ); } reject(result.error); return; } else if (areResultsExpected) { - const audits = result.data.map(current => ({ + const audits = result.data.map((current) => ({ emulatedFormFactor: current.device, id: current.pageId, name: current.name, @@ -75,8 +75,8 @@ export default ({ bestPractices: current.scoreBestPractices, performance: current.scorePerformance, progressiveWebApp: current.scoreProgressiveWebApp, - seo: current.scoreSeo - } + seo: current.scoreSeo, + }, })); resolve(audits); @@ -89,15 +89,15 @@ export default ({ reject( new LighthouseCheckError(errorMessage, { - code: ERROR_TIMEOUT - }) + code: ERROR_TIMEOUT, + }), ); return; } else { if (verbose) { console.log( `${NAME}:`, - `Received ${resultLength} out of ${queueIds.length} results. Trying again in ${FETCH_POLL_INTERVAL_SECONDS} seconds.` + `Received ${resultLength} out of ${queueIds.length} results. Trying again in ${FETCH_POLL_INTERVAL_SECONDS} seconds.`, ); } diff --git a/node_modules/@foo-software/lighthouse-check/src/fetchLighthouseAudits.js b/node_modules/@foo-software/lighthouse-check/src/fetchLighthouseAudits.js index 8e354a48a..e2c85d0a0 100644 --- a/node_modules/@foo-software/lighthouse-check/src/fetchLighthouseAudits.js +++ b/node_modules/@foo-software/lighthouse-check/src/fetchLighthouseAudits.js @@ -1,12 +1,12 @@ import get from 'lodash.get'; -import fetch from './fetch'; import LighthouseCheckError from './LighthouseCheckError'; import { API_LIGHTHOUSE_AUDIT_PATH, API_URL, - SUCCESS_CODE_GENERIC + SUCCESS_CODE_GENERIC, } from './constants'; import { ERROR_GENERIC, ERROR_NO_RESULTS } from './errorCodes'; +import fetch from './fetch'; export default async ({ apiToken, queueIds }) => { try { @@ -16,34 +16,34 @@ export default async ({ apiToken, queueIds }) => { method: 'get', headers: { Authorization: apiToken, - 'Content-Type': 'application/json' - } - } + 'Content-Type': 'application/json', + }, + }, ); const lighthouseAuditsJson = await lighthouseAuditsResponse.json(); if (lighthouseAuditsJson.status >= 400) { throw new LighthouseCheckError('No results found.', { - code: ERROR_NO_RESULTS + code: ERROR_NO_RESULTS, }); } const lighthouseResults = get( lighthouseAuditsJson, 'data.lighthouseaudit', - [] + [], ); // success return { code: SUCCESS_CODE_GENERIC, data: lighthouseResults, - message: 'Lighthouse results successfully fetched.' + message: 'Lighthouse results successfully fetched.', }; } catch (error) { return { code: error.code || ERROR_GENERIC, - error + error, }; } }; diff --git a/node_modules/@foo-software/lighthouse-check/src/helpers/arguments.js b/node_modules/@foo-software/lighthouse-check/src/helpers/arguments.js index 17f5733ed..ad3900d9b 100644 --- a/node_modules/@foo-software/lighthouse-check/src/helpers/arguments.js +++ b/node_modules/@foo-software/lighthouse-check/src/helpers/arguments.js @@ -2,7 +2,7 @@ import meow from 'meow'; // we should note that these values are expected from the command // line and that they're always strings. -export const convertOptionsFromArguments = options => { +export const convertOptionsFromArguments = (options) => { const cli = meow(); return Object.keys(options).reduce((accumulator, current) => { @@ -53,7 +53,7 @@ export const convertOptionsFromArguments = options => { return { ...accumulator, - [current]: value + [current]: value, }; }, {}); }; diff --git a/node_modules/@foo-software/lighthouse-check/src/helpers/arguments.test.js b/node_modules/@foo-software/lighthouse-check/src/helpers/arguments.test.js new file mode 100644 index 000000000..181b48961 --- /dev/null +++ b/node_modules/@foo-software/lighthouse-check/src/helpers/arguments.test.js @@ -0,0 +1,145 @@ +import { convertOptionsFromArguments } from './arguments'; + +describe('convertOptionsFromArguments', () => { + const ARGV = process.argv; + + beforeEach(() => { + // clear the cache + jest.resetModules(); + process.argv = [ + '/usr/local/bin/node', + 'lighthouse-check', + '--verbose', + '--ipsum', + 'lorem', + '--hello', + 'world', + '--foo', + 'bar', + '--some-string', + '--some-array', + ]; + }); + + afterEach(() => { + process.argv = ARGV; + }); + + it('should use default values when arguments are non-existent', () => { + const expected = { + nonexistent: 'lorem', + nonexistent2: false, + }; + const actual = convertOptionsFromArguments({ + nonexistent: { + type: 'string', + value: 'lorem', + }, + nonexistent2: { + type: 'boolean', + value: false, + }, + }); + expect(actual).toEqual(expected); + }); + + it('should override options from arguments', () => { + const expected = { + ipsum: 'lorem', + another: 'one', + hello: 'world', + }; + const actual = convertOptionsFromArguments({ + ipsum: { + type: 'string', + value: 'foobar', + }, + another: { + type: 'string', + value: 'one', + }, + hello: { + type: 'string', + value: 'something', + }, + }); + expect(actual).toEqual(expected); + }); + + it('should treat explicitly defined boolean types as "true" when a value is empty', () => { + const actual = convertOptionsFromArguments({ + verbose: { + type: 'boolean', + }, + }); + expect(actual.verbose).toEqual(true); + }); + + it('should ignore empty flag values that are not explicitly defined as boolean types', () => { + const actual = convertOptionsFromArguments({ + 'some-string': { + type: 'string', + }, + }); + expect(actual['some-string']).toBeUndefined(); + }); + + it('should ignore empty flag values that are explicitly defined as array types', () => { + const actual = convertOptionsFromArguments({ + 'some-array': { + type: 'array', + }, + }); + expect(actual['some-array']).toBeUndefined(); + }); + + it('should create correct types from CLI string argument', () => { + const options = convertOptionsFromArguments({ + myEmptyString: { + type: 'string', + value: '', + }, + myString: { + type: 'string', + value: 'foobar', + }, + myBoolean: { + type: 'boolean', + value: 'true', + }, + myBooleanFalse: { + type: 'boolean', + value: 'false', + }, + myBooleanEmpty: { + type: 'boolean', + value: '', + }, + myNumber: { + type: 'number', + value: '100', + }, + myArray: { + type: 'array', + value: 'one,two', + }, + myObject: { + type: 'object', + value: '{"hello":"world","ipsum":"lorem"}', + }, + }); + + expect(typeof options.myEmptyString).toEqual('undefined'); + expect(options.myString).toEqual('foobar'); + expect(options.myBoolean).toEqual(true); + expect(options.myBooleanFalse).toEqual(false); + + // the CLI argument present with no arguments is interpretted as `true` + expect(options.myBooleanEmpty).toEqual(true); + + expect(options.myNumber).toEqual(100); + expect(options.myArray).toEqual(['one', 'two']); + expect(options.myObject.hello).toEqual('world'); + expect(options.myObject.ipsum).toEqual('lorem'); + }); +}); diff --git a/node_modules/@foo-software/lighthouse-check/src/helpers/getHelpText.js b/node_modules/@foo-software/lighthouse-check/src/helpers/getHelpText.js index fd28869b1..d15df72ab 100644 --- a/node_modules/@foo-software/lighthouse-check/src/helpers/getHelpText.js +++ b/node_modules/@foo-software/lighthouse-check/src/helpers/getHelpText.js @@ -1,4 +1,4 @@ -export default name => ` +export default (name) => ` Usage: ${name} --option See all options on GitHub: https://github.com/foo-software/lighthouse-check-cli#options diff --git a/node_modules/@foo-software/lighthouse-check/src/helpers/getLighthouseAuditTitlesByKey.js b/node_modules/@foo-software/lighthouse-check/src/helpers/getLighthouseAuditTitlesByKey.js index 9f2592a4c..bfa031ddc 100644 --- a/node_modules/@foo-software/lighthouse-check/src/helpers/getLighthouseAuditTitlesByKey.js +++ b/node_modules/@foo-software/lighthouse-check/src/helpers/getLighthouseAuditTitlesByKey.js @@ -1,3 +1,3 @@ import lighthouseAuditTitles from '../lighthouseAuditTitles'; -export default keys => keys.map(current => lighthouseAuditTitles[current]); +export default (keys) => keys.map((current) => lighthouseAuditTitles[current]); diff --git a/node_modules/@foo-software/lighthouse-check/src/helpers/getLighthouseAuditTitlesByKey.test.js b/node_modules/@foo-software/lighthouse-check/src/helpers/getLighthouseAuditTitlesByKey.test.js index 391fadfe7..c6e795ef6 100644 --- a/node_modules/@foo-software/lighthouse-check/src/helpers/getLighthouseAuditTitlesByKey.test.js +++ b/node_modules/@foo-software/lighthouse-check/src/helpers/getLighthouseAuditTitlesByKey.test.js @@ -7,7 +7,7 @@ describe('getLighthouseAuditTitlesByKey', () => { 'Best Practices', 'Performance', 'Progressive Web App', - 'SEO' + 'SEO', ]; const actual = getLighthouseAuditTitlesByKey([ @@ -15,7 +15,7 @@ describe('getLighthouseAuditTitlesByKey', () => { 'bestPractices', 'performance', 'progressiveWebApp', - 'seo' + 'seo', ]); expect(actual).toEqual(expected); diff --git a/node_modules/@foo-software/lighthouse-check/src/index.js b/node_modules/@foo-software/lighthouse-check/src/index.js index d60971282..5d50dd7b3 100644 --- a/node_modules/@foo-software/lighthouse-check/src/index.js +++ b/node_modules/@foo-software/lighthouse-check/src/index.js @@ -1,7 +1,5 @@ export { default as validateStatus } from './validateStatus'; -export { - default as fetchAndWaitForLighthouseAudits -} from './fetchAndWaitForLighthouseAudits'; +export { default as fetchAndWaitForLighthouseAudits } from './fetchAndWaitForLighthouseAudits'; export { default as fetchLighthouseAudits } from './fetchLighthouseAudits'; export { default as lighthouseCheck } from './lighthouseCheck'; export { default as localLighthouse } from './localLighthouse'; diff --git a/node_modules/@foo-software/lighthouse-check/src/lighthouseAuditTitles.js b/node_modules/@foo-software/lighthouse-check/src/lighthouseAuditTitles.js index 1f524cf34..cc0bcc90b 100644 --- a/node_modules/@foo-software/lighthouse-check/src/lighthouseAuditTitles.js +++ b/node_modules/@foo-software/lighthouse-check/src/lighthouseAuditTitles.js @@ -3,5 +3,5 @@ export default { bestPractices: 'Best Practices', performance: 'Performance', progressiveWebApp: 'Progressive Web App', - seo: 'SEO' + seo: 'SEO', }; diff --git a/node_modules/@foo-software/lighthouse-check/src/lighthouseCheck.js b/node_modules/@foo-software/lighthouse-check/src/lighthouseCheck.js index dac95d631..ac40fab03 100644 --- a/node_modules/@foo-software/lighthouse-check/src/lighthouseCheck.js +++ b/node_modules/@foo-software/lighthouse-check/src/lighthouseCheck.js @@ -1,14 +1,14 @@ import path from 'path'; -import fetchAndWaitForLighthouseAudits from './fetchAndWaitForLighthouseAudits'; import LighthouseCheckError from './LighthouseCheckError'; -import triggerLighthouse from './triggerLighthouse'; -import localLighthouse from './localLighthouse'; -import postPrComment from './postPrComment'; -import slackNotify from './slackNotify'; -import writeResults from './helpers/writeResults'; import { NAME, SUCCESS_CODE_GENERIC } from './constants'; import { ERROR_NO_RESULTS, ERROR_RUNTIME } from './errorCodes'; +import fetchAndWaitForLighthouseAudits from './fetchAndWaitForLighthouseAudits'; +import writeResults from './helpers/writeResults'; +import localLighthouse from './localLighthouse'; import logResults from './logResults'; +import postPrComment from './postPrComment'; +import slackNotify from './slackNotify'; +import triggerLighthouse from './triggerLighthouse'; export default ({ apiToken, @@ -48,7 +48,7 @@ export default ({ urls, verbose = true, wait = true, - slackWebhookUrl + slackWebhookUrl, }) => new Promise(async (resolve, reject) => { try { @@ -72,7 +72,7 @@ export default ({ tag, timeout, urls, - verbose + verbose, }); if (triggerResult.error) { @@ -92,9 +92,9 @@ export default ({ const queueIds = triggerResult.data.reduce( (accumulator, current) => [ ...accumulator, - ...(!current.id ? [] : [current.id]) + ...(!current.id ? [] : [current.id]), ], - [] + [], ); // if this condition doesn't pass - we got a problem @@ -107,14 +107,14 @@ export default ({ apiToken, queueIds, timeout, - verbose + verbose, }); // if output directory is specified write the results to disk if (outputDirectoryPath) { writeResults({ outputDirectory: outputDirectoryPath, - results: auditResults + results: auditResults, }); } @@ -126,7 +126,7 @@ export default ({ results: auditResults, sha, slackWebhookUrl, - verbose + verbose, }); } @@ -139,7 +139,7 @@ export default ({ prCommentSaveOld, prCommentUrl, results: auditResults, - verbose + verbose, }); } @@ -147,13 +147,13 @@ export default ({ isGitHubAction, isLocalAudit, isOrb, - results: auditResults + results: auditResults, }); // success resolve({ code: SUCCESS_CODE_GENERIC, - data: auditResults + data: auditResults, }); return; } @@ -166,8 +166,8 @@ export default ({ reject( new LighthouseCheckError(errorMessage, { - code: ERROR_NO_RESULTS - }) + code: ERROR_NO_RESULTS, + }), ); } else { const lighthouseAudits = await localLighthouse({ @@ -186,14 +186,14 @@ export default ({ throttling, throttlingMethod, urls, - verbose + verbose, }); if (!lighthouseAudits.length) { reject( new LighthouseCheckError('Something went wrong - no results.', { - code: ERROR_NO_RESULTS - }) + code: ERROR_NO_RESULTS, + }), ); } else { if (slackWebhookUrl) { @@ -204,7 +204,7 @@ export default ({ results: lighthouseAudits, sha, slackWebhookUrl, - verbose + verbose, }); } @@ -217,7 +217,7 @@ export default ({ prCommentSaveOld, prCommentUrl, results: lighthouseAudits, - verbose + verbose, }); } @@ -225,13 +225,13 @@ export default ({ isGitHubAction, isLocalAudit, isOrb, - results: lighthouseAudits + results: lighthouseAudits, }); // success resolve({ code: SUCCESS_CODE_GENERIC, - data: lighthouseAudits + data: lighthouseAudits, }); } } diff --git a/node_modules/@foo-software/lighthouse-check/src/lighthouseConfig.js b/node_modules/@foo-software/lighthouse-check/src/lighthouseConfig.js index a011e50e9..073eeef62 100644 --- a/node_modules/@foo-software/lighthouse-check/src/lighthouseConfig.js +++ b/node_modules/@foo-software/lighthouse-check/src/lighthouseConfig.js @@ -19,7 +19,7 @@ export const throttling = { requestLatencyMs: 150 * DEVTOOLS_RTT_ADJUSTMENT_FACTOR, downloadThroughputKbps: 1.6 * 1024 * DEVTOOLS_THROUGHPUT_ADJUSTMENT_FACTOR, uploadThroughputKbps: 750 * DEVTOOLS_THROUGHPUT_ADJUSTMENT_FACTOR, - cpuSlowdownMultiplier: 4 + cpuSlowdownMultiplier: 4, }, // These values partially align with WebPageTest's definition of "Regular 3G". // These values are meant to roughly align with Chrome UX report's 3G definition which are based @@ -30,7 +30,7 @@ export const throttling = { requestLatencyMs: 300 * DEVTOOLS_RTT_ADJUSTMENT_FACTOR, downloadThroughputKbps: 700 * DEVTOOLS_THROUGHPUT_ADJUSTMENT_FACTOR, uploadThroughputKbps: 700 * DEVTOOLS_THROUGHPUT_ADJUSTMENT_FACTOR, - cpuSlowdownMultiplier: 4 + cpuSlowdownMultiplier: 4, }, // Using a "broadband" connection type // Corresponds to "Dense 4G 25th percentile" in https://docs.google.com/document/d/1Ft1Bnq9-t4jK5egLSOc28IL4TvR-Tt0se_1faTA4KTY/edit#heading=h.bb7nfy2x9e5v @@ -40,8 +40,8 @@ export const throttling = { cpuSlowdownMultiplier: 1, requestLatencyMs: 0, // 0 means unset downloadThroughputKbps: 0, - uploadThroughputKbps: 0 - } + uploadThroughputKbps: 0, + }, }; /** @@ -55,7 +55,7 @@ const MOTOG4_EMULATION_METRICS = { // our perf recommendations. // https://github.com/GoogleChrome/lighthouse/issues/10741#issuecomment-626903508 deviceScaleFactor: 2.625, - disabled: false + disabled: false, }; /** @@ -67,12 +67,12 @@ const DESKTOP_EMULATION_METRICS = { width: 1350, height: 940, deviceScaleFactor: 1, - disabled: false + disabled: false, }; const screenEmulationMetrics = { mobile: MOTOG4_EMULATION_METRICS, - desktop: DESKTOP_EMULATION_METRICS + desktop: DESKTOP_EMULATION_METRICS, }; // eslint-disable-next-line max-len @@ -84,7 +84,7 @@ const DESKTOP_USERAGENT = const userAgents = { mobile: MOTOG4_USERAGENT, - desktop: DESKTOP_USERAGENT + desktop: DESKTOP_USERAGENT, }; // https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/config/lr-desktop-config.js @@ -98,8 +98,8 @@ export const desktop = { screenEmulation: screenEmulationMetrics.desktop, emulatedUserAgent: userAgents.desktop, // Skip the h2 audit so it doesn't lie to us. See https://github.com/GoogleChrome/lighthouse/issues/6539 - skipAudits: ['uses-http2'] - } + skipAudits: ['uses-http2'], + }, }; // https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/config/lr-mobile-config.js @@ -110,6 +110,6 @@ export const mobile = { maxWaitForLoad: 35 * 1000, // lighthouse:default is mobile by default // Skip the h2 audit so it doesn't lie to us. See https://github.com/GoogleChrome/lighthouse/issues/6539 - skipAudits: ['uses-http2'] - } + skipAudits: ['uses-http2'], + }, }; diff --git a/node_modules/@foo-software/lighthouse-check/src/lighthouseOptions.js b/node_modules/@foo-software/lighthouse-check/src/lighthouseOptions.js index 1cb9e5e14..e1978e2cf 100644 --- a/node_modules/@foo-software/lighthouse-check/src/lighthouseOptions.js +++ b/node_modules/@foo-software/lighthouse-check/src/lighthouseOptions.js @@ -4,11 +4,11 @@ export default { '--disable-gpu', '--headless', '--no-sandbox', - '--ignore-certificate-errors' + '--ignore-certificate-errors', ], ...(!process.env.LOG_LEVEL ? {} : { - logLevel: process.env.LOG_LEVEL - }) + logLevel: process.env.LOG_LEVEL, + }), }; diff --git a/node_modules/@foo-software/lighthouse-check/src/localLighthouse.js b/node_modules/@foo-software/lighthouse-check/src/localLighthouse.js index ba5c9b19c..9e2d7b11b 100644 --- a/node_modules/@foo-software/lighthouse-check/src/localLighthouse.js +++ b/node_modules/@foo-software/lighthouse-check/src/localLighthouse.js @@ -1,25 +1,25 @@ +import lighthousePersist from '@foo-software/lighthouse-persist'; import fs from 'fs'; import get from 'lodash.get'; -import lighthousePersist from '@foo-software/lighthouse-persist'; +import { NAME } from './constants'; +import writeResults from './helpers/writeResults'; import { desktop, mobile, throttling } from './lighthouseConfig'; import options from './lighthouseOptions'; -import writeResults from './helpers/writeResults'; -import { NAME } from './constants'; const defaultLighthouseConfigs = { desktop, - mobile + mobile, }; -const getScoresFromFloat = scores => +const getScoresFromFloat = (scores) => Object.keys(scores).reduce( (accumulator, current) => ({ ...accumulator, ...(typeof scores[current] === 'number' && { - [current]: Math.floor(scores[current] * 100) - }) + [current]: Math.floor(scores[current] * 100), + }), }), - {} + {}, ); export const localLighthouse = async ({ @@ -35,7 +35,7 @@ export const localLighthouse = async ({ overrides, throttling: throttlingParam, throttlingMethod, - url + url, }) => { // if desktop device, and no throttling param specified, use the // appropriate throttling @@ -54,41 +54,41 @@ export const localLighthouse = async ({ ...(!maxWaitForLoad ? {} : { - maxWaitForLoad + maxWaitForLoad, }), ...(!throttlingMethod ? {} : { - throttlingMethod + throttlingMethod, }), ...(!throttlingOverride || !throttling[throttlingOverride] ? {} : { - throttling: throttling[throttlingOverride] + throttling: throttling[throttlingOverride], }), ...(!emulatedFormFactor ? {} : { - emulatedFormFactor + emulatedFormFactor, }), ...(!extraHeaders ? {} : { - extraHeaders + extraHeaders, }), // if we wanted translations (holy!) // locale: 'ja', ...(!locale ? {} : { - locale - }) + locale, + }), }, ...(!overrides || !overrides.config ? {} : { - ...overrides.config - }) + ...overrides.config, + }), }; const { localReport, report, result } = await lighthousePersist({ @@ -102,11 +102,11 @@ export const localLighthouse = async ({ ...(!overrides || !overrides.options ? {} : { - ...overrides.options - }) + ...overrides.options, + }), }, outputDirectory, - url + url, }); const scores = getScoresFromFloat({ @@ -114,7 +114,7 @@ export const localLighthouse = async ({ bestPractices: get(result, 'categories["best-practices"].score'), performance: get(result, 'categories.performance.score'), progressiveWebApp: get(result, 'categories.pwa.score'), - seo: get(result, 'categories.seo.score') + seo: get(result, 'categories.seo.score'), }); return { @@ -123,7 +123,7 @@ export const localLighthouse = async ({ report, emulatedFormFactor, runtimeError: get(result, 'runtimeError.message'), - scores + scores, }; }; @@ -132,7 +132,7 @@ export const getLocalLighthouseResultsWithRetries = async ({ localLighthousePromise = localLighthouse, maxRetries = 0, retries = 0, - verbose = false + verbose = false, }) => { let lighthouseAuditResult; try { @@ -155,12 +155,12 @@ export const getLocalLighthouseResultsWithRetries = async ({ console.log( `${NAME}: Error below caught on retry ${retries} of ${maxRetries}.`, error, - 'Trying again...' + 'Trying again...', ); } else { console.log( `Error caught on retry ${retries} of ${maxRetries}.`, - 'Trying again...' + 'Trying again...', ); } @@ -168,7 +168,7 @@ export const getLocalLighthouseResultsWithRetries = async ({ auditConfig, localLighthousePromise, maxRetries, - retries: retries + 1 + retries: retries + 1, }); } } @@ -189,7 +189,7 @@ export default async ({ throttling, throttlingMethod, urls, - verbose + verbose, }) => { // check for overrides config or options let overrides; @@ -221,7 +221,7 @@ export default async ({ throttling, throttlingMethod, url, - verbose + verbose, }; if (options.emulatedFormFactor !== 'all') { @@ -230,11 +230,11 @@ export default async ({ // establish two audits for all device types auditConfigs.push({ ...options, - emulatedFormFactor: 'desktop' + emulatedFormFactor: 'desktop', }); auditConfigs.push({ ...options, - emulatedFormFactor: 'mobile' + emulatedFormFactor: 'mobile', }); } } @@ -246,14 +246,14 @@ export default async ({ for (const auditConfig of auditConfigs) { if (verbose) { console.log( - `${NAME}: Auditing ${auditConfig.emulatedFormFactor} (${index}/${auditConfigs.length}): ${auditConfig.url}` + `${NAME}: Auditing ${auditConfig.emulatedFormFactor} (${index}/${auditConfigs.length}): ${auditConfig.url}`, ); } const lighthouseAuditResult = await getLocalLighthouseResultsWithRetries({ auditConfig, maxRetries, retries: 0, - verbose + verbose, }); auditResults.push(lighthouseAuditResult); index++; @@ -263,7 +263,7 @@ export default async ({ if (outputDirectory) { writeResults({ outputDirectory, - results: auditResults + results: auditResults, }); } diff --git a/node_modules/@foo-software/lighthouse-check/src/localLighthouse.test.js b/node_modules/@foo-software/lighthouse-check/src/localLighthouse.test.js index 499121fdd..ca6579a06 100644 --- a/node_modules/@foo-software/lighthouse-check/src/localLighthouse.test.js +++ b/node_modules/@foo-software/lighthouse-check/src/localLighthouse.test.js @@ -11,8 +11,8 @@ describe('getLocalLighthouseResultsWithRetries', () => { auditConfig: {}, localLighthousePromise, maxRetries: 3, - retries: 0 - }) + retries: 0, + }), ).rejects.toHaveProperty('message', 'uh ohhhhh'); expect(localLighthousePromise).toHaveBeenCalledTimes(4); @@ -36,8 +36,8 @@ describe('getLocalLighthouseResultsWithRetries', () => { auditConfig: {}, localLighthousePromise, maxRetries: 3, - retries: 0 - }) + retries: 0, + }), ).resolves.toEqual({ data: true }); expect(localLighthousePromise).toHaveBeenCalledTimes(3); @@ -51,8 +51,8 @@ describe('getLocalLighthouseResultsWithRetries', () => { await expect( getLocalLighthouseResultsWithRetries({ auditConfig: {}, - localLighthousePromise - }) + localLighthousePromise, + }), ).resolves.toEqual({ data: true }); expect(localLighthousePromise).toHaveBeenCalledTimes(1); @@ -66,8 +66,8 @@ describe('getLocalLighthouseResultsWithRetries', () => { await expect( getLocalLighthouseResultsWithRetries({ auditConfig: {}, - localLighthousePromise - }) + localLighthousePromise, + }), ).rejects.toHaveProperty('message', 'uh ohhhhh'); expect(localLighthousePromise).toHaveBeenCalledTimes(1); diff --git a/node_modules/@foo-software/lighthouse-check/src/logResults.js b/node_modules/@foo-software/lighthouse-check/src/logResults.js index 463189264..26115befe 100644 --- a/node_modules/@foo-software/lighthouse-check/src/logResults.js +++ b/node_modules/@foo-software/lighthouse-check/src/logResults.js @@ -3,7 +3,7 @@ import getLighthouseAuditTitlesByKey from './helpers/getLighthouseAuditTitlesByK // config for the `table` module (for console logging a table) const tableConfig = { - border: getBorderCharacters('ramac') + border: getBorderCharacters('ramac'), }; export default ({ isGitHubAction, isLocalAudit, isOrb, results }) => { @@ -14,9 +14,9 @@ export default ({ isGitHubAction, isLocalAudit, isOrb, results }) => { columns: { 0: { paddingLeft: 29, - paddingRight: 29 - } - } + paddingRight: 29, + }, + }, }; // log the header @@ -24,7 +24,7 @@ export default ({ isGitHubAction, isLocalAudit, isOrb, results }) => { console.log(table(headerTable, headerTableConfig)); // log results - results.forEach(result => { + results.forEach((result) => { console.log(`URL: ${result.url}`); if (result.emulatedFormFactor) { @@ -41,7 +41,7 @@ export default ({ isGitHubAction, isLocalAudit, isOrb, results }) => { const tableData = [ getLighthouseAuditTitlesByKey(Object.keys(result.scores)), - Object.values(result.scores) + Object.values(result.scores), ]; console.log('\n'); if (result.runtimeError) { @@ -77,7 +77,7 @@ export default ({ isGitHubAction, isLocalAudit, isOrb, results }) => { // plug const plugTable = [[message]]; const plugTableConfig = { - ...tableConfig + ...tableConfig, }; // log the plug diff --git a/node_modules/@foo-software/lighthouse-check/src/postPrComment.js b/node_modules/@foo-software/lighthouse-check/src/postPrComment.js index a2561cf6d..8b85fa937 100644 --- a/node_modules/@foo-software/lighthouse-check/src/postPrComment.js +++ b/node_modules/@foo-software/lighthouse-check/src/postPrComment.js @@ -1,16 +1,16 @@ +import LighthouseCheckError from './LighthouseCheckError'; +import { NAME } from './constants'; +import { ERROR_UNEXPECTED_RESPONSE } from './errorCodes'; import fetch from './fetch'; import getLighthouseScoreColor from './helpers/getLighthouseScoreColor'; import lighthouseAuditTitles from './lighthouseAuditTitles'; -import LighthouseCheckError from './LighthouseCheckError'; -import { ERROR_UNEXPECTED_RESPONSE } from './errorCodes'; -import { NAME } from './constants'; const getBadge = ({ title, score = 0 }) => `![](https://img.shields.io/badge/${title}-${score}-${getLighthouseScoreColor( { isHex: false, - score - } + score, + }, )}?style=flat-square) `; export default async ({ @@ -21,7 +21,7 @@ export default async ({ prCommentSaveOld, prCommentUrl, results, - verbose + verbose, }) => { try { let markdown = ''; @@ -30,16 +30,16 @@ export default async ({ // the wrong one const commentIds = []; - results.forEach(result => { + results.forEach((result) => { commentIds.push( - result.id || `${result.emulatedFormFactor}:${result.url}` + result.id || `${result.emulatedFormFactor}:${result.url}`, ); // badges - Object.keys(result.scores).forEach(current => { + Object.keys(result.scores).forEach((current) => { markdown += getBadge({ title: lighthouseAuditTitles[current].replace(/ /g, '%20'), - score: result.scores[current] + score: result.scores[current], }); }); @@ -91,7 +91,7 @@ export default async ({ // in the future const commentIdentifierPrefix = ''; const commentIdentifier = `\n`; markdown += commentIdentifierPrefix + commentIdentifier; @@ -105,8 +105,8 @@ export default async ({ method: 'get', headers: { 'content-type': 'application/json', - authorization: `token ${prCommentAccessToken}` - } + authorization: `token ${prCommentAccessToken}`, + }, }); const existingCommentsJsonResult = await existingCommentsResult.json(); @@ -114,25 +114,24 @@ export default async ({ Array.isArray(existingCommentsJsonResult) && existingCommentsJsonResult.length ) { - existingComment = existingCommentsJsonResult.find(current => { + existingComment = existingCommentsJsonResult.find((current) => { const hasLighthouseComment = current.body.includes( - commentIdentifierPrefix + commentIdentifierPrefix, ); if (!hasLighthouseComment) { return false; } // check to see if this comment matches the current result set - const [, commentIdsFromExistingCommentString] = current.body.split( - 'COMMENT_ID' - ); + const [, commentIdsFromExistingCommentString] = + current.body.split('COMMENT_ID'); if (!commentIdsFromExistingCommentString) { return false; } const commentIdsFromExistingComment = JSON.parse( - commentIdsFromExistingCommentString + commentIdsFromExistingCommentString, ); // if one has more results than the other then we are definitely different @@ -164,14 +163,14 @@ export default async ({ ...(shouldUpdate ? {} : { - event: 'COMMENT' + event: 'COMMENT', }), - body: markdown + body: markdown, }), headers: { 'content-type': 'application/json', - authorization: `token ${prCommentAccessToken}` - } + authorization: `token ${prCommentAccessToken}`, + }, }); const jsonResult = await result.json(); @@ -180,8 +179,8 @@ export default async ({ jsonResult.message || 'something went wrong', { code: ERROR_UNEXPECTED_RESPONSE, - data: jsonResult - } + data: jsonResult, + }, ); } } catch (error) { diff --git a/node_modules/@foo-software/lighthouse-check/src/slackNotify.js b/node_modules/@foo-software/lighthouse-check/src/slackNotify.js index 7a63a721b..d3d234060 100644 --- a/node_modules/@foo-software/lighthouse-check/src/slackNotify.js +++ b/node_modules/@foo-software/lighthouse-check/src/slackNotify.js @@ -1,7 +1,7 @@ import { IncomingWebhook } from '@slack/webhook'; +import { NAME } from './constants'; import getLighthouseScoreColor from './helpers/getLighthouseScoreColor'; import lighthouseAuditTitles from './lighthouseAuditTitles'; -import { NAME } from './constants'; export default async ({ author, @@ -10,7 +10,7 @@ export default async ({ results, sha, slackWebhookUrl, - verbose + verbose, }) => { try { const webhook = new IncomingWebhook(slackWebhookUrl); @@ -51,8 +51,8 @@ export default async ({ ...(!footer ? {} : { - footer - }) + footer, + }), }, ...(!result.runtimeError ? [] @@ -60,18 +60,18 @@ export default async ({ { color: '#f74531', text: `*Lighthouse runtime error*: ${result.runtimeError}`, - short: true - } + short: true, + }, ]), - ...Object.keys(result.scores).map(current => ({ + ...Object.keys(result.scores).map((current) => ({ color: getLighthouseScoreColor({ isHex: true, - score: result.scores[current] + score: result.scores[current], }), text: `*${lighthouseAuditTitles[current]}*: ${result.scores[current]}`, - short: true - })) - ] + short: true, + })), + ], }); } } catch (error) { diff --git a/node_modules/@foo-software/lighthouse-check/src/triggerLighthouse.test.js b/node_modules/@foo-software/lighthouse-check/src/triggerLighthouse.test.js index eac26a843..74dc388a3 100644 --- a/node_modules/@foo-software/lighthouse-check/src/triggerLighthouse.test.js +++ b/node_modules/@foo-software/lighthouse-check/src/triggerLighthouse.test.js @@ -3,14 +3,14 @@ import triggerLighthouse from './triggerLighthouse'; const mockResponse = { status: 200, - data: {} + data: {}, }; const mockPageResponse = { ...mockResponse, data: { - page: [] - } + page: [], + }, }; const mockFetchPagesResponse = { @@ -20,25 +20,25 @@ const mockFetchPagesResponse = { page: [ { _id: 'abc', - apiToken: 'abc123' + apiToken: 'abc123', }, { _id: 'def', - apiToken: 'def456' - } - ] - } - }) + apiToken: 'def456', + }, + ], + }, + }), }; const mockFetchPagesEmptyResponse = { - json: () => mockPageResponse + json: () => mockPageResponse, }; const mockFetchPagesUnauthorizedResponse = { json: () => ({ - status: 401 - }) + status: 401, + }), }; const mockQueueItemsResponse = { @@ -46,15 +46,15 @@ const mockQueueItemsResponse = { data: { queue: { results: [], - errors: 0 - } - } + errors: 0, + }, + }, }; const mockFetchQueueItemsEmptyResponse = { json: () => ({ - ...mockQueueItemsResponse - }) + ...mockQueueItemsResponse, + }), }; const mockFetchQueueItemsSuccessResponse = { @@ -66,16 +66,16 @@ const mockFetchQueueItemsSuccessResponse = { results: [ { code: 'SUCCESS_QUEUE_ADD', - status: 200 + status: 200, }, { code: 'SUCCESS_QUEUE_ADD', - status: 200 - } - ] - } - } - }) + status: 200, + }, + ], + }, + }, + }), }; const mockFetchQueueItemsFailResponse = { @@ -88,18 +88,18 @@ const mockFetchQueueItemsFailResponse = { { code: 'SOME_ERROR', message: 'some error message', - status: 401 + status: 401, }, { code: 'SOME_ERROR', message: 'some error message', - status: 401 - } + status: 401, + }, ], - errors: 2 - } - } - }) + errors: 2, + }, + }, + }), }; const mockFetchQueueItemsFailMaxReachedResponse = { @@ -112,18 +112,18 @@ const mockFetchQueueItemsFailMaxReachedResponse = { { code: 'ERROR_QUEUE_MAX_USED_DAY', message: 'Max limit of 5 triggers reached.', - status: 401 + status: 401, }, { code: 'ERROR_QUEUE_MAX_USED_DAY', message: 'Max limit of 5 triggers reached.', - status: 401 - } + status: 401, + }, ], - errors: 2 - } - } - }) + errors: 2, + }, + }, + }), }; const mockFetchQueueItemsMixedResponse = { @@ -136,31 +136,31 @@ const mockFetchQueueItemsMixedResponse = { { code: 'ERROR_QUEUE_MAX_USED_DAY', message: 'Max limit of 5 triggers reached.', - status: 401 + status: 401, }, { code: 'ERROR_QUEUE_MAX_USED_DAY', message: 'Max limit of 5 triggers reached.', - status: 401 + status: 401, }, { code: 'SUCCESS_QUEUE_ADD', - status: 200 - } + status: 200, + }, ], - errors: 2 - } - } - }) + errors: 2, + }, + }, + }), }; const mockParams = { - apiToken: 'abc123' + apiToken: 'abc123', }; jest.mock('node-fetch', () => ({ __esModule: true, - default: jest.fn() + default: jest.fn(), })); describe('triggerLighthouse()', () => { diff --git a/node_modules/@foo-software/lighthouse-check/src/validateStatus.js b/node_modules/@foo-software/lighthouse-check/src/validateStatus.js index 41a16d592..316e31a3d 100644 --- a/node_modules/@foo-software/lighthouse-check/src/validateStatus.js +++ b/node_modules/@foo-software/lighthouse-check/src/validateStatus.js @@ -12,7 +12,7 @@ const getScoreFailMessage = ({ name, url, minScore, score }) => { if (Number(score) < Number(minScore)) { return [ - `${url}: ${name}: minimum score: ${minScore}, actual score: ${score}` + `${url}: ${name}: minimum score: ${minScore}, actual score: ${score}`, ]; } @@ -25,7 +25,7 @@ const getFailureMessages = ({ minPerformanceScore, minProgressiveWebAppScore, minSeoScore, - results + results, }) => results.reduce( (accumulator, current) => [ @@ -34,34 +34,34 @@ const getFailureMessages = ({ name: 'Accessibility', minScore: minAccessibilityScore, score: current.scores.accessibility, - ...current + ...current, }), ...getScoreFailMessage({ name: 'Best Practices', minScore: minBestPracticesScore, score: current.scores.bestPractices, - ...current + ...current, }), ...getScoreFailMessage({ name: 'Performance', minScore: minPerformanceScore, score: current.scores.performance, - ...current + ...current, }), ...getScoreFailMessage({ name: 'Progressive Web App', minScore: minProgressiveWebAppScore, score: current.scores.progressiveWebApp, - ...current + ...current, }), ...getScoreFailMessage({ name: 'SEO', minScore: minSeoScore, score: current.scores.seo, - ...current - }) + ...current, + }), ], - [] + [], ); export default async ({ @@ -72,7 +72,7 @@ export default async ({ minSeoScore, outputDirectory, results, - verbose + verbose, }) => { let resultsJson = results; @@ -89,7 +89,7 @@ export default async ({ minPerformanceScore, minProgressiveWebAppScore, minSeoScore, - results: resultsJson + results: resultsJson, }); // if we have scores that were below the minimum requirement @@ -99,8 +99,8 @@ export default async ({ throw new LighthouseCheckError( `Minimum score requirements failed:\n${failureMessage}`, { - code: ERROR_INVALID - } + code: ERROR_INVALID, + }, ); } diff --git a/package-lock.json b/package-lock.json index 85d430e89..7bf63c27e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@actions/core": "^1.10.0", "@actions/github": "^5.1.1", - "@foo-software/lighthouse-check": "^8.0.4", + "@foo-software/lighthouse-check": "^8.0.6", "express": "^4.18.2", "lodash.get": "^4.4.2" }, @@ -673,16 +673,16 @@ } }, "node_modules/@foo-software/lighthouse-check": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/@foo-software/lighthouse-check/-/lighthouse-check-8.0.4.tgz", - "integrity": "sha512-3v5dX3QxnG2LaHuVs4+t73Ksq4C52iRyeWDyO/t4oTBmdb/ttZK/CClad1tttY3Kf1SGvXK615T7VIfOcfEFMw==", + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/@foo-software/lighthouse-check/-/lighthouse-check-8.0.6.tgz", + "integrity": "sha512-SBG5Qu1C8BzbLHoIIqs9kWS1lOBk2ZlxZ7vlK73sy2LzXqO5mOhF4tKsMcH6/0RoQQklPqRTAbzjFjM4WDaUqA==", "dependencies": { "@foo-software/lighthouse-persist": "^6.2.0", "@slack/webhook": "^6.1.0", "babel-jest": "^29.3.1", "lodash.get": "^4.4.2", "meow": "^11.0.0", - "node-fetch": "^3.3.0", + "node-fetch": "^2.6.7", "ora": "^6.1.2", "table": "^6.8.1" }, @@ -694,23 +694,6 @@ "node": ">= 16.0.0" } }, - "node_modules/@foo-software/lighthouse-check/node_modules/node-fetch": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.0.tgz", - "integrity": "sha512-BKwRP/O0UvoMKp7GNdwPlObhYGB5DQqwhEDQlNKuoqwVYSxkSZCSbHjnFFmUEtwSKRPU4kNK8PbDYYitwaE3QA==", - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, "node_modules/@foo-software/lighthouse-persist": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/@foo-software/lighthouse-persist/-/lighthouse-persist-6.2.0.tgz", @@ -8773,30 +8756,18 @@ } }, "@foo-software/lighthouse-check": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/@foo-software/lighthouse-check/-/lighthouse-check-8.0.4.tgz", - "integrity": "sha512-3v5dX3QxnG2LaHuVs4+t73Ksq4C52iRyeWDyO/t4oTBmdb/ttZK/CClad1tttY3Kf1SGvXK615T7VIfOcfEFMw==", + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/@foo-software/lighthouse-check/-/lighthouse-check-8.0.6.tgz", + "integrity": "sha512-SBG5Qu1C8BzbLHoIIqs9kWS1lOBk2ZlxZ7vlK73sy2LzXqO5mOhF4tKsMcH6/0RoQQklPqRTAbzjFjM4WDaUqA==", "requires": { "@foo-software/lighthouse-persist": "^6.2.0", "@slack/webhook": "^6.1.0", "babel-jest": "^29.3.1", "lodash.get": "^4.4.2", "meow": "^11.0.0", - "node-fetch": "^3.3.0", + "node-fetch": "^2.6.7", "ora": "^6.1.2", "table": "^6.8.1" - }, - "dependencies": { - "node-fetch": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.0.tgz", - "integrity": "sha512-BKwRP/O0UvoMKp7GNdwPlObhYGB5DQqwhEDQlNKuoqwVYSxkSZCSbHjnFFmUEtwSKRPU4kNK8PbDYYitwaE3QA==", - "requires": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - } - } } }, "@foo-software/lighthouse-persist": { diff --git a/package.json b/package.json index beaf5e5ec..3192f0281 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "dependencies": { "@actions/core": "^1.10.0", "@actions/github": "^5.1.1", - "@foo-software/lighthouse-check": "^8.0.4", + "@foo-software/lighthouse-check": "^8.0.6", "express": "^4.18.2", "lodash.get": "^4.4.2" },