diff --git a/.github/actions/close-bot/package-lock.json b/.github/actions/close-bot/package-lock.json index c1e05e66f2972..34ef713632344 100644 --- a/.github/actions/close-bot/package-lock.json +++ b/.github/actions/close-bot/package-lock.json @@ -9,14 +9,17 @@ "version": "0.0.0", "license": "CC0", "dependencies": { - "@actions/core": "^1.5.0", + "@actions/core": "^1.6.0", "@actions/github": "^5.0.0" } }, "node_modules/@actions/core": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.5.0.tgz", - "integrity": "sha512-eDOLH1Nq9zh+PJlYLqEMkS/jLQxhksPNmUGNBHfa4G+tQmnIhzpctxmchETtVGyBOvXgOVVpYuE40+eS4cUnwQ==" + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.6.0.tgz", + "integrity": "sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw==", + "dependencies": { + "@actions/http-client": "^1.0.11" + } }, "node_modules/@actions/github": { "version": "5.0.0", @@ -193,9 +196,12 @@ }, "dependencies": { "@actions/core": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.5.0.tgz", - "integrity": "sha512-eDOLH1Nq9zh+PJlYLqEMkS/jLQxhksPNmUGNBHfa4G+tQmnIhzpctxmchETtVGyBOvXgOVVpYuE40+eS4cUnwQ==" + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.6.0.tgz", + "integrity": "sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw==", + "requires": { + "@actions/http-client": "^1.0.11" + } }, "@actions/github": { "version": "5.0.0", diff --git a/.github/actions/close-bot/package.json b/.github/actions/close-bot/package.json index 08c30824f4865..b5e864ca4af25 100644 --- a/.github/actions/close-bot/package.json +++ b/.github/actions/close-bot/package.json @@ -10,7 +10,7 @@ "author": "chris48s", "license": "CC0", "dependencies": { - "@actions/core": "^1.5.0", + "@actions/core": "^1.6.0", "@actions/github": "^5.0.0" } } diff --git a/CHANGELOG.md b/CHANGELOG.md index 68cf5e1e5ad80..ade4f92711595 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,20 @@ Note: this changelog is for the shields.io server. The changelog for the badge-m --- +## server-2021-10-04 + +- feat: add 2021 support to GitHub Hacktoberfest [#7086](https://github.com/badges/shields/issues/7086) +- Add [ClearlyDefined] service [#6944](https://github.com/badges/shields/issues/6944) +- handle null licenses in crates.io response schema, run [crates] [#7074](https://github.com/badges/shields/issues/7074) +- [OBS] add Open Build Service service-badge [#6993](https://github.com/badges/shields/issues/6993) +- Correction of badges url in self-hosting configuration with a custom port. Issue 7025 [#7036](https://github.com/badges/shields/issues/7036) +- fix: support gitlab token via env var [#7023](https://github.com/badges/shields/issues/7023) +- Add API-based support for [GitLab] badges, add new GitLab Tag badge [#6988](https://github.com/badges/shields/issues/6988) +- [freecodecamp]: allow + symbol in username [#7016](https://github.com/badges/shields/issues/7016) +- Rename Riot to Element in Matrix badge help [#6996](https://github.com/badges/shields/issues/6996) +- Fixed Reddit Negative Karma Issue [#6992](https://github.com/badges/shields/issues/6992) +- Dependency updates + ## server-2021-09-01 - use multi-stage build to reduce size of docker images [#6938](https://github.com/badges/shields/issues/6938) diff --git a/config/custom-environment-variables.yml b/config/custom-environment-variables.yml index 3afe51a5450b5..2b3081f2ae2d8 100644 --- a/config/custom-environment-variables.yml +++ b/config/custom-environment-variables.yml @@ -93,7 +93,6 @@ private: obs_pass: 'OBS_PASS' redis_url: 'REDIS_URL' sentry_dsn: 'SENTRY_DSN' - shields_secret: 'SHIELDS_SECRET' sl_insight_userUuid: 'SL_INSIGHT_USER_UUID' sl_insight_apiToken: 'SL_INSIGHT_API_TOKEN' sonarqube_token: 'SONARQUBE_TOKEN' diff --git a/core/base-service/base.js b/core/base-service/base.js index a547814ea4166..566d12867803b 100644 --- a/core/base-service/base.js +++ b/core/base-service/base.js @@ -20,7 +20,7 @@ import { Deprecated, } from './errors.js' import { validateExample, transformExample } from './examples.js' -import { fetchFactory } from './got.js' +import { sendRequest } from './node-fetch.js' import { makeFullUrl, assertValidRoute, @@ -432,7 +432,7 @@ class BaseService { ServiceClass: this, }) - const fetcher = fetchFactory(fetchLimitBytes) + const fetcher = sendRequest.bind(sendRequest, fetchLimitBytes) camp.route( regex, diff --git a/core/base-service/base.spec.js b/core/base-service/base.spec.js index ac58c86598203..09dd6e814e19b 100644 --- a/core/base-service/base.spec.js +++ b/core/base-service/base.spec.js @@ -124,15 +124,11 @@ describe('BaseService', function () { }) describe('Logging', function () { - let sandbox beforeEach(function () { - sandbox = sinon.createSandbox() + sinon.stub(trace, 'logTrace') }) afterEach(function () { - sandbox.restore() - }) - beforeEach(function () { - sandbox.stub(trace, 'logTrace') + sinon.restore() }) it('Invokes the logger as expected', async function () { await DummyService.invoke( @@ -426,15 +422,11 @@ describe('BaseService', function () { }) describe('request', function () { - let sandbox beforeEach(function () { - sandbox = sinon.createSandbox() + sinon.stub(trace, 'logTrace') }) afterEach(function () { - sandbox.restore() - }) - beforeEach(function () { - sandbox.stub(trace, 'logTrace') + sinon.restore() }) it('logs appropriate information', async function () { diff --git a/core/base-service/cache-headers.spec.js b/core/base-service/cache-headers.spec.js index 9c705116a2fe7..ebfc53f815243 100644 --- a/core/base-service/cache-headers.spec.js +++ b/core/base-service/cache-headers.spec.js @@ -99,14 +99,11 @@ describe('Cache header functions', function () { }) describe('setHeadersForCacheLength', function () { - let sandbox beforeEach(function () { - sandbox = sinon.createSandbox() - sandbox.useFakeTimers() + sinon.useFakeTimers() }) afterEach(function () { - sandbox.restore() - sandbox = undefined + sinon.restore() }) it('should set the correct Date header', function () { diff --git a/core/base-service/got.js b/core/base-service/got.js deleted file mode 100644 index 0120e216cd56d..0000000000000 --- a/core/base-service/got.js +++ /dev/null @@ -1,96 +0,0 @@ -import got from 'got' -import { Inaccessible, InvalidResponse } from './errors.js' - -const userAgent = 'Shields.io/2003a' - -function requestOptions2GotOptions(options) { - const requestOptions = Object.assign({}, options) - const gotOptions = {} - const interchangableOptions = ['body', 'form', 'headers', 'method', 'url'] - - interchangableOptions.forEach(function (opt) { - if (opt in requestOptions) { - gotOptions[opt] = requestOptions[opt] - delete requestOptions[opt] - } - }) - - if ('qs' in requestOptions) { - gotOptions.searchParams = requestOptions.qs - delete requestOptions.qs - } - - if ('gzip' in requestOptions) { - gotOptions.decompress = requestOptions.gzip - delete requestOptions.gzip - } - - if ('strictSSL' in requestOptions) { - gotOptions.https = { - rejectUnauthorized: requestOptions.strictSSL, - } - delete requestOptions.strictSSL - } - - if ('auth' in requestOptions) { - gotOptions.username = requestOptions.auth.user - gotOptions.password = requestOptions.auth.pass - delete requestOptions.auth - } - - if (Object.keys(requestOptions).length > 0) { - throw new Error(`Found unrecognised options ${Object.keys(requestOptions)}`) - } - - return gotOptions -} - -async function sendRequest(gotWrapper, url, options) { - const gotOptions = requestOptions2GotOptions(options) - gotOptions.throwHttpErrors = false - gotOptions.retry = 0 - gotOptions.headers = gotOptions.headers || {} - gotOptions.headers['User-Agent'] = userAgent - try { - const resp = await gotWrapper(url, gotOptions) - return { res: resp, buffer: resp.body } - } catch (err) { - if (err instanceof got.CancelError) { - throw new InvalidResponse({ - underlyingError: new Error('Maximum response size exceeded'), - }) - } - throw new Inaccessible({ underlyingError: err }) - } -} - -function fetchFactory(fetchLimitBytes) { - const gotWithLimit = got.extend({ - handlers: [ - (options, next) => { - const promiseOrStream = next(options) - promiseOrStream.on('downloadProgress', progress => { - if ( - progress.transferred > fetchLimitBytes && - // just accept the file if we've already finished downloading - // the entire file before we went over the limit - progress.percent !== 1 - ) { - /* - TODO: we should be able to pass cancel() a message - https://github.com/sindresorhus/got/blob/main/documentation/advanced-creation.md#examples - but by the time we catch it, err.message is just "Promise was canceled" - */ - promiseOrStream.cancel('Maximum response size exceeded') - } - }) - - return promiseOrStream - }, - ], - }) - - return sendRequest.bind(sendRequest, gotWithLimit) -} - -export { requestOptions2GotOptions, fetchFactory } diff --git a/core/base-service/got.spec.js b/core/base-service/got.spec.js deleted file mode 100644 index 185052d16384e..0000000000000 --- a/core/base-service/got.spec.js +++ /dev/null @@ -1,102 +0,0 @@ -import { expect } from 'chai' -import nock from 'nock' -import { requestOptions2GotOptions, fetchFactory } from './got.js' -import { Inaccessible, InvalidResponse } from './errors.js' - -describe('requestOptions2GotOptions function', function () { - it('translates valid options', function () { - expect( - requestOptions2GotOptions({ - body: 'body', - form: 'form', - headers: 'headers', - method: 'method', - url: 'url', - qs: 'qs', - gzip: 'gzip', - strictSSL: 'strictSSL', - auth: { user: 'user', pass: 'pass' }, - }) - ).to.deep.equal({ - body: 'body', - form: 'form', - headers: 'headers', - method: 'method', - url: 'url', - searchParams: 'qs', - decompress: 'gzip', - https: { rejectUnauthorized: 'strictSSL' }, - username: 'user', - password: 'pass', - }) - }) - - it('throws if unrecognised options are found', function () { - expect(() => - requestOptions2GotOptions({ body: 'body', foobar: 'foobar' }) - ).to.throw(Error, 'Found unrecognised options foobar') - }) -}) - -describe('got wrapper', function () { - it('should not throw an error if the response <= fetchLimitBytes', async function () { - nock('https://www.google.com') - .get('/foo/bar') - .once() - .reply(200, 'x'.repeat(100)) - const sendRequest = fetchFactory(100) - const { res } = await sendRequest('https://www.google.com/foo/bar') - expect(res.statusCode).to.equal(200) - }) - - it('should throw an InvalidResponse error if the response is > fetchLimitBytes', async function () { - nock('https://www.google.com') - .get('/foo/bar') - .once() - .reply(200, 'x'.repeat(101)) - const sendRequest = fetchFactory(100) - return expect( - sendRequest('https://www.google.com/foo/bar') - ).to.be.rejectedWith(InvalidResponse, 'Maximum response size exceeded') - }) - - it('should throw an Inaccessible error if the request throws a (non-HTTP) error', async function () { - nock('https://www.google.com').get('/foo/bar').replyWithError('oh no') - const sendRequest = fetchFactory(1024) - return expect( - sendRequest('https://www.google.com/foo/bar') - ).to.be.rejectedWith(Inaccessible, 'oh no') - }) - - it('should throw an Inaccessible error if the host can not be accessed', async function () { - this.timeout(5000) - nock.disableNetConnect() - const sendRequest = fetchFactory(1024) - return expect( - sendRequest('https://www.google.com/foo/bar') - ).to.be.rejectedWith( - Inaccessible, - 'Nock: Disallowed net connect for "www.google.com:443/foo/bar"' - ) - }) - - it('should pass a custom user agent header', async function () { - nock('https://www.google.com', { - reqheaders: { - 'user-agent': function (agent) { - return agent.startsWith('Shields.io') - }, - }, - }) - .get('/foo/bar') - .once() - .reply(200) - const sendRequest = fetchFactory(1024) - await sendRequest('https://www.google.com/foo/bar') - }) - - afterEach(function () { - nock.cleanAll() - nock.enableNetConnect() - }) -}) diff --git a/core/base-service/node-fetch.js b/core/base-service/node-fetch.js new file mode 100644 index 0000000000000..de954b492ab85 --- /dev/null +++ b/core/base-service/node-fetch.js @@ -0,0 +1,101 @@ +import { URL, URLSearchParams } from 'url' +import fetch from 'node-fetch' +import { Inaccessible, InvalidResponse } from './errors.js' + +const userAgent = 'Shields.io/2003a' + +function object2URLSearchParams(obj) { + const qs = {} + for (const [key, value] of Object.entries(obj)) { + if (value === undefined) { + continue + } else if (value === null) { + qs[key] = '' + } else if (['string', 'number', 'boolean'].includes(typeof value)) { + qs[key] = value + } + } + return new URLSearchParams(qs) +} + +function request2NodeFetch({ url, options }) { + const requestOptions = Object.assign({}, options) + const nodeFetchOptions = {} + const nodeFetchUrl = new URL(url) + const interchangableOptions = ['headers', 'method', 'body'] + + if ('body' in requestOptions && 'form' in requestOptions) { + throw new Error("Options 'form' and 'body' can not both be used") + } + + interchangableOptions.forEach(function (opt) { + if (opt in requestOptions) { + nodeFetchOptions[opt] = requestOptions[opt] + delete requestOptions[opt] + } + }) + nodeFetchOptions.headers = nodeFetchOptions.headers || {} + + if ('qs' in requestOptions) { + if (typeof requestOptions.qs === 'string') { + nodeFetchUrl.search = requestOptions.qs + delete requestOptions.qs + } else if (typeof requestOptions.qs === 'object') { + nodeFetchUrl.search = object2URLSearchParams(requestOptions.qs) + delete requestOptions.qs + } else if (requestOptions.qs == null) { + delete requestOptions.qs + } else { + throw new Error("Property 'qs' must be string, object or null") + } + } + + if ('gzip' in requestOptions) { + nodeFetchOptions.compress = requestOptions.gzip + delete requestOptions.gzip + } + + if ('auth' in requestOptions) { + const user = requestOptions.auth.user || '' + const pass = requestOptions.auth.pass || '' + const b64authStr = Buffer.from(`${user}:${pass}`).toString('base64') + nodeFetchOptions.headers.Authorization = `Basic ${b64authStr}` + delete requestOptions.auth + } + + if ('form' in requestOptions) { + nodeFetchOptions.body = object2URLSearchParams(requestOptions.form) + delete requestOptions.form + } + + if (Object.keys(requestOptions).length > 0) { + throw new Error(`Found unrecognised options ${Object.keys(requestOptions)}`) + } + + return { url: nodeFetchUrl.toString(), options: nodeFetchOptions } +} + +async function sendRequest(fetchLimitBytes, url, options) { + const { url: nodeFetchUrl, options: nodeFetchOptions } = request2NodeFetch({ + url, + options, + }) + nodeFetchOptions.headers['User-Agent'] = userAgent + nodeFetchOptions.size = fetchLimitBytes + nodeFetchOptions.follow = 10 + try { + const resp = await fetch(nodeFetchUrl, nodeFetchOptions) + const body = await resp.text() + resp.statusCode = resp.status + return { res: resp, buffer: body } + } catch (err) { + if (err.type === 'max-size') { + throw new InvalidResponse({ + underlyingError: new Error('Maximum response size exceeded'), + }) + } + throw new Inaccessible({ underlyingError: err }) + } +} + +export { request2NodeFetch, sendRequest } diff --git a/core/base-service/node-fetch.spec.js b/core/base-service/node-fetch.spec.js new file mode 100644 index 0000000000000..0ee6f6745a4f5 --- /dev/null +++ b/core/base-service/node-fetch.spec.js @@ -0,0 +1,180 @@ +import { URLSearchParams } from 'url' +import { expect } from 'chai' +import nock from 'nock' +import { request2NodeFetch, sendRequest } from './node-fetch.js' +import { Inaccessible, InvalidResponse } from './errors.js' + +describe('request2NodeFetch function', function () { + it('translates simple options', function () { + expect( + request2NodeFetch({ + url: 'https://google.com/', + options: { + body: 'body', + headers: 'headers', + method: 'method', + gzip: 'gzip', + }, + }) + ).to.deep.equal({ + url: 'https://google.com/', + options: { + body: 'body', + headers: 'headers', + method: 'method', + compress: 'gzip', + }, + }) + }) + + it('translates auth to header', function () { + expect( + request2NodeFetch({ + url: 'https://google.com/', + options: { auth: { user: 'user', pass: 'pass' } }, + }) + ).to.deep.equal({ + url: 'https://google.com/', + options: { + headers: { + Authorization: 'Basic dXNlcjpwYXNz', + }, + }, + }) + expect( + request2NodeFetch({ + url: 'https://google.com/', + options: { auth: { user: 'user' } }, + }) + ).to.deep.equal({ + url: 'https://google.com/', + options: { + headers: { + Authorization: 'Basic dXNlcjo=', + }, + }, + }) + expect( + request2NodeFetch({ + url: 'https://google.com/', + options: { auth: { pass: 'pass' } }, + }) + ).to.deep.equal({ + url: 'https://google.com/', + options: { + headers: { + Authorization: 'Basic OnBhc3M=', + }, + }, + }) + }) + + it('translates form to body', function () { + expect( + request2NodeFetch({ + url: 'https://google.com/', + options: { + form: { foo: 'bar', baz: 1 }, + }, + }) + ).to.deep.equal({ + url: 'https://google.com/', + options: { + body: new URLSearchParams({ foo: 'bar', baz: 1 }), + headers: {}, + }, + }) + }) + + it('appends qs to URL', function () { + expect( + request2NodeFetch({ + url: 'https://google.com/', + options: { + qs: { foo: 'bar', baz: 1 }, + }, + }) + ).to.deep.equal({ + url: 'https://google.com/?foo=bar&baz=1', + options: { + headers: {}, + }, + }) + }) + + it('throws if unrecognised options are found', function () { + expect(() => + request2NodeFetch({ + url: 'https://google.com/', + options: { body: 'body', foobar: 'foobar' }, + }) + ).to.throw(Error, 'Found unrecognised options foobar') + }) + + it('throws if body and form are both specified', function () { + expect(() => + request2NodeFetch({ + url: 'https://google.com/', + options: { body: 'body', form: 'form' }, + }) + ).to.throw(Error, "Options 'form' and 'body' can not both be used") + }) +}) + +describe('sendRequest', function () { + it('should not throw an error if the response <= fetchLimitBytes', async function () { + nock('https://www.google.com') + .get('/foo/bar') + .once() + .reply(200, 'x'.repeat(100)) + const { res } = await sendRequest(100, 'https://www.google.com/foo/bar') + expect(res.statusCode).to.equal(200) + }) + + it('should throw an InvalidResponse error if the response is > fetchLimitBytes', async function () { + nock('https://www.google.com') + .get('/foo/bar') + .once() + .reply(200, 'x'.repeat(101)) + return expect( + sendRequest(100, 'https://www.google.com/foo/bar') + ).to.be.rejectedWith(InvalidResponse, 'Maximum response size exceeded') + }) + + it('should throw an Inaccessible error if the request throws a (non-HTTP) error', async function () { + nock('https://www.google.com').get('/foo/bar').replyWithError('oh no') + return expect( + sendRequest(1024, 'https://www.google.com/foo/bar') + ).to.be.rejectedWith(Inaccessible, 'oh no') + }) + + it('should throw an Inaccessible error if the host can not be accessed', async function () { + this.timeout(5000) + nock.disableNetConnect() + return expect( + sendRequest(1024, 'https://www.google.com/foo/bar') + ).to.be.rejectedWith( + Inaccessible, + 'Nock: Disallowed net connect for "www.google.com:443/foo/bar"' + ) + }) + + it('should pass a custom user agent header', async function () { + nock('https://www.google.com', { + reqheaders: { + 'user-agent': function (agent) { + return agent.startsWith('Shields.io') + }, + }, + }) + .get('/foo/bar') + .once() + .reply(200) + await sendRequest(1024, 'https://www.google.com/foo/bar') + }) + + afterEach(function () { + nock.cleanAll() + nock.enableNetConnect() + }) +}) diff --git a/core/base-service/validate.spec.js b/core/base-service/validate.spec.js index 78f6c46f5ceeb..9060e3256a5f7 100644 --- a/core/base-service/validate.spec.js +++ b/core/base-service/validate.spec.js @@ -10,15 +10,11 @@ describe('validate', function () { requiredString: Joi.string().required(), }).required() - let sandbox beforeEach(function () { - sandbox = sinon.createSandbox() + sinon.stub(trace, 'logTrace') }) afterEach(function () { - sandbox.restore() - }) - beforeEach(function () { - sandbox.stub(trace, 'logTrace') + sinon.restore() }) const ErrorClass = InvalidParameter diff --git a/core/server/secret-is-valid.js b/core/server/secret-is-valid.js deleted file mode 100644 index c8b87ffda123f..0000000000000 --- a/core/server/secret-is-valid.js +++ /dev/null @@ -1,18 +0,0 @@ -function constEq(a, b) { - if (a.length !== b.length) { - return false - } - let zero = 0 - for (let i = 0; i < a.length; i++) { - zero |= a.charCodeAt(i) ^ b.charCodeAt(i) - } - return zero === 0 -} - -function makeSecretIsValid(shieldsSecret) { - return function secretIsValid(secret = '') { - return shieldsSecret && constEq(secret, shieldsSecret) - } -} - -export { makeSecretIsValid } diff --git a/core/server/server.js b/core/server/server.js index 8b5b166b35719..7a2b1d814a3a1 100644 --- a/core/server/server.js +++ b/core/server/server.js @@ -177,7 +177,6 @@ const privateConfigSchema = Joi.object({ obs_pass: Joi.string(), redis_url: Joi.string().uri({ scheme: ['redis', 'rediss'] }), sentry_dsn: Joi.string(), - shields_secret: Joi.string(), sl_insight_userUuid: Joi.string(), sl_insight_apiToken: Joi.string(), sonarqube_token: Joi.string(), diff --git a/core/token-pooling/token-pool.js b/core/token-pooling/token-pool.js index 7dcf64ad5abdf..34010ed53664f 100644 --- a/core/token-pooling/token-pool.js +++ b/core/token-pooling/token-pool.js @@ -328,29 +328,6 @@ class TokenPool { this.fifoQueue.forEach(visit) this.priorityQueue.forEach(visit) } - - allValidTokenIds() { - const result = [] - this.forEach(({ id }) => result.push(id)) - return result - } - - serializeDebugInfo({ sanitize = true } = {}) { - const maybeSanitize = sanitize ? id => sanitizeToken(id) : id => id - - const priorityQueue = [] - this.priorityQueue.forEach(t => - priorityQueue.push(t.getDebugInfo({ sanitize })) - ) - - return { - utcEpochSeconds: getUtcEpochSeconds(), - allValidTokenIds: this.allValidTokenIds().map(maybeSanitize), - fifoQueue: this.fifoQueue.map(t => t.getDebugInfo({ sanitize })), - priorityQueue, - sanitized: sanitize, - } - } } export { sanitizeToken, Token, TokenPool } diff --git a/core/token-pooling/token-pool.spec.js b/core/token-pooling/token-pool.spec.js index fdfa937d200a1..373a4ef479ff8 100644 --- a/core/token-pooling/token-pool.spec.js +++ b/core/token-pooling/token-pool.spec.js @@ -19,10 +19,6 @@ describe('The token pool', function () { ids.forEach(id => tokenPool.add(id)) }) - it('allValidTokenIds() should return the full list', function () { - expect(tokenPool.allValidTokenIds()).to.deep.equal(ids) - }) - it('should yield the expected tokens', function () { ids.forEach(id => times(batchSize, () => expect(tokenPool.next().id).to.equal(id)) @@ -38,67 +34,6 @@ describe('The token pool', function () { ) }) - describe('serializeDebugInfo should initially return the expected', function () { - beforeEach(function () { - sinon.useFakeTimers({ now: 1544307744484 }) - }) - - afterEach(function () { - sinon.restore() - }) - - context('sanitize is not specified', function () { - it('returns fully sanitized results', function () { - // This is `sha()` of '1', '2', '3', '4', '5'. These are written - // literally for avoidance of doubt as to whether sanitization is - // happening. - const sanitizedIds = [ - '6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b', - 'd4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35', - '4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce', - '4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a', - 'ef2d127de37b942baad06145e54b0c619a1f22327b2ebbcfbec78f5564afe39d', - ] - - expect(tokenPool.serializeDebugInfo()).to.deep.equal({ - allValidTokenIds: sanitizedIds, - priorityQueue: [], - fifoQueue: sanitizedIds.map(id => ({ - data: '[redacted]', - id, - isFrozen: false, - isValid: true, - nextReset: Token.nextResetNever, - usesRemaining: batchSize, - })), - sanitized: true, - utcEpochSeconds: 1544307744, - }) - }) - }) - - context('with sanitize: false', function () { - it('returns unsanitized results', function () { - expect(tokenPool.serializeDebugInfo({ sanitize: false })).to.deep.equal( - { - allValidTokenIds: ids, - priorityQueue: [], - fifoQueue: ids.map(id => ({ - data: undefined, - id, - isFrozen: false, - isValid: true, - nextReset: Token.nextResetNever, - usesRemaining: batchSize, - })), - sanitized: false, - utcEpochSeconds: 1544307744, - } - ) - }) - }) - }) - context('tokens are marked exhausted immediately', function () { it('should be exhausted', function () { ids.forEach(() => { diff --git a/doc/adding-new-config-values.md b/doc/adding-new-config-values.md new file mode 100644 index 0000000000000..fe7fdd58ed913 --- /dev/null +++ b/doc/adding-new-config-values.md @@ -0,0 +1,22 @@ +# Adding New Config Values + +The Badge Server supports a [variety of methods for defining configuration settings and secrets](./server-secrets.md), and provides a framework for loading those values during bootstrapping. + +Any new configuration setting or secret must be correctly registered so that it will be loaded at startup along with the others. + +This generally includes adding the corresponding information for your new setting(s)/secret(s) to the following locations: + +- [core/server/server.js](https://github.com/badges/shields/blob/master/core/server/server.js) - Add the new values to the [schemas](https://github.com/badges/shields/blob/master/core/server/server.js#L118-L193). Secrets/tokens/etc. should go in the `privateConfigSchema` while non-secret configuration settings should go in the `publicConfigSchema`. +- [config/custom-environment-variables.yml](https://github.com/badges/shields/blob/master/config/custom-environment-variables.yml) +- [docs/server-secrets.md](https://github.com/badges/shields/blob/master/doc/server-secrets.md) (only applicable for secrets) +- [config/default.yml](https://github.com/badges/shields/blob/master/config/default.yml) (optional) +- Any other template config files (e.g. `config/local.template.yml`) (optional) + +The exact values needed will depend on what type of secret/setting you are adding, but for reference a few commits are included below which added secrets and or settings: + +- (secret) [8a9efb2fc99f97e78ab133c836ab1685803bf4df](https://github.com/badges/shields/commit/8a9efb2fc99f97e78ab133c836ab1685803bf4df) +- (secret) [bd6f4ee1465d14a8f188c37823748a21b6a46762](https://github.com/badges/shields/commit/bd6f4ee1465d14a8f188c37823748a21b6a46762) +- (secret) [0fd557d7bb623e3852c92cebac586d5f6d6d89d8](https://github.com/badges/shields/commit/0fd557d7bb623e3852c92cebac586d5f6d6d89d8) +- (configuration setting) [b1fc4925928c061234e9492f3794c0797467e123](https://github.com/badges/shields/commit/b1fc4925928c061234e9492f3794c0797467e123) + +Don't hesitate to reach out if you're unsure of the exact values needed for your new secret/setting, or have any other questions. Feel free to post questions on your corresponding Issue/Pull Request, and/or ping us on the `contributing` channel on our Discord server. diff --git a/doc/production-hosting.md b/doc/production-hosting.md index d7f6f9e2ad8cc..8a8120853dd15 100644 --- a/doc/production-hosting.md +++ b/doc/production-hosting.md @@ -16,7 +16,7 @@ Production hosting is managed by the Shields ops team: | Component | Subcomponent | People with access | | ----------------------------- | ------------------------------- | --------------------------------------------------------------- | -| shields-production-us | Account owner | @paulmelnikow | +| shields-production-us | Account owner | @calebcartwright, @paulmelnikow | | shields-production-us | Full access | @calebcartwright, @chris48s, @paulmelnikow, @pyvesb | | shields-production-us | Access management | @calebcartwright, @chris48s, @paulmelnikow, @pyvesb | | Compose.io Redis | Account owner | @paulmelnikow | diff --git a/doc/releases.md b/doc/releases.md index 2770bf9e66d41..9a871b3048788 100644 --- a/doc/releases.md +++ b/doc/releases.md @@ -2,7 +2,7 @@ Shields is a community project that is stewarded by a handful of core maintainers who contribute on a volunteer basis. We do our best to maintain the availability and reliability of the service, and enhance and improve the project overall. However, if you've spotted something wrong or would like to see a specific feature implemented, please consider helping us resolve it by submitting a pull request. All community contributions, even documentation improvements, are welcome! -https://github.com/badges/shields is a monorepo and hosts the Shields frontend and server code as well as the [badge-maker][npm package] NPM library (and the [badge design specification](https://github.com/badges/shields/tree/master/spec)). The packaging and release processes for these items is described in the respective sections below. +https://github.com/badges/shields is a monorepo and hosts the Shields frontend and server code as well as the [badge-maker][npm package] NPM library (and the [badge design specification](https://github.com/badges/shields/tree/master/spec)). The packaging and release processes for these items are described in the respective sections below. ## badge-maker package diff --git a/doc/service-tests.md b/doc/service-tests.md index 0a332806bc9e6..23afe7255a687 100644 --- a/doc/service-tests.md +++ b/doc/service-tests.md @@ -254,7 +254,7 @@ By checking code coverage, we can make sure we've covered all our bases. We can generate a coverage report and open it: ``` -npm run coverage:test:services -- --only=wercker +npm run coverage:test:services -- -- --only=wercker npm run coverage:report:open ``` diff --git a/package-lock.json b/package-lock.json index 7a4fc4a45783f..2abf2f73a3f7d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@fontsource/lato": "^4.5.0", "@fontsource/lekton": "^4.5.0", - "@sentry/node": "^6.13.2", + "@sentry/node": "^6.13.3", "@shields_io/camp": "^18.1.1", "badge-maker": "file:badge-maker", "bytes": "^3.1.0", @@ -21,16 +21,16 @@ "cloudflare-middleware": "^1.0.4", "config": "^3.3.6", "cross-env": "^7.0.3", - "decamelize": "^5.0.0", + "decamelize": "^6.0.0", "emojic": "^1.1.16", "escape-string-regexp": "^4.0.0", - "fast-xml-parser": "^3.20.0", + "fast-xml-parser": "^3.20.3", "glob": "^7.2.0", "global-agent": "^3.0.0", "got": "11.8.2", - "graphql": "^15.5.3", + "graphql": "^15.6.1", "graphql-tag": "^2.12.5", - "ioredis": "4.27.9", + "ioredis": "4.27.10", "joi": "17.4.2", "joi-extension-semver": "5.0.0", "js-yaml": "^4.1.0", @@ -40,6 +40,7 @@ "lodash.times": "^4.3.2", "moment": "^2.29.1", "node-env-flag": "^0.1.0", + "node-fetch": "^2.6.1", "parse-link-header": "^1.0.1", "path-to-regexp": "^6.2.0", "pretty-bytes": "^5.6.0", @@ -49,13 +50,13 @@ "query-string": "^7.0.1", "request": "~2.88.2", "semver": "~7.3.5", - "simple-icons": "5.15.0", + "simple-icons": "5.17.0", "webextension-store-meta": "^1.0.4", "xmldom": "~0.6.0", "xpath": "~0.0.32" }, "devDependencies": { - "@babel/core": "^7.15.5", + "@babel/core": "^7.15.8", "@babel/polyfill": "^7.12.1", "@babel/register": "7.15.3", "@mapbox/react-click-to-select": "^2.2.1", @@ -64,16 +65,16 @@ "@types/lodash.groupby": "^4.6.6", "@types/mocha": "^9.0.0", "@types/node": "^16.7.10", - "@types/react-helmet": "^6.1.2", + "@types/react-helmet": "^6.1.3", "@types/react-modal": "^3.12.1", "@types/react-select": "^4.0.17", - "@types/styled-components": "5.1.14", - "@typescript-eslint/eslint-plugin": "^4.31.0", - "@typescript-eslint/parser": "^4.30.0", + "@types/styled-components": "5.1.15", + "@typescript-eslint/eslint-plugin": "^4.33.0", + "@typescript-eslint/parser": "^4.32.0", "babel-plugin-inline-react-svg": "^2.0.1", "babel-plugin-istanbul": "^6.0.0", "babel-preset-gatsby": "^1.14.0", - "c8": "^7.9.0", + "c8": "^7.10.0", "caller": "^1.0.1", "chai": "^4.3.4", "chai-as-promised": "^7.1.1", @@ -81,8 +82,8 @@ "chai-string": "^1.4.0", "child-process-promise": "^2.2.1", "clipboard-copy": "^4.0.1", - "concurrently": "^6.2.1", - "cypress": "^8.4.1", + "concurrently": "^6.3.0", + "cypress": "^8.5.0", "danger": "^10.6.6", "danger-plugin-no-test-shortcuts": "^2.0.0", "deepmerge": "^4.2.2", @@ -94,7 +95,7 @@ "eslint-plugin-chai-friendly": "^0.7.2", "eslint-plugin-cypress": "^2.12.1", "eslint-plugin-import": "^2.24.2", - "eslint-plugin-jsdoc": "^36.1.0", + "eslint-plugin-jsdoc": "^36.1.1", "eslint-plugin-mocha": "^9.0.0", "eslint-plugin-no-extension-in-require": "^0.2.0", "eslint-plugin-node": "^11.1.0", @@ -105,7 +106,7 @@ "fetch-ponyfill": "^7.1.0", "form-data": "^4.0.0", "gatsby": "3.13.1", - "gatsby-plugin-catch-links": "^3.13.0", + "gatsby-plugin-catch-links": "^3.14.0", "gatsby-plugin-page-creator": "^3.14.0", "gatsby-plugin-react-helmet": "^4.14.0", "gatsby-plugin-remove-trailing-slashes": "^3.14.0", @@ -117,13 +118,13 @@ "is-svg": "^4.3.1", "js-yaml-loader": "^1.2.2", "jsdoc": "^3.6.7", - "lint-staged": "^11.1.2", + "lint-staged": "^11.2.1", "lodash.debounce": "^4.0.8", "lodash.difference": "^4.5.0", "minimist": "^1.2.5", - "mocha": "^9.1.1", + "mocha": "^9.1.2", "mocha-env-reporter": "^4.0.0", - "mocha-junit-reporter": "^2.0.0", + "mocha-junit-reporter": "^2.0.2", "mocha-yaml-loader": "^1.0.3", "nock": "13.1.3", "node-mocks-http": "^1.11.0", @@ -192,9 +193,9 @@ "dev": true }, "node_modules/@babel/code-frame": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", - "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", + "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", "dev": true, "dependencies": { "@babel/highlight": "^7.14.5" @@ -213,20 +214,20 @@ } }, "node_modules/@babel/core": { - "version": "7.15.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.5.tgz", - "integrity": "sha512-pYgXxiwAgQpgM1bNkZsDEq85f0ggXMA5L7c+o3tskGMh2BunCI9QUwB9Z4jpvXUOuMdyGKiGKQiRe11VS6Jzvg==", + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.8.tgz", + "integrity": "sha512-3UG9dsxvYBMYwRv+gS41WKHno4K60/9GPy1CJaH6xy3Elq8CTtvtjT5R5jmNhXfCYLX2mTw+7/aq5ak/gOE0og==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.4", + "@babel/code-frame": "^7.15.8", + "@babel/generator": "^7.15.8", "@babel/helper-compilation-targets": "^7.15.4", - "@babel/helper-module-transforms": "^7.15.4", + "@babel/helper-module-transforms": "^7.15.8", "@babel/helpers": "^7.15.4", - "@babel/parser": "^7.15.5", + "@babel/parser": "^7.15.8", "@babel/template": "^7.15.4", "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4", + "@babel/types": "^7.15.6", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -321,12 +322,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.4.tgz", - "integrity": "sha512-d3itta0tu+UayjEORPNz6e1T3FtvWlP5N4V5M+lhp/CxT4oAA7/NcScnpRyspUMLK6tu9MNHmQHxRykuN2R7hw==", + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.8.tgz", + "integrity": "sha512-ECmAKstXbp1cvpTTZciZCgfOt6iN64lR0d+euv3UZisU5awfRawOvg07Utn/qBGuH4bRIEZKrA/4LzZyXhZr8g==", "dev": true, "dependencies": { - "@babel/types": "^7.15.4", + "@babel/types": "^7.15.6", "jsesc": "^2.5.1", "source-map": "^0.5.0" }, @@ -548,19 +549,19 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.4.tgz", - "integrity": "sha512-9fHHSGE9zTC++KuXLZcB5FKgvlV83Ox+NLUmQTawovwlJ85+QMhk1CnVk406CQVj97LaWod6KVjl2Sfgw9Aktw==", + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.8.tgz", + "integrity": "sha512-DfAfA6PfpG8t4S6npwzLvTUpp0sS7JrcuaMiy1Y5645laRJIp/LiLGIBbQKaXSInK8tiGNI7FL7L8UvB8gdUZg==", "dev": true, "dependencies": { "@babel/helper-module-imports": "^7.15.4", "@babel/helper-replace-supers": "^7.15.4", "@babel/helper-simple-access": "^7.15.4", "@babel/helper-split-export-declaration": "^7.15.4", - "@babel/helper-validator-identifier": "^7.14.9", + "@babel/helper-validator-identifier": "^7.15.7", "@babel/template": "^7.15.4", "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/types": "^7.15.6" }, "engines": { "node": ">=6.9.0" @@ -653,9 +654,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", - "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", + "version": "7.15.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", + "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", "dev": true, "engines": { "node": ">=6.9.0" @@ -755,9 +756,9 @@ "dev": true }, "node_modules/@babel/parser": { - "version": "7.15.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.6.tgz", - "integrity": "sha512-S/TSCcsRuCkmpUuoWijua0Snt+f3ewU/8spLo+4AXJCZfT0bVCzLD5MuOKdrx0mlAptbKzn5AdgEIIKXxXkz9Q==", + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.8.tgz", + "integrity": "sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -3688,14 +3689,14 @@ "dev": true }, "node_modules/@sentry/core": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.13.2.tgz", - "integrity": "sha512-snXNNFLwlS7yYxKTX4DBXebvJK+6ikBWN6noQ1CHowvM3ReFBlrdrs0Z0SsSFEzXm2S4q7f6HHbm66GSQZ/8FQ==", - "dependencies": { - "@sentry/hub": "6.13.2", - "@sentry/minimal": "6.13.2", - "@sentry/types": "6.13.2", - "@sentry/utils": "6.13.2", + "version": "6.13.3", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.13.3.tgz", + "integrity": "sha512-obm3SjgCk8A7nB37b2AU1eq1q7gMoJRrGMv9VRIyfcG0Wlz/5lJ9O3ohUk+YZaaVfZMxXn6hFtsBiOWmlv7IIA==", + "dependencies": { + "@sentry/hub": "6.13.3", + "@sentry/minimal": "6.13.3", + "@sentry/types": "6.13.3", + "@sentry/utils": "6.13.3", "tslib": "^1.9.3" }, "engines": { @@ -3703,12 +3704,12 @@ } }, "node_modules/@sentry/hub": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.13.2.tgz", - "integrity": "sha512-sppSuJdNMiMC/vFm/dQowCBh11uTrmvks00fc190YWgxHshodJwXMdpc+pN61VSOmy2QA4MbQ5aMAgHzPzel3A==", + "version": "6.13.3", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.13.3.tgz", + "integrity": "sha512-eYppBVqvhs5cvm33snW2sxfcw6G20/74RbBn+E4WDo15hozis89kU7ZCJDOPkXuag3v1h9igns/kM6PNBb41dw==", "dependencies": { - "@sentry/types": "6.13.2", - "@sentry/utils": "6.13.2", + "@sentry/types": "6.13.3", + "@sentry/utils": "6.13.3", "tslib": "^1.9.3" }, "engines": { @@ -3716,12 +3717,12 @@ } }, "node_modules/@sentry/minimal": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.13.2.tgz", - "integrity": "sha512-6iJfEvHzzpGBHDfLxSHcGObh73XU1OSQKWjuhDOe7UQDyI4BQmTfcXAC+Fr8sm8C/tIsmpVi/XJhs8cubFdSMw==", + "version": "6.13.3", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.13.3.tgz", + "integrity": "sha512-63MlYYRni3fs5Bh8XBAfVZ+ctDdWg0fapSTP1ydIC37fKvbE+5zhyUqwrEKBIiclEApg1VKX7bkKxVdu/vsFdw==", "dependencies": { - "@sentry/hub": "6.13.2", - "@sentry/types": "6.13.2", + "@sentry/hub": "6.13.3", + "@sentry/types": "6.13.3", "tslib": "^1.9.3" }, "engines": { @@ -3729,15 +3730,15 @@ } }, "node_modules/@sentry/node": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-6.13.2.tgz", - "integrity": "sha512-0Vw22amG143MTiNaSny66YGU3+uW7HxyGI9TLGE7aJY1nNmC0DE+OgqQYGBRCrrPu+VFXRDxrOg9b15A1gKqjA==", - "dependencies": { - "@sentry/core": "6.13.2", - "@sentry/hub": "6.13.2", - "@sentry/tracing": "6.13.2", - "@sentry/types": "6.13.2", - "@sentry/utils": "6.13.2", + "version": "6.13.3", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-6.13.3.tgz", + "integrity": "sha512-ZeZSw+TcPcf4e0j7iEqNMtoVmz+WFW/TEoGokXIwysZqSgchKdAXDHqn+CqUqFan7d76JcJmzztAUK2JruQ2Kg==", + "dependencies": { + "@sentry/core": "6.13.3", + "@sentry/hub": "6.13.3", + "@sentry/tracing": "6.13.3", + "@sentry/types": "6.13.3", + "@sentry/utils": "6.13.3", "cookie": "^0.4.1", "https-proxy-agent": "^5.0.0", "lru_map": "^0.3.3", @@ -3787,14 +3788,14 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/@sentry/tracing": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.13.2.tgz", - "integrity": "sha512-bHJz+C/nd6biWTNcYAu91JeRilsvVgaye4POkdzWSmD0XoLWHVMrpCQobGpXe7onkp2noU3YQjhqgtBqPHtnpw==", - "dependencies": { - "@sentry/hub": "6.13.2", - "@sentry/minimal": "6.13.2", - "@sentry/types": "6.13.2", - "@sentry/utils": "6.13.2", + "version": "6.13.3", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.13.3.tgz", + "integrity": "sha512-yyOFIhqlprPM0g4f35Icear3eZk2mwyYcGEzljJfY2iU6pJwj1lzia5PfSwiCW7jFGMmlBJNhOAIpfhlliZi8Q==", + "dependencies": { + "@sentry/hub": "6.13.3", + "@sentry/minimal": "6.13.3", + "@sentry/types": "6.13.3", + "@sentry/utils": "6.13.3", "tslib": "^1.9.3" }, "engines": { @@ -3802,19 +3803,19 @@ } }, "node_modules/@sentry/types": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.13.2.tgz", - "integrity": "sha512-6WjGj/VjjN8LZDtqJH5ikeB1o39rO1gYS6anBxiS3d0sXNBb3Ux0pNNDFoBxQpOhmdDHXYS57MEptX9EV82gmg==", + "version": "6.13.3", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.13.3.tgz", + "integrity": "sha512-Vrz5CdhaTRSvCQjSyIFIaV9PodjAVFkzJkTRxyY7P77RcegMsRSsG1yzlvCtA99zG9+e6MfoJOgbOCwuZids5A==", "engines": { "node": ">=6" } }, "node_modules/@sentry/utils": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.13.2.tgz", - "integrity": "sha512-foF4PbxqPMWNbuqdXkdoOmKm3quu3PP7Q7j/0pXkri4DtCuvF/lKY92mbY0V9rHS/phCoj+3/Se5JvM2ymh2/w==", + "version": "6.13.3", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.13.3.tgz", + "integrity": "sha512-zYFuFH3MaYtBZTeJ4Yajg7pDf0pM3MWs3+9k5my9Fd+eqNcl7dYQYJbT9gyC0HXK1QI4CAMNNlHNl4YXhF91ag==", "dependencies": { - "@sentry/types": "6.13.2", + "@sentry/types": "6.13.3", "tslib": "^1.9.3" }, "engines": { @@ -4315,9 +4316,9 @@ } }, "node_modules/@types/react-helmet": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.2.tgz", - "integrity": "sha512-dcfAZNlWb5JYFbO9CGfrPWLJAyFcT6UeR3u35eBbv8liY2Rg4K7fM1G5+HnwVgot+C+kVwXAZ8pLEn2jsMfTDg==", + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.3.tgz", + "integrity": "sha512-U4onVxaZxAp78KpXsfmyCIhLjsvJJ3goG3CYFOo+xW0cPYAz9oe5cBAUSAcN7l35OTbrFvu9TuE0YkcZMKGr4A==", "dev": true, "dependencies": { "@types/react": "*" @@ -4394,9 +4395,9 @@ "dev": true }, "node_modules/@types/styled-components": { - "version": "5.1.14", - "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.14.tgz", - "integrity": "sha512-d6P1/tyNytqKwam3cQXq7a9uPtovc/mdAs7dBiz1YbDdNIT3X4WmuFU78YdSYh84TXVuhOwezZ3EeKuNBhwsHQ==", + "version": "5.1.15", + "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.15.tgz", + "integrity": "sha512-4evch8BRI3AKgb0GAZ/sn+mSeB+Dq7meYtMi7J/0Mg98Dt1+r8fySOek7Sjw1W+Wskyjc93565o5xWAT/FdY0Q==", "dev": true, "dependencies": { "@types/hoist-non-react-statics": "*", @@ -4463,15 +4464,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.31.0.tgz", - "integrity": "sha512-iPKZTZNavAlOhfF4gymiSuUkgLne/nh5Oz2/mdiUmuZVD42m9PapnCnzjxuDsnpnbH3wT5s2D8bw6S39TC6GNw==", + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz", + "integrity": "sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==", "dev": true, "dependencies": { - "@typescript-eslint/experimental-utils": "4.31.0", - "@typescript-eslint/scope-manager": "4.31.0", + "@typescript-eslint/experimental-utils": "4.33.0", + "@typescript-eslint/scope-manager": "4.33.0", "debug": "^4.3.1", "functional-red-black-tree": "^1.0.1", + "ignore": "^5.1.8", "regexpp": "^3.1.0", "semver": "^7.3.5", "tsutils": "^3.21.0" @@ -4493,67 +4495,66 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz", + "integrity": "sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==", "dev": true, "dependencies": { - "ms": "2.1.2" + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/visitor-keys": "4.33.0" }, "engines": { - "node": ">=6.0" + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@typescript-eslint/experimental-utils": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.31.0.tgz", - "integrity": "sha512-Hld+EQiKLMppgKKkdUsLeVIeEOrwKc2G983NmznY/r5/ZtZCDvIOXnXtwqJIgYz/ymsy7n7RGvMyrzf1WaSQrw==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz", + "integrity": "sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==", "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.31.0", - "@typescript-eslint/types": "4.31.0", - "@typescript-eslint/typescript-estree": "4.31.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" } }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz", + "integrity": "sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==", "dev": true, "dependencies": { + "@typescript-eslint/types": "4.33.0", "eslint-visitor-keys": "^2.0.0" }, "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" }, "funding": { - "url": "https://github.com/sponsors/mysticatea" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" }, - "peerDependencies": { - "eslint": ">=5" + "engines": { + "node": ">=6.0" } }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-visitor-keys": { + "node_modules/@typescript-eslint/eslint-plugin/node_modules/eslint-visitor-keys": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", @@ -4562,16 +4563,33 @@ "node": ">=10" } }, - "node_modules/@typescript-eslint/parser": { - "version": "4.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.30.0.tgz", - "integrity": "sha512-HJ0XuluSZSxeboLU7Q2VQ6eLlCwXPBOGnA7CqgBnz2Db3JRQYyBDJgQnop6TZ+rsbSx5gEdWhw4rE4mDa1FnZg==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/experimental-utils": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz", + "integrity": "sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "4.30.0", - "@typescript-eslint/types": "4.30.0", - "@typescript-eslint/typescript-estree": "4.30.0", - "debug": "^4.3.1" + "@types/json-schema": "^7.0.7", + "@typescript-eslint/scope-manager": "4.33.0", + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/typescript-estree": "4.33.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" }, "engines": { "node": "^10.12.0 || >=12.0.0" @@ -4581,22 +4599,17 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "*" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "4.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.30.0.tgz", - "integrity": "sha512-VJ/jAXovxNh7rIXCQbYhkyV2Y3Ac/0cVHP/FruTJSAUUm4Oacmn/nkN5zfWmWFEanN4ggP0vJSHOeajtHq3f8A==", + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/scope-manager": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz", + "integrity": "sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "4.30.0", - "@typescript-eslint/visitor-keys": "4.30.0" + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/visitor-keys": "4.33.0" }, "engines": { "node": "^8.10.0 || ^10.13.0 || >=11.10.1" @@ -4606,10 +4619,10 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "4.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.30.0.tgz", - "integrity": "sha512-YKldqbNU9K4WpTNwBqtAerQKLLW/X2A/j4yw92e3ZJYLx+BpKLeheyzoPfzIXHfM8BXfoleTdiYwpsvVPvHrDw==", + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/types": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz", + "integrity": "sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==", "dev": true, "engines": { "node": "^8.10.0 || ^10.13.0 || >=11.10.1" @@ -4619,14 +4632,14 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "4.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.30.0.tgz", - "integrity": "sha512-6WN7UFYvykr/U0Qgy4kz48iGPWILvYL34xXJxvDQeiRE018B7POspNRVtAZscWntEPZpFCx4hcz/XBT+erenfg==", + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz", + "integrity": "sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "4.30.0", - "@typescript-eslint/visitor-keys": "4.30.0", + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/visitor-keys": "4.33.0", "debug": "^4.3.1", "globby": "^11.0.3", "is-glob": "^4.0.1", @@ -4646,13 +4659,13 @@ } } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "4.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.30.0.tgz", - "integrity": "sha512-pNaaxDt/Ol/+JZwzP7MqWc8PJQTUhZwoee/PVlQ+iYoYhagccvoHnC9e4l+C/krQYYkENxznhVSDwClIbZVxRw==", + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz", + "integrity": "sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "4.30.0", + "@typescript-eslint/types": "4.33.0", "eslint-visitor-keys": "^2.0.0" }, "engines": { @@ -4663,19 +4676,42 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser/node_modules/debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "node_modules/@typescript-eslint/experimental-utils/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "dependencies": { "ms": "2.1.2" }, "engines": { "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" } }, - "node_modules/@typescript-eslint/parser/node_modules/eslint-visitor-keys": { + "node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-visitor-keys": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", @@ -4684,7 +4720,7 @@ "node": ">=10" } }, - "node_modules/@typescript-eslint/parser/node_modules/globby": { + "node_modules/@typescript-eslint/experimental-utils/node_modules/globby": { "version": "11.0.4", "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", @@ -4704,7 +4740,7 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@typescript-eslint/parser/node_modules/ignore": { + "node_modules/@typescript-eslint/experimental-utils/node_modules/ignore": { "version": "5.1.8", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", @@ -4713,6 +4749,56 @@ "node": ">= 4" } }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/parser": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.32.0.tgz", + "integrity": "sha512-lhtYqQ2iEPV5JqV7K+uOVlPePjClj4dOw7K4/Z1F2yvjIUvyr13yJnDzkK6uon4BjHYuHy3EG0c2Z9jEhFk56w==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "4.32.0", + "@typescript-eslint/types": "4.32.0", + "@typescript-eslint/typescript-estree": "4.32.0", + "debug": "^4.3.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/@typescript-eslint/parser/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -4720,13 +4806,13 @@ "dev": true }, "node_modules/@typescript-eslint/scope-manager": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.31.0.tgz", - "integrity": "sha512-LJ+xtl34W76JMRLjbaQorhR0hfRAlp3Lscdiz9NeI/8i+q0hdBZ7BsiYieLoYWqy+AnRigaD3hUwPFugSzdocg==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.32.0.tgz", + "integrity": "sha512-DK+fMSHdM216C0OM/KR1lHXjP1CNtVIhJ54kQxfOE6x8UGFAjha8cXgDMBEIYS2XCYjjCtvTkjQYwL3uvGOo0w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "4.31.0", - "@typescript-eslint/visitor-keys": "4.31.0" + "@typescript-eslint/types": "4.32.0", + "@typescript-eslint/visitor-keys": "4.32.0" }, "engines": { "node": "^8.10.0 || ^10.13.0 || >=11.10.1" @@ -4737,9 +4823,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.31.0.tgz", - "integrity": "sha512-9XR5q9mk7DCXgXLS7REIVs+BaAswfdHhx91XqlJklmqWpTALGjygWVIb/UnLh4NWhfwhR5wNe1yTyCInxVhLqQ==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.32.0.tgz", + "integrity": "sha512-LE7Z7BAv0E2UvqzogssGf1x7GPpUalgG07nGCBYb1oK4mFsOiFC/VrSMKbZQzFJdN2JL5XYmsx7C7FX9p9ns0w==", "dev": true, "engines": { "node": "^8.10.0 || ^10.13.0 || >=11.10.1" @@ -4750,13 +4836,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.31.0.tgz", - "integrity": "sha512-QHl2014t3ptg+xpmOSSPn5hm4mY8D4s97ftzyk9BZ8RxYQ3j73XcwuijnJ9cMa6DO4aLXeo8XS3z1omT9LA/Eg==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.32.0.tgz", + "integrity": "sha512-tRYCgJ3g1UjMw1cGG8Yn1KzOzNlQ6u1h9AmEtPhb5V5a1TmiHWcRyF/Ic+91M4f43QeChyYlVTcf3DvDTZR9vw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "4.31.0", - "@typescript-eslint/visitor-keys": "4.31.0", + "@typescript-eslint/types": "4.32.0", + "@typescript-eslint/visitor-keys": "4.32.0", "debug": "^4.3.1", "globby": "^11.0.3", "is-glob": "^4.0.1", @@ -4829,12 +4915,12 @@ "dev": true }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.31.0.tgz", - "integrity": "sha512-HUcRp2a9I+P21+O21yu3ezv3GEPGjyGiXoEUQwZXjR8UxRApGeLyWH4ZIIUSalE28aG4YsV6GjtaAVB3QKOu0w==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.32.0.tgz", + "integrity": "sha512-e7NE0qz8W+atzv3Cy9qaQ7BTLwWsm084Z0c4nIO2l3Bp6u9WIgdqCgyPyV5oSPDMIW3b20H59OOCmVk3jw3Ptw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "4.31.0", + "@typescript-eslint/types": "4.32.0", "eslint-visitor-keys": "^2.0.0" }, "engines": { @@ -6431,16 +6517,16 @@ } }, "node_modules/c8": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/c8/-/c8-7.9.0.tgz", - "integrity": "sha512-aQ7dC8gASnKdBwHUuYuzsdKCEDrKnWr7ZuZUnf4CNAL81oyKloKrs7H7zYvcrmCtIrMToudBSUhq2q+LLBMvgg==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/c8/-/c8-7.10.0.tgz", + "integrity": "sha512-OAwfC5+emvA6R7pkYFVBTOtI5ruf9DahffGmIqUc9l6wEh0h7iAFP6dt/V9Ioqlr2zW5avX9U9/w1I4alTRHkA==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@istanbuljs/schema": "^0.1.2", "find-up": "^5.0.0", "foreground-child": "^2.0.0", - "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-coverage": "^3.0.1", "istanbul-lib-report": "^3.0.0", "istanbul-reports": "^3.0.2", "rimraf": "^3.0.0", @@ -7562,9 +7648,9 @@ } }, "node_modules/colorette": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz", - "integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", "dev": true }, "node_modules/colors": { @@ -7704,15 +7790,14 @@ } }, "node_modules/concurrently": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-6.2.1.tgz", - "integrity": "sha512-emgwhH+ezkuYKSHZQ+AkgEpoUZZlbpPVYCVv7YZx0r+T7fny1H03r2nYRebpi2DudHR4n1Rgbo2YTxKOxVJ4+g==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-6.3.0.tgz", + "integrity": "sha512-k4k1jQGHHKsfbqzkUszVf29qECBrkvBKkcPJEUDTyVR7tZd1G/JOfnst4g1sYbFvJ4UjHZisj1aWQR8yLKpGPw==", "dev": true, "dependencies": { "chalk": "^4.1.0", "date-fns": "^2.16.1", "lodash": "^4.17.21", - "read-pkg": "^5.2.0", "rxjs": "^6.6.3", "spawn-command": "^0.0.2-1", "supports-color": "^8.1.0", @@ -7744,57 +7829,6 @@ "node": ">=8" } }, - "node_modules/concurrently/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/concurrently/node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/concurrently/node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/concurrently/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, "node_modules/concurrently/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -7807,15 +7841,6 @@ "node": ">=10" } }, - "node_modules/concurrently/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/config": { "version": "3.3.6", "resolved": "https://registry.npmjs.org/config/-/config-3.3.6.tgz", @@ -8656,9 +8681,9 @@ "dev": true }, "node_modules/cypress": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-8.4.1.tgz", - "integrity": "sha512-itJXq0Vx3sXCUrDyBi2IUrkxVu/gTTp1VhjB5tzGgkeCR8Ae+/T8WV63rsZ7fS8Tpq7LPPXiyoM/sEdOX7cR6A==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-8.5.0.tgz", + "integrity": "sha512-MMkXIS+Ro2KETn4gAlG3tIc/7FiljuuCZP0zpd9QsRG6MZSyZW/l1J3D4iQM6WHsVxuX4rFChn5jPFlC2tNSvQ==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -8696,6 +8721,7 @@ "minimist": "^1.2.5", "ospath": "^1.2.2", "pretty-bytes": "^5.6.0", + "proxy-from-env": "1.0.0", "ramda": "~0.27.1", "request-progress": "^3.0.0", "supports-color": "^8.1.1", @@ -9112,11 +9138,14 @@ } }, "node_modules/decamelize": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.0.tgz", - "integrity": "sha512-U75DcT5hrio3KNtvdULAWnLiAPbFUC4191ldxMmj4FA/mRuBnmDwU0boNfPyFRhnan+Jm+haLeSn3P0afcBn4w==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", + "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", "engines": { - "node": ">=10" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/decamelize-keys": { @@ -10573,9 +10602,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "36.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-36.1.0.tgz", - "integrity": "sha512-Qpied2AJCQcScxfzTObLKRiP5QgLXjMU/ITjBagEV5p2Q/HpumD1EQtazdRYdjDSwPmXhwOl2yquwOGQ4HOJNw==", + "version": "36.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-36.1.1.tgz", + "integrity": "sha512-nuLDvH1EJaKx0PCa9oeQIxH6pACIhZd1gkalTUxZbaxxwokjs7TplqY0Q8Ew3CoZaf5aowm0g/Z3JGHCatt+gQ==", "dev": true, "dependencies": { "@es-joy/jsdoccomment": "0.10.8", @@ -12005,11 +12034,11 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, "node_modules/fast-xml-parser": { - "version": "3.20.0", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.20.0.tgz", - "integrity": "sha512-cMQwDJYVDjMPU56DviszewgMKuNzuf4NQSBuDf9RgZ6FKm5QEMxW05Za8lvnuL6moxoeZVUWBlL733WmovvV6g==", + "version": "3.20.3", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.20.3.tgz", + "integrity": "sha512-FfHJ/QCpo4K2gquBX7dIAcmShSBG4dMtYJ3ghSiR4w7YqlUujuamrM57C+mKLNWS3mvZzmm2B2Qx8Q6Gfw+lDQ==", "dependencies": { - "strnum": "^1.0.3" + "strnum": "^1.0.4" }, "bin": { "xml2js": "cli.js" @@ -13425,12 +13454,12 @@ } }, "node_modules/gatsby-plugin-catch-links": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/gatsby-plugin-catch-links/-/gatsby-plugin-catch-links-3.13.0.tgz", - "integrity": "sha512-IdxpkO6yLUHxFao4lSSDIbvD7UXYFxCBbVvl/PSOUcahMGWuVLudXgP5vrJfq95pbM3M7KjaX8NxuRyaz51OHg==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/gatsby-plugin-catch-links/-/gatsby-plugin-catch-links-3.14.0.tgz", + "integrity": "sha512-F1cydnQWrD6ObDJdBqyPmobEpS3rWYvD9rjLszIkCCcO/9orqOgpffbVJf0xdMnzStxqeyUPGze06Ld8YCtFIw==", "dev": true, "dependencies": { - "@babel/runtime": "^7.14.8", + "@babel/runtime": "^7.15.4", "escape-string-regexp": "^1.0.5" }, "engines": { @@ -15289,9 +15318,9 @@ "dev": true }, "node_modules/graphql": { - "version": "15.5.3", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.5.3.tgz", - "integrity": "sha512-sM+jXaO5KinTui6lbK/7b7H/Knj9BpjGxZ+Ki35v7YbUJxxdBCUqNM0h3CRVU1ZF9t5lNiBzvBCSYPvIwxPOQA==", + "version": "15.6.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.6.1.tgz", + "integrity": "sha512-3i5lu0z6dRvJ48QP9kFxBkJ7h4Kso7PS8eahyTFz5Jm6CvQfLtNIE8LX9N6JLnXTuwR+sIYnXzaWp6anOg0QQw==", "engines": { "node": ">= 10.x" } @@ -16332,9 +16361,9 @@ } }, "node_modules/ioredis": { - "version": "4.27.9", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.27.9.tgz", - "integrity": "sha512-hAwrx9F+OQ0uIvaJefuS3UTqW+ByOLyLIV+j0EH8ClNVxvFyH9Vmb08hCL4yje6mDYT5zMquShhypkd50RRzkg==", + "version": "4.27.10", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.27.10.tgz", + "integrity": "sha512-BtV2mEoZlhnW0EyxuK49V5iutLeZeJAYi/+Fuc4Q6DpDjq0cGMLODdS/+Kb5CHpT7v3YT6SK0vgJF6y0Ls4+Bg==", "dependencies": { "cluster-key-slot": "^1.1.0", "debug": "^4.3.1", @@ -17146,9 +17175,9 @@ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "node_modules/istanbul-lib-coverage": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", - "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.1.tgz", + "integrity": "sha512-GvCYYTxaCPqwMjobtVcVKvSHtAGe48MNhGjpK8LtVF8K0ISX7hCKl85LgtuaSneWVyQmaGcW3iXVV3GaZSLpmQ==", "dev": true, "engines": { "node": ">=8" @@ -17912,25 +17941,25 @@ } }, "node_modules/lint-staged": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-11.1.2.tgz", - "integrity": "sha512-6lYpNoA9wGqkL6Hew/4n1H6lRqF3qCsujVT0Oq5Z4hiSAM7S6NksPJ3gnr7A7R52xCtiZMcEUNNQ6d6X5Bvh9w==", + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-11.2.1.tgz", + "integrity": "sha512-p56vAvBwABYSThvncT1Vuq0u6A8ZS56oC+eURfoavqyhBPJv+RGAmIU2kEYQOO19LPQVHQJ56eoBq/ARPlBoVQ==", "dev": true, "dependencies": { - "chalk": "^4.1.1", - "cli-truncate": "^2.1.0", - "commander": "^7.2.0", - "cosmiconfig": "^7.0.0", - "debug": "^4.3.1", + "cli-truncate": "2.1.0", + "colorette": "^1.4.0", + "commander": "^8.2.0", + "cosmiconfig": "^7.0.1", + "debug": "^4.3.2", "enquirer": "^2.3.6", - "execa": "^5.0.0", - "listr2": "^3.8.2", - "log-symbols": "^4.1.0", + "execa": "^5.1.1", + "listr2": "^3.12.2", "micromatch": "^4.0.4", "normalize-path": "^3.0.0", "please-upgrade-node": "^3.2.0", "string-argv": "0.3.1", - "stringify-object": "^3.3.0" + "stringify-object": "3.3.0", + "supports-color": "8.1.1" }, "bin": { "lint-staged": "bin/lint-staged.js" @@ -17974,18 +18003,18 @@ } }, "node_modules/lint-staged/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.2.0.tgz", + "integrity": "sha512-LLKxDvHeL91/8MIyTAD5BFMNtoIwztGPMiM/7Bl8rIPmHCZXRxmSWr91h57dpOpnQ6jIUqEWdXE/uBYMfiVZDA==", "dev": true, "engines": { - "node": ">= 10" + "node": ">= 12" } }, "node_modules/lint-staged/node_modules/cosmiconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", - "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", "dev": true, "dependencies": { "@types/parse-json": "^4.0.0", @@ -18013,15 +18042,20 @@ } }, "node_modules/lint-staged/node_modules/debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "dependencies": { "ms": "2.1.2" }, "engines": { "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/lint-staged/node_modules/emoji-regex": { @@ -18031,9 +18065,9 @@ "dev": true }, "node_modules/lint-staged/node_modules/execa": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", - "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "dependencies": { "cross-spawn": "^7.0.3", @@ -18077,6 +18111,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lint-staged/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/lint-staged/node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -18105,12 +18148,15 @@ } }, "node_modules/lint-staged/node_modules/is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lint-staged/node_modules/micromatch": { @@ -18157,6 +18203,9 @@ }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lint-staged/node_modules/path-key": { @@ -18224,6 +18273,21 @@ "node": ">=8" } }, + "node_modules/lint-staged/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/lint-staged/node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -18252,13 +18316,13 @@ } }, "node_modules/listr2": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.10.0.tgz", - "integrity": "sha512-eP40ZHihu70sSmqFNbNy2NL1YwImmlMmPh9WO5sLmPDleurMHt3n+SwEWNu2kzKScexZnkyFtc1VI0z/TGlmpw==", + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.12.2.tgz", + "integrity": "sha512-64xC2CJ/As/xgVI3wbhlPWVPx0wfTqbUAkpb7bjDi0thSWMqrf07UFhrfsGoo8YSXmF049Rp9C0cjLC8rZxK9A==", "dev": true, "dependencies": { "cli-truncate": "^2.1.0", - "colorette": "^1.2.2", + "colorette": "^1.4.0", "log-update": "^4.0.0", "p-map": "^4.0.0", "rxjs": "^6.6.7", @@ -19671,16 +19735,16 @@ } }, "node_modules/mocha": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.1.tgz", - "integrity": "sha512-0wE74YMgOkCgBUj8VyIDwmLUjTsS13WV1Pg7l0SHea2qzZzlq7MDnfbPsHKcELBRk3+izEVkRofjmClpycudCA==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.2.tgz", + "integrity": "sha512-ta3LtJ+63RIBP03VBjMGtSqbe6cWXRejF9SyM9Zyli1CKZJZ+vfCTj3oW24V7wAphMJdpOFLoMI3hjJ1LWbs0w==", "dev": true, "dependencies": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", "chokidar": "3.5.2", - "debug": "4.3.1", + "debug": "4.3.2", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", @@ -19691,12 +19755,11 @@ "log-symbols": "4.1.0", "minimatch": "3.0.4", "ms": "2.1.3", - "nanoid": "3.1.23", + "nanoid": "3.1.25", "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", - "wide-align": "1.1.3", "workerpool": "6.1.5", "yargs": "16.2.0", "yargs-parser": "20.2.4", @@ -19755,37 +19818,40 @@ } }, "node_modules/mocha-junit-reporter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-2.0.0.tgz", - "integrity": "sha512-20HoWh2HEfhqmigfXOKUhZQyX23JImskc37ZOhIjBKoBEsb+4cAFRJpAVhFpnvsztLklW/gFVzsrobjLwmX4lA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-2.0.2.tgz", + "integrity": "sha512-vYwWq5hh3v1lG0gdQCBxwNipBfvDiAM1PHroQRNp96+2l72e9wEUTw+mzoK+O0SudgfQ7WvTQZ9Nh3qkAYAjfg==", "dev": true, "dependencies": { "debug": "^2.2.0", "md5": "^2.1.0", "mkdirp": "~0.5.1", - "strip-ansi": "^4.0.0", + "strip-ansi": "^6.0.1", "xml": "^1.0.0" + }, + "peerDependencies": { + "mocha": ">=2.2.5" } }, "node_modules/mocha-junit-reporter/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/mocha-junit-reporter/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "dependencies": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/mocha-teamcity-reporter": { @@ -19845,15 +19911,20 @@ } }, "node_modules/mocha/node_modules/debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "dependencies": { "ms": "2.1.2" }, "engines": { "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/mocha/node_modules/debug/node_modules/ms": { @@ -20115,9 +20186,9 @@ "dev": true }, "node_modules/nanoid": { - "version": "3.1.23", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", - "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", + "version": "3.1.25", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz", + "integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==", "dev": true, "bin": { "nanoid": "bin/nanoid.cjs" @@ -21017,6 +21088,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/open-cli/node_modules/decamelize": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", + "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/open-cli/node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -23027,6 +23110,12 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", + "dev": true + }, "node_modules/ps-tree": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", @@ -25131,9 +25220,9 @@ } }, "node_modules/simple-icons": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/simple-icons/-/simple-icons-5.15.0.tgz", - "integrity": "sha512-bzlD0K7HS5qgLMVzzfIxua8EzpYhTZ4yTYBQbGpeaih0DDdmsWbD41Dz9eTBpsjLEV2475FcWSi8bCQqTd8TQg==", + "version": "5.17.0", + "resolved": "https://registry.npmjs.org/simple-icons/-/simple-icons-5.17.0.tgz", + "integrity": "sha512-36ioBzflfG9MisXA0NwTpi5xq169awYXgKwhFhGSLyRz4+l7sZ53P9JrPXS4E4lguxd6LykJMpEH4yNhT6ooJg==", "engines": { "node": ">=0.12.18" } @@ -26433,40 +26522,6 @@ "lodash.maxby": "^4.6.0" } }, - "node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/string.prototype.matchall": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.5.tgz", @@ -26616,9 +26671,9 @@ } }, "node_modules/strnum": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.3.tgz", - "integrity": "sha512-GVoRjsqAYZkAH16GDzfTuafuwKxzKdaaCQyLaWf37gOP1e2PPbAKWoME1OmO+c4RCKMfNrrPRDLFCNBFU45N/A==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.4.tgz", + "integrity": "sha512-lMzNMfDpaQOLt4B2mEbfzYS0+T7dvCXeojnlGf6f1AygvWDMcWyXYaLbyICfjVu29sErR8fnRagQfBW/N/hGgw==" }, "node_modules/strtok3": { "version": "6.2.4", @@ -29319,15 +29374,6 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, - "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "dependencies": { - "string-width": "^1.0.2 || 2" - } - }, "node_modules/widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", @@ -29977,9 +30023,9 @@ } }, "@babel/code-frame": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", - "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", + "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", "dev": true, "requires": { "@babel/highlight": "^7.14.5" @@ -29992,20 +30038,20 @@ "dev": true }, "@babel/core": { - "version": "7.15.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.5.tgz", - "integrity": "sha512-pYgXxiwAgQpgM1bNkZsDEq85f0ggXMA5L7c+o3tskGMh2BunCI9QUwB9Z4jpvXUOuMdyGKiGKQiRe11VS6Jzvg==", + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.8.tgz", + "integrity": "sha512-3UG9dsxvYBMYwRv+gS41WKHno4K60/9GPy1CJaH6xy3Elq8CTtvtjT5R5jmNhXfCYLX2mTw+7/aq5ak/gOE0og==", "dev": true, "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.4", + "@babel/code-frame": "^7.15.8", + "@babel/generator": "^7.15.8", "@babel/helper-compilation-targets": "^7.15.4", - "@babel/helper-module-transforms": "^7.15.4", + "@babel/helper-module-transforms": "^7.15.8", "@babel/helpers": "^7.15.4", - "@babel/parser": "^7.15.5", + "@babel/parser": "^7.15.8", "@babel/template": "^7.15.4", "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4", + "@babel/types": "^7.15.6", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -30072,12 +30118,12 @@ } }, "@babel/generator": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.4.tgz", - "integrity": "sha512-d3itta0tu+UayjEORPNz6e1T3FtvWlP5N4V5M+lhp/CxT4oAA7/NcScnpRyspUMLK6tu9MNHmQHxRykuN2R7hw==", + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.8.tgz", + "integrity": "sha512-ECmAKstXbp1cvpTTZciZCgfOt6iN64lR0d+euv3UZisU5awfRawOvg07Utn/qBGuH4bRIEZKrA/4LzZyXhZr8g==", "dev": true, "requires": { - "@babel/types": "^7.15.4", + "@babel/types": "^7.15.6", "jsesc": "^2.5.1", "source-map": "^0.5.0" } @@ -30241,19 +30287,19 @@ } }, "@babel/helper-module-transforms": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.4.tgz", - "integrity": "sha512-9fHHSGE9zTC++KuXLZcB5FKgvlV83Ox+NLUmQTawovwlJ85+QMhk1CnVk406CQVj97LaWod6KVjl2Sfgw9Aktw==", + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.8.tgz", + "integrity": "sha512-DfAfA6PfpG8t4S6npwzLvTUpp0sS7JrcuaMiy1Y5645laRJIp/LiLGIBbQKaXSInK8tiGNI7FL7L8UvB8gdUZg==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.15.4", "@babel/helper-replace-supers": "^7.15.4", "@babel/helper-simple-access": "^7.15.4", "@babel/helper-split-export-declaration": "^7.15.4", - "@babel/helper-validator-identifier": "^7.14.9", + "@babel/helper-validator-identifier": "^7.15.7", "@babel/template": "^7.15.4", "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/types": "^7.15.6" } }, "@babel/helper-optimise-call-expression": { @@ -30322,9 +30368,9 @@ } }, "@babel/helper-validator-identifier": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", - "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", + "version": "7.15.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", + "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", "dev": true }, "@babel/helper-validator-option": { @@ -30402,9 +30448,9 @@ } }, "@babel/parser": { - "version": "7.15.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.6.tgz", - "integrity": "sha512-S/TSCcsRuCkmpUuoWijua0Snt+f3ewU/8spLo+4AXJCZfT0bVCzLD5MuOKdrx0mlAptbKzn5AdgEIIKXxXkz9Q==", + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.8.tgz", + "integrity": "sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA==", "dev": true }, "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { @@ -32758,47 +32804,47 @@ } }, "@sentry/core": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.13.2.tgz", - "integrity": "sha512-snXNNFLwlS7yYxKTX4DBXebvJK+6ikBWN6noQ1CHowvM3ReFBlrdrs0Z0SsSFEzXm2S4q7f6HHbm66GSQZ/8FQ==", - "requires": { - "@sentry/hub": "6.13.2", - "@sentry/minimal": "6.13.2", - "@sentry/types": "6.13.2", - "@sentry/utils": "6.13.2", + "version": "6.13.3", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.13.3.tgz", + "integrity": "sha512-obm3SjgCk8A7nB37b2AU1eq1q7gMoJRrGMv9VRIyfcG0Wlz/5lJ9O3ohUk+YZaaVfZMxXn6hFtsBiOWmlv7IIA==", + "requires": { + "@sentry/hub": "6.13.3", + "@sentry/minimal": "6.13.3", + "@sentry/types": "6.13.3", + "@sentry/utils": "6.13.3", "tslib": "^1.9.3" } }, "@sentry/hub": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.13.2.tgz", - "integrity": "sha512-sppSuJdNMiMC/vFm/dQowCBh11uTrmvks00fc190YWgxHshodJwXMdpc+pN61VSOmy2QA4MbQ5aMAgHzPzel3A==", + "version": "6.13.3", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.13.3.tgz", + "integrity": "sha512-eYppBVqvhs5cvm33snW2sxfcw6G20/74RbBn+E4WDo15hozis89kU7ZCJDOPkXuag3v1h9igns/kM6PNBb41dw==", "requires": { - "@sentry/types": "6.13.2", - "@sentry/utils": "6.13.2", + "@sentry/types": "6.13.3", + "@sentry/utils": "6.13.3", "tslib": "^1.9.3" } }, "@sentry/minimal": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.13.2.tgz", - "integrity": "sha512-6iJfEvHzzpGBHDfLxSHcGObh73XU1OSQKWjuhDOe7UQDyI4BQmTfcXAC+Fr8sm8C/tIsmpVi/XJhs8cubFdSMw==", + "version": "6.13.3", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.13.3.tgz", + "integrity": "sha512-63MlYYRni3fs5Bh8XBAfVZ+ctDdWg0fapSTP1ydIC37fKvbE+5zhyUqwrEKBIiclEApg1VKX7bkKxVdu/vsFdw==", "requires": { - "@sentry/hub": "6.13.2", - "@sentry/types": "6.13.2", + "@sentry/hub": "6.13.3", + "@sentry/types": "6.13.3", "tslib": "^1.9.3" } }, "@sentry/node": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-6.13.2.tgz", - "integrity": "sha512-0Vw22amG143MTiNaSny66YGU3+uW7HxyGI9TLGE7aJY1nNmC0DE+OgqQYGBRCrrPu+VFXRDxrOg9b15A1gKqjA==", - "requires": { - "@sentry/core": "6.13.2", - "@sentry/hub": "6.13.2", - "@sentry/tracing": "6.13.2", - "@sentry/types": "6.13.2", - "@sentry/utils": "6.13.2", + "version": "6.13.3", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-6.13.3.tgz", + "integrity": "sha512-ZeZSw+TcPcf4e0j7iEqNMtoVmz+WFW/TEoGokXIwysZqSgchKdAXDHqn+CqUqFan7d76JcJmzztAUK2JruQ2Kg==", + "requires": { + "@sentry/core": "6.13.3", + "@sentry/hub": "6.13.3", + "@sentry/tracing": "6.13.3", + "@sentry/types": "6.13.3", + "@sentry/utils": "6.13.3", "cookie": "^0.4.1", "https-proxy-agent": "^5.0.0", "lru_map": "^0.3.3", @@ -32838,28 +32884,28 @@ } }, "@sentry/tracing": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.13.2.tgz", - "integrity": "sha512-bHJz+C/nd6biWTNcYAu91JeRilsvVgaye4POkdzWSmD0XoLWHVMrpCQobGpXe7onkp2noU3YQjhqgtBqPHtnpw==", - "requires": { - "@sentry/hub": "6.13.2", - "@sentry/minimal": "6.13.2", - "@sentry/types": "6.13.2", - "@sentry/utils": "6.13.2", + "version": "6.13.3", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.13.3.tgz", + "integrity": "sha512-yyOFIhqlprPM0g4f35Icear3eZk2mwyYcGEzljJfY2iU6pJwj1lzia5PfSwiCW7jFGMmlBJNhOAIpfhlliZi8Q==", + "requires": { + "@sentry/hub": "6.13.3", + "@sentry/minimal": "6.13.3", + "@sentry/types": "6.13.3", + "@sentry/utils": "6.13.3", "tslib": "^1.9.3" } }, "@sentry/types": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.13.2.tgz", - "integrity": "sha512-6WjGj/VjjN8LZDtqJH5ikeB1o39rO1gYS6anBxiS3d0sXNBb3Ux0pNNDFoBxQpOhmdDHXYS57MEptX9EV82gmg==" + "version": "6.13.3", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.13.3.tgz", + "integrity": "sha512-Vrz5CdhaTRSvCQjSyIFIaV9PodjAVFkzJkTRxyY7P77RcegMsRSsG1yzlvCtA99zG9+e6MfoJOgbOCwuZids5A==" }, "@sentry/utils": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.13.2.tgz", - "integrity": "sha512-foF4PbxqPMWNbuqdXkdoOmKm3quu3PP7Q7j/0pXkri4DtCuvF/lKY92mbY0V9rHS/phCoj+3/Se5JvM2ymh2/w==", + "version": "6.13.3", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.13.3.tgz", + "integrity": "sha512-zYFuFH3MaYtBZTeJ4Yajg7pDf0pM3MWs3+9k5my9Fd+eqNcl7dYQYJbT9gyC0HXK1QI4CAMNNlHNl4YXhF91ag==", "requires": { - "@sentry/types": "6.13.2", + "@sentry/types": "6.13.3", "tslib": "^1.9.3" } }, @@ -33326,9 +33372,9 @@ } }, "@types/react-helmet": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.2.tgz", - "integrity": "sha512-dcfAZNlWb5JYFbO9CGfrPWLJAyFcT6UeR3u35eBbv8liY2Rg4K7fM1G5+HnwVgot+C+kVwXAZ8pLEn2jsMfTDg==", + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.3.tgz", + "integrity": "sha512-U4onVxaZxAp78KpXsfmyCIhLjsvJJ3goG3CYFOo+xW0cPYAz9oe5cBAUSAcN7l35OTbrFvu9TuE0YkcZMKGr4A==", "dev": true, "requires": { "@types/react": "*" @@ -33405,9 +33451,9 @@ "dev": true }, "@types/styled-components": { - "version": "5.1.14", - "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.14.tgz", - "integrity": "sha512-d6P1/tyNytqKwam3cQXq7a9uPtovc/mdAs7dBiz1YbDdNIT3X4WmuFU78YdSYh84TXVuhOwezZ3EeKuNBhwsHQ==", + "version": "5.1.15", + "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.15.tgz", + "integrity": "sha512-4evch8BRI3AKgb0GAZ/sn+mSeB+Dq7meYtMi7J/0Mg98Dt1+r8fySOek7Sjw1W+Wskyjc93565o5xWAT/FdY0Q==", "dev": true, "requires": { "@types/hoist-non-react-statics": "*", @@ -33476,20 +33522,47 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.31.0.tgz", - "integrity": "sha512-iPKZTZNavAlOhfF4gymiSuUkgLne/nh5Oz2/mdiUmuZVD42m9PapnCnzjxuDsnpnbH3wT5s2D8bw6S39TC6GNw==", + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz", + "integrity": "sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "4.31.0", - "@typescript-eslint/scope-manager": "4.31.0", + "@typescript-eslint/experimental-utils": "4.33.0", + "@typescript-eslint/scope-manager": "4.33.0", "debug": "^4.3.1", "functional-red-black-tree": "^1.0.1", + "ignore": "^5.1.8", "regexpp": "^3.1.0", "semver": "^7.3.5", "tsutils": "^3.21.0" }, "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz", + "integrity": "sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/visitor-keys": "4.33.0" + } + }, + "@typescript-eslint/types": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz", + "integrity": "sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==", + "dev": true + }, + "@typescript-eslint/visitor-keys": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz", + "integrity": "sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.33.0", + "eslint-visitor-keys": "^2.0.0" + } + }, "debug": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", @@ -33499,6 +33572,18 @@ "ms": "2.1.2" } }, + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -33508,72 +33593,43 @@ } }, "@typescript-eslint/experimental-utils": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.31.0.tgz", - "integrity": "sha512-Hld+EQiKLMppgKKkdUsLeVIeEOrwKc2G983NmznY/r5/ZtZCDvIOXnXtwqJIgYz/ymsy7n7RGvMyrzf1WaSQrw==", + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz", + "integrity": "sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==", "dev": true, "requires": { "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.31.0", - "@typescript-eslint/types": "4.31.0", - "@typescript-eslint/typescript-estree": "4.31.0", + "@typescript-eslint/scope-manager": "4.33.0", + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/typescript-estree": "4.33.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" }, - "dependencies": { - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - } - }, - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, - "@typescript-eslint/parser": { - "version": "4.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.30.0.tgz", - "integrity": "sha512-HJ0XuluSZSxeboLU7Q2VQ6eLlCwXPBOGnA7CqgBnz2Db3JRQYyBDJgQnop6TZ+rsbSx5gEdWhw4rE4mDa1FnZg==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "4.30.0", - "@typescript-eslint/types": "4.30.0", - "@typescript-eslint/typescript-estree": "4.30.0", - "debug": "^4.3.1" - }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "4.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.30.0.tgz", - "integrity": "sha512-VJ/jAXovxNh7rIXCQbYhkyV2Y3Ac/0cVHP/FruTJSAUUm4Oacmn/nkN5zfWmWFEanN4ggP0vJSHOeajtHq3f8A==", + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz", + "integrity": "sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==", "dev": true, "requires": { - "@typescript-eslint/types": "4.30.0", - "@typescript-eslint/visitor-keys": "4.30.0" + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/visitor-keys": "4.33.0" } }, "@typescript-eslint/types": { - "version": "4.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.30.0.tgz", - "integrity": "sha512-YKldqbNU9K4WpTNwBqtAerQKLLW/X2A/j4yw92e3ZJYLx+BpKLeheyzoPfzIXHfM8BXfoleTdiYwpsvVPvHrDw==", + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz", + "integrity": "sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "4.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.30.0.tgz", - "integrity": "sha512-6WN7UFYvykr/U0Qgy4kz48iGPWILvYL34xXJxvDQeiRE018B7POspNRVtAZscWntEPZpFCx4hcz/XBT+erenfg==", + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz", + "integrity": "sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==", "dev": true, "requires": { - "@typescript-eslint/types": "4.30.0", - "@typescript-eslint/visitor-keys": "4.30.0", + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/visitor-keys": "4.33.0", "debug": "^4.3.1", "globby": "^11.0.3", "is-glob": "^4.0.1", @@ -33582,24 +33638,33 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "4.30.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.30.0.tgz", - "integrity": "sha512-pNaaxDt/Ol/+JZwzP7MqWc8PJQTUhZwoee/PVlQ+iYoYhagccvoHnC9e4l+C/krQYYkENxznhVSDwClIbZVxRw==", + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz", + "integrity": "sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==", "dev": true, "requires": { - "@typescript-eslint/types": "4.30.0", + "@typescript-eslint/types": "4.33.0", "eslint-visitor-keys": "^2.0.0" } }, "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { "ms": "2.1.2" } }, + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + } + }, "eslint-visitor-keys": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", @@ -33634,30 +33699,59 @@ } } }, + "@typescript-eslint/parser": { + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.32.0.tgz", + "integrity": "sha512-lhtYqQ2iEPV5JqV7K+uOVlPePjClj4dOw7K4/Z1F2yvjIUvyr13yJnDzkK6uon4BjHYuHy3EG0c2Z9jEhFk56w==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "4.32.0", + "@typescript-eslint/types": "4.32.0", + "@typescript-eslint/typescript-estree": "4.32.0", + "debug": "^4.3.1" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "@typescript-eslint/scope-manager": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.31.0.tgz", - "integrity": "sha512-LJ+xtl34W76JMRLjbaQorhR0hfRAlp3Lscdiz9NeI/8i+q0hdBZ7BsiYieLoYWqy+AnRigaD3hUwPFugSzdocg==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.32.0.tgz", + "integrity": "sha512-DK+fMSHdM216C0OM/KR1lHXjP1CNtVIhJ54kQxfOE6x8UGFAjha8cXgDMBEIYS2XCYjjCtvTkjQYwL3uvGOo0w==", "dev": true, "requires": { - "@typescript-eslint/types": "4.31.0", - "@typescript-eslint/visitor-keys": "4.31.0" + "@typescript-eslint/types": "4.32.0", + "@typescript-eslint/visitor-keys": "4.32.0" } }, "@typescript-eslint/types": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.31.0.tgz", - "integrity": "sha512-9XR5q9mk7DCXgXLS7REIVs+BaAswfdHhx91XqlJklmqWpTALGjygWVIb/UnLh4NWhfwhR5wNe1yTyCInxVhLqQ==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.32.0.tgz", + "integrity": "sha512-LE7Z7BAv0E2UvqzogssGf1x7GPpUalgG07nGCBYb1oK4mFsOiFC/VrSMKbZQzFJdN2JL5XYmsx7C7FX9p9ns0w==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.31.0.tgz", - "integrity": "sha512-QHl2014t3ptg+xpmOSSPn5hm4mY8D4s97ftzyk9BZ8RxYQ3j73XcwuijnJ9cMa6DO4aLXeo8XS3z1omT9LA/Eg==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.32.0.tgz", + "integrity": "sha512-tRYCgJ3g1UjMw1cGG8Yn1KzOzNlQ6u1h9AmEtPhb5V5a1TmiHWcRyF/Ic+91M4f43QeChyYlVTcf3DvDTZR9vw==", "dev": true, "requires": { - "@typescript-eslint/types": "4.31.0", - "@typescript-eslint/visitor-keys": "4.31.0", + "@typescript-eslint/types": "4.32.0", + "@typescript-eslint/visitor-keys": "4.32.0", "debug": "^4.3.1", "globby": "^11.0.3", "is-glob": "^4.0.1", @@ -33703,12 +33797,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "4.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.31.0.tgz", - "integrity": "sha512-HUcRp2a9I+P21+O21yu3ezv3GEPGjyGiXoEUQwZXjR8UxRApGeLyWH4ZIIUSalE28aG4YsV6GjtaAVB3QKOu0w==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.32.0.tgz", + "integrity": "sha512-e7NE0qz8W+atzv3Cy9qaQ7BTLwWsm084Z0c4nIO2l3Bp6u9WIgdqCgyPyV5oSPDMIW3b20H59OOCmVk3jw3Ptw==", "dev": true, "requires": { - "@typescript-eslint/types": "4.31.0", + "@typescript-eslint/types": "4.32.0", "eslint-visitor-keys": "^2.0.0" }, "dependencies": { @@ -35015,16 +35109,16 @@ "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" }, "c8": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/c8/-/c8-7.9.0.tgz", - "integrity": "sha512-aQ7dC8gASnKdBwHUuYuzsdKCEDrKnWr7ZuZUnf4CNAL81oyKloKrs7H7zYvcrmCtIrMToudBSUhq2q+LLBMvgg==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/c8/-/c8-7.10.0.tgz", + "integrity": "sha512-OAwfC5+emvA6R7pkYFVBTOtI5ruf9DahffGmIqUc9l6wEh0h7iAFP6dt/V9Ioqlr2zW5avX9U9/w1I4alTRHkA==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", "@istanbuljs/schema": "^0.1.2", "find-up": "^5.0.0", "foreground-child": "^2.0.0", - "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-coverage": "^3.0.1", "istanbul-lib-report": "^3.0.0", "istanbul-reports": "^3.0.2", "rimraf": "^3.0.0", @@ -35911,9 +36005,9 @@ } }, "colorette": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz", - "integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", "dev": true }, "colors": { @@ -36031,15 +36125,14 @@ } }, "concurrently": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-6.2.1.tgz", - "integrity": "sha512-emgwhH+ezkuYKSHZQ+AkgEpoUZZlbpPVYCVv7YZx0r+T7fny1H03r2nYRebpi2DudHR4n1Rgbo2YTxKOxVJ4+g==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-6.3.0.tgz", + "integrity": "sha512-k4k1jQGHHKsfbqzkUszVf29qECBrkvBKkcPJEUDTyVR7tZd1G/JOfnst4g1sYbFvJ4UjHZisj1aWQR8yLKpGPw==", "dev": true, "requires": { "chalk": "^4.1.0", "date-fns": "^2.16.1", "lodash": "^4.17.21", - "read-pkg": "^5.2.0", "rxjs": "^6.6.3", "spawn-command": "^0.0.2-1", "supports-color": "^8.1.0", @@ -36059,48 +36152,6 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, "supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -36109,12 +36160,6 @@ "requires": { "has-flag": "^4.0.0" } - }, - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true } } }, @@ -36750,9 +36795,9 @@ "dev": true }, "cypress": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-8.4.1.tgz", - "integrity": "sha512-itJXq0Vx3sXCUrDyBi2IUrkxVu/gTTp1VhjB5tzGgkeCR8Ae+/T8WV63rsZ7fS8Tpq7LPPXiyoM/sEdOX7cR6A==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-8.5.0.tgz", + "integrity": "sha512-MMkXIS+Ro2KETn4gAlG3tIc/7FiljuuCZP0zpd9QsRG6MZSyZW/l1J3D4iQM6WHsVxuX4rFChn5jPFlC2tNSvQ==", "dev": true, "requires": { "@cypress/request": "^2.88.6", @@ -36789,6 +36834,7 @@ "minimist": "^1.2.5", "ospath": "^1.2.2", "pretty-bytes": "^5.6.0", + "proxy-from-env": "1.0.0", "ramda": "~0.27.1", "request-progress": "^3.0.0", "supports-color": "^8.1.1", @@ -37117,9 +37163,9 @@ } }, "decamelize": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.0.tgz", - "integrity": "sha512-U75DcT5hrio3KNtvdULAWnLiAPbFUC4191ldxMmj4FA/mRuBnmDwU0boNfPyFRhnan+Jm+haLeSn3P0afcBn4w==" + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-6.0.0.tgz", + "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==" }, "decamelize-keys": { "version": "1.1.0", @@ -38464,9 +38510,9 @@ } }, "eslint-plugin-jsdoc": { - "version": "36.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-36.1.0.tgz", - "integrity": "sha512-Qpied2AJCQcScxfzTObLKRiP5QgLXjMU/ITjBagEV5p2Q/HpumD1EQtazdRYdjDSwPmXhwOl2yquwOGQ4HOJNw==", + "version": "36.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-36.1.1.tgz", + "integrity": "sha512-nuLDvH1EJaKx0PCa9oeQIxH6pACIhZd1gkalTUxZbaxxwokjs7TplqY0Q8Ew3CoZaf5aowm0g/Z3JGHCatt+gQ==", "dev": true, "requires": { "@es-joy/jsdoccomment": "0.10.8", @@ -39397,11 +39443,11 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, "fast-xml-parser": { - "version": "3.20.0", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.20.0.tgz", - "integrity": "sha512-cMQwDJYVDjMPU56DviszewgMKuNzuf4NQSBuDf9RgZ6FKm5QEMxW05Za8lvnuL6moxoeZVUWBlL733WmovvV6g==", + "version": "3.20.3", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.20.3.tgz", + "integrity": "sha512-FfHJ/QCpo4K2gquBX7dIAcmShSBG4dMtYJ3ghSiR4w7YqlUujuamrM57C+mKLNWS3mvZzmm2B2Qx8Q6Gfw+lDQ==", "requires": { - "strnum": "^1.0.3" + "strnum": "^1.0.4" } }, "fastest-levenshtein": { @@ -41067,12 +41113,12 @@ } }, "gatsby-plugin-catch-links": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/gatsby-plugin-catch-links/-/gatsby-plugin-catch-links-3.13.0.tgz", - "integrity": "sha512-IdxpkO6yLUHxFao4lSSDIbvD7UXYFxCBbVvl/PSOUcahMGWuVLudXgP5vrJfq95pbM3M7KjaX8NxuRyaz51OHg==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/gatsby-plugin-catch-links/-/gatsby-plugin-catch-links-3.14.0.tgz", + "integrity": "sha512-F1cydnQWrD6ObDJdBqyPmobEpS3rWYvD9rjLszIkCCcO/9orqOgpffbVJf0xdMnzStxqeyUPGze06Ld8YCtFIw==", "dev": true, "requires": { - "@babel/runtime": "^7.14.8", + "@babel/runtime": "^7.15.4", "escape-string-regexp": "^1.0.5" }, "dependencies": { @@ -41930,9 +41976,9 @@ "dev": true }, "graphql": { - "version": "15.5.3", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.5.3.tgz", - "integrity": "sha512-sM+jXaO5KinTui6lbK/7b7H/Knj9BpjGxZ+Ki35v7YbUJxxdBCUqNM0h3CRVU1ZF9t5lNiBzvBCSYPvIwxPOQA==" + "version": "15.6.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.6.1.tgz", + "integrity": "sha512-3i5lu0z6dRvJ48QP9kFxBkJ7h4Kso7PS8eahyTFz5Jm6CvQfLtNIE8LX9N6JLnXTuwR+sIYnXzaWp6anOg0QQw==" }, "graphql-compose": { "version": "7.25.1", @@ -42771,9 +42817,9 @@ } }, "ioredis": { - "version": "4.27.9", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.27.9.tgz", - "integrity": "sha512-hAwrx9F+OQ0uIvaJefuS3UTqW+ByOLyLIV+j0EH8ClNVxvFyH9Vmb08hCL4yje6mDYT5zMquShhypkd50RRzkg==", + "version": "4.27.10", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.27.10.tgz", + "integrity": "sha512-BtV2mEoZlhnW0EyxuK49V5iutLeZeJAYi/+Fuc4Q6DpDjq0cGMLODdS/+Kb5CHpT7v3YT6SK0vgJF6y0Ls4+Bg==", "requires": { "cluster-key-slot": "^1.1.0", "debug": "^4.3.1", @@ -43361,9 +43407,9 @@ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "istanbul-lib-coverage": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", - "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.1.tgz", + "integrity": "sha512-GvCYYTxaCPqwMjobtVcVKvSHtAGe48MNhGjpK8LtVF8K0ISX7hCKl85LgtuaSneWVyQmaGcW3iXVV3GaZSLpmQ==", "dev": true }, "istanbul-lib-instrument": { @@ -43995,25 +44041,25 @@ } }, "lint-staged": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-11.1.2.tgz", - "integrity": "sha512-6lYpNoA9wGqkL6Hew/4n1H6lRqF3qCsujVT0Oq5Z4hiSAM7S6NksPJ3gnr7A7R52xCtiZMcEUNNQ6d6X5Bvh9w==", + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-11.2.1.tgz", + "integrity": "sha512-p56vAvBwABYSThvncT1Vuq0u6A8ZS56oC+eURfoavqyhBPJv+RGAmIU2kEYQOO19LPQVHQJ56eoBq/ARPlBoVQ==", "dev": true, "requires": { - "chalk": "^4.1.1", - "cli-truncate": "^2.1.0", - "commander": "^7.2.0", - "cosmiconfig": "^7.0.0", - "debug": "^4.3.1", + "cli-truncate": "2.1.0", + "colorette": "^1.4.0", + "commander": "^8.2.0", + "cosmiconfig": "^7.0.1", + "debug": "^4.3.2", "enquirer": "^2.3.6", - "execa": "^5.0.0", - "listr2": "^3.8.2", - "log-symbols": "^4.1.0", + "execa": "^5.1.1", + "listr2": "^3.12.2", "micromatch": "^4.0.4", "normalize-path": "^3.0.0", "please-upgrade-node": "^3.2.0", "string-argv": "0.3.1", - "stringify-object": "^3.3.0" + "stringify-object": "3.3.0", + "supports-color": "8.1.1" }, "dependencies": { "ansi-regex": { @@ -44042,15 +44088,15 @@ } }, "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.2.0.tgz", + "integrity": "sha512-LLKxDvHeL91/8MIyTAD5BFMNtoIwztGPMiM/7Bl8rIPmHCZXRxmSWr91h57dpOpnQ6jIUqEWdXE/uBYMfiVZDA==", "dev": true }, "cosmiconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", - "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", "dev": true, "requires": { "@types/parse-json": "^4.0.0", @@ -44072,9 +44118,9 @@ } }, "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { "ms": "2.1.2" @@ -44087,9 +44133,9 @@ "dev": true }, "execa": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", - "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "requires": { "cross-spawn": "^7.0.3", @@ -44118,6 +44164,12 @@ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -44137,9 +44189,9 @@ "dev": true }, "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true }, "micromatch": { @@ -44226,6 +44278,15 @@ "ansi-regex": "^5.0.0" } }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -44247,13 +44308,13 @@ } }, "listr2": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.10.0.tgz", - "integrity": "sha512-eP40ZHihu70sSmqFNbNy2NL1YwImmlMmPh9WO5sLmPDleurMHt3n+SwEWNu2kzKScexZnkyFtc1VI0z/TGlmpw==", + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.12.2.tgz", + "integrity": "sha512-64xC2CJ/As/xgVI3wbhlPWVPx0wfTqbUAkpb7bjDi0thSWMqrf07UFhrfsGoo8YSXmF049Rp9C0cjLC8rZxK9A==", "dev": true, "requires": { "cli-truncate": "^2.1.0", - "colorette": "^1.2.2", + "colorette": "^1.4.0", "log-update": "^4.0.0", "p-map": "^4.0.0", "rxjs": "^6.6.7", @@ -45377,16 +45438,16 @@ } }, "mocha": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.1.tgz", - "integrity": "sha512-0wE74YMgOkCgBUj8VyIDwmLUjTsS13WV1Pg7l0SHea2qzZzlq7MDnfbPsHKcELBRk3+izEVkRofjmClpycudCA==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.2.tgz", + "integrity": "sha512-ta3LtJ+63RIBP03VBjMGtSqbe6cWXRejF9SyM9Zyli1CKZJZ+vfCTj3oW24V7wAphMJdpOFLoMI3hjJ1LWbs0w==", "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", "chokidar": "3.5.2", - "debug": "4.3.1", + "debug": "4.3.2", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", @@ -45397,12 +45458,11 @@ "log-symbols": "4.1.0", "minimatch": "3.0.4", "ms": "2.1.3", - "nanoid": "3.1.23", + "nanoid": "3.1.25", "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", - "wide-align": "1.1.3", "workerpool": "6.1.5", "yargs": "16.2.0", "yargs-parser": "20.2.4", @@ -45416,9 +45476,9 @@ "dev": true }, "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { "ms": "2.1.2" @@ -45585,31 +45645,31 @@ } }, "mocha-junit-reporter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-2.0.0.tgz", - "integrity": "sha512-20HoWh2HEfhqmigfXOKUhZQyX23JImskc37ZOhIjBKoBEsb+4cAFRJpAVhFpnvsztLklW/gFVzsrobjLwmX4lA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-2.0.2.tgz", + "integrity": "sha512-vYwWq5hh3v1lG0gdQCBxwNipBfvDiAM1PHroQRNp96+2l72e9wEUTw+mzoK+O0SudgfQ7WvTQZ9Nh3qkAYAjfg==", "dev": true, "requires": { "debug": "^2.2.0", "md5": "^2.1.0", "mkdirp": "~0.5.1", - "strip-ansi": "^4.0.0", + "strip-ansi": "^6.0.1", "xml": "^1.0.0" }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^5.0.1" } } } @@ -45731,9 +45791,9 @@ "dev": true }, "nanoid": { - "version": "3.1.23", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", - "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", + "version": "3.1.25", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz", + "integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==", "dev": true }, "nanomatch": { @@ -46427,6 +46487,12 @@ "quick-lru": "^4.0.1" } }, + "decamelize": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", + "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", + "dev": true + }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -47900,6 +47966,12 @@ "ipaddr.js": "1.9.1" } }, + "proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", + "dev": true + }, "ps-tree": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", @@ -49609,9 +49681,9 @@ "dev": true }, "simple-icons": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/simple-icons/-/simple-icons-5.15.0.tgz", - "integrity": "sha512-bzlD0K7HS5qgLMVzzfIxua8EzpYhTZ4yTYBQbGpeaih0DDdmsWbD41Dz9eTBpsjLEV2475FcWSi8bCQqTd8TQg==" + "version": "5.17.0", + "resolved": "https://registry.npmjs.org/simple-icons/-/simple-icons-5.17.0.tgz", + "integrity": "sha512-36ioBzflfG9MisXA0NwTpi5xq169awYXgKwhFhGSLyRz4+l7sZ53P9JrPXS4E4lguxd6LykJMpEH4yNhT6ooJg==" }, "simple-swizzle": { "version": "0.2.2", @@ -50700,33 +50772,6 @@ "lodash.maxby": "^4.6.0" } }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, "string.prototype.matchall": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.5.tgz", @@ -50839,9 +50884,9 @@ "dev": true }, "strnum": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.3.tgz", - "integrity": "sha512-GVoRjsqAYZkAH16GDzfTuafuwKxzKdaaCQyLaWf37gOP1e2PPbAKWoME1OmO+c4RCKMfNrrPRDLFCNBFU45N/A==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.4.tgz", + "integrity": "sha512-lMzNMfDpaQOLt4B2mEbfzYS0+T7dvCXeojnlGf6f1AygvWDMcWyXYaLbyICfjVu29sErR8fnRagQfBW/N/hGgw==" }, "strtok3": { "version": "6.2.4", @@ -52907,15 +52952,6 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, "widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", diff --git a/package.json b/package.json index d84f750c9bc1e..1078ad3f77cb2 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "dependencies": { "@fontsource/lato": "^4.5.0", "@fontsource/lekton": "^4.5.0", - "@sentry/node": "^6.13.2", + "@sentry/node": "^6.13.3", "@shields_io/camp": "^18.1.1", "badge-maker": "file:badge-maker", "bytes": "^3.1.0", @@ -34,16 +34,16 @@ "cloudflare-middleware": "^1.0.4", "config": "^3.3.6", "cross-env": "^7.0.3", - "decamelize": "^5.0.0", + "decamelize": "^6.0.0", "emojic": "^1.1.16", "escape-string-regexp": "^4.0.0", - "fast-xml-parser": "^3.20.0", + "fast-xml-parser": "^3.20.3", "glob": "^7.2.0", "global-agent": "^3.0.0", "got": "11.8.2", - "graphql": "^15.5.3", + "graphql": "^15.6.1", "graphql-tag": "^2.12.5", - "ioredis": "4.27.9", + "ioredis": "4.27.10", "joi": "17.4.2", "joi-extension-semver": "5.0.0", "js-yaml": "^4.1.0", @@ -53,6 +53,7 @@ "lodash.times": "^4.3.2", "moment": "^2.29.1", "node-env-flag": "^0.1.0", + "node-fetch": "^2.6.1", "parse-link-header": "^1.0.1", "path-to-regexp": "^6.2.0", "pretty-bytes": "^5.6.0", @@ -62,7 +63,7 @@ "query-string": "^7.0.1", "request": "~2.88.2", "semver": "~7.3.5", - "simple-icons": "5.15.0", + "simple-icons": "5.17.0", "webextension-store-meta": "^1.0.4", "xmldom": "~0.6.0", "xpath": "~0.0.32" @@ -142,7 +143,7 @@ ] }, "devDependencies": { - "@babel/core": "^7.15.5", + "@babel/core": "^7.15.8", "@babel/polyfill": "^7.12.1", "@babel/register": "7.15.3", "@mapbox/react-click-to-select": "^2.2.1", @@ -151,16 +152,16 @@ "@types/lodash.groupby": "^4.6.6", "@types/mocha": "^9.0.0", "@types/node": "^16.7.10", - "@types/react-helmet": "^6.1.2", + "@types/react-helmet": "^6.1.3", "@types/react-modal": "^3.12.1", "@types/react-select": "^4.0.17", - "@types/styled-components": "5.1.14", - "@typescript-eslint/eslint-plugin": "^4.31.0", - "@typescript-eslint/parser": "^4.30.0", + "@types/styled-components": "5.1.15", + "@typescript-eslint/eslint-plugin": "^4.33.0", + "@typescript-eslint/parser": "^4.32.0", "babel-plugin-inline-react-svg": "^2.0.1", "babel-plugin-istanbul": "^6.0.0", "babel-preset-gatsby": "^1.14.0", - "c8": "^7.9.0", + "c8": "^7.10.0", "caller": "^1.0.1", "chai": "^4.3.4", "chai-as-promised": "^7.1.1", @@ -168,8 +169,8 @@ "chai-string": "^1.4.0", "child-process-promise": "^2.2.1", "clipboard-copy": "^4.0.1", - "concurrently": "^6.2.1", - "cypress": "^8.4.1", + "concurrently": "^6.3.0", + "cypress": "^8.5.0", "danger": "^10.6.6", "danger-plugin-no-test-shortcuts": "^2.0.0", "deepmerge": "^4.2.2", @@ -181,7 +182,7 @@ "eslint-plugin-chai-friendly": "^0.7.2", "eslint-plugin-cypress": "^2.12.1", "eslint-plugin-import": "^2.24.2", - "eslint-plugin-jsdoc": "^36.1.0", + "eslint-plugin-jsdoc": "^36.1.1", "eslint-plugin-mocha": "^9.0.0", "eslint-plugin-no-extension-in-require": "^0.2.0", "eslint-plugin-node": "^11.1.0", @@ -192,7 +193,7 @@ "fetch-ponyfill": "^7.1.0", "form-data": "^4.0.0", "gatsby": "3.13.1", - "gatsby-plugin-catch-links": "^3.13.0", + "gatsby-plugin-catch-links": "^3.14.0", "gatsby-plugin-page-creator": "^3.14.0", "gatsby-plugin-react-helmet": "^4.14.0", "gatsby-plugin-remove-trailing-slashes": "^3.14.0", @@ -204,13 +205,13 @@ "is-svg": "^4.3.1", "js-yaml-loader": "^1.2.2", "jsdoc": "^3.6.7", - "lint-staged": "^11.1.2", + "lint-staged": "^11.2.1", "lodash.debounce": "^4.0.8", "lodash.difference": "^4.5.0", "minimist": "^1.2.5", - "mocha": "^9.1.1", + "mocha": "^9.1.2", "mocha-env-reporter": "^4.0.0", - "mocha-junit-reporter": "^2.0.0", + "mocha-junit-reporter": "^2.0.2", "mocha-yaml-loader": "^1.0.3", "nock": "13.1.3", "node-mocks-http": "^1.11.0", diff --git a/scripts/github_token_backup.fish b/scripts/github_token_backup.fish deleted file mode 100755 index 8aef250809784..0000000000000 --- a/scripts/github_token_backup.fish +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env fish -# -# Back up the GitHub tokens from each production server. -# - -if test (count $argv) -lt 1 - echo Usage: (basename (status -f)) shields_secret -end - -set shields_secret $argv[1] - -function do_backup - set server $argv[1] - curl --insecure -u ":$shields_secret" "https://$server.servers.shields.io/\$github-auth/tokens" > "$server""_tokens.json" -end - -for server in s0 s1 s2 - do_backup $server -end diff --git a/services/appveyor/appveyor-tests.service.js b/services/appveyor/appveyor-tests.service.js index 465130445eb49..6b8951db3caba 100644 --- a/services/appveyor/appveyor-tests.service.js +++ b/services/appveyor/appveyor-tests.service.js @@ -1,31 +1,10 @@ import { testResultQueryParamSchema, renderTestResultBadge, + documentation, } from '../test-results.js' import AppVeyorBase from './appveyor-base.js' -const documentation = ` -

- You may change the "passed", "failed" and "skipped" text on this badge by supplying query parameters &passed_label=, &failed_label= and &skipped_label= respectively. -

- -

- For example, if you want to use a different terminology: -
- /appveyor/tests/NZSmartie/coap-net-iu0to.svg?passed_label=good&failed_label=bad&skipped_label=n%2Fa -

- -

- Or symbols: -
- /appveyor/tests/NZSmartie/coap-net-iu0to.svg?compact_message&passed_label=%F0%9F%8E%89&failed_label=%F0%9F%92%A2&skipped_label=%F0%9F%A4%B7 -

- -

- There is also a &compact_message query parameter, which will default to displaying ✔, ✘ and ➟, separated by a horizontal bar |. -

-` - const commonPreviewProps = { passed: 477, failed: 2, diff --git a/services/appveyor/appveyor-tests.tester.js b/services/appveyor/appveyor-tests.tester.js index 102f532d29958..2c3f564df1ef5 100644 --- a/services/appveyor/appveyor-tests.tester.js +++ b/services/appveyor/appveyor-tests.tester.js @@ -1,38 +1,26 @@ -import queryString from 'querystring' -import Joi from 'joi' +import { + isDefaultTestTotals, + isDefaultCompactTestTotals, + isCustomTestTotals, + isCustomCompactTestTotals, +} from '../test-validators.js' import { createServiceTester } from '../tester.js' export const t = await createServiceTester() -const isAppveyorTestTotals = Joi.string().regex( - /^[0-9]+ passed(, [0-9]+ failed)?(, [0-9]+ skipped)?$/ -) - -const isCompactAppveyorTestTotals = Joi.string().regex( - /^✔ [0-9]+( \| ✘ [0-9]+)?( \| ➟ [0-9]+)?$/ -) - -const isCustomAppveyorTestTotals = Joi.string().regex( - /^[0-9]+ good(, [0-9]+ bad)?(, [0-9]+ n\/a)?$/ -) - -const isCompactCustomAppveyorTestTotals = Joi.string().regex( - /^💃 [0-9]+( \| 🤦‍♀️ [0-9]+)?( \| 🤷 [0-9]+)?$/ -) - t.create('Test status') .timeout(10000) .get('/NZSmartie/coap-net-iu0to.json') - .expectBadge({ label: 'tests', message: isAppveyorTestTotals }) + .expectBadge({ label: 'tests', message: isDefaultTestTotals }) t.create('Test status on branch') .timeout(10000) .get('/NZSmartie/coap-net-iu0to/master.json') - .expectBadge({ label: 'tests', message: isAppveyorTestTotals }) + .expectBadge({ label: 'tests', message: isDefaultTestTotals }) t.create('Test status with compact message') .timeout(10000) .get('/NZSmartie/coap-net-iu0to.json?compact_message') - .expectBadge({ label: 'tests', message: isCompactAppveyorTestTotals }) + .expectBadge({ label: 'tests', message: isDefaultCompactTestTotals }) t.create('Test status with custom labels') .timeout(10000) @@ -43,21 +31,21 @@ t.create('Test status with custom labels') skipped_label: 'n/a', }, }) - .expectBadge({ label: 'tests', message: isCustomAppveyorTestTotals }) + .expectBadge({ label: 'tests', message: isCustomTestTotals }) t.create('Test status with compact message and custom labels') .timeout(10000) - .get( - `/NZSmartie/coap-net-iu0to.json?${queryString.stringify({ + .get('/NZSmartie/coap-net-iu0to.json', { + qs: { compact_message: null, passed_label: '💃', failed_label: '🤦‍♀️', skipped_label: '🤷', - })}` - ) + }, + }) .expectBadge({ label: 'tests', - message: isCompactCustomAppveyorTestTotals, + message: isCustomCompactTestTotals, }) t.create('Test status on non-existent project') diff --git a/services/azure-devops/azure-devops-tests.service.js b/services/azure-devops/azure-devops-tests.service.js index a2939b95aebfc..b6d8c0e6a06d5 100644 --- a/services/azure-devops/azure-devops-tests.service.js +++ b/services/azure-devops/azure-devops-tests.service.js @@ -2,11 +2,24 @@ import Joi from 'joi' import { testResultQueryParamSchema, renderTestResultBadge, + documentation as commonDocumentation, } from '../test-results.js' import AzureDevOpsBase from './azure-devops-base.js' const commonAttrs = { keywords: ['vso', 'vsts', 'azure-devops'], + namedParams: { + organization: 'azuredevops-powershell', + project: 'azuredevops-powershell', + definitionId: '1', + branch: 'master', + }, + queryParams: { + passed_label: 'passed', + failed_label: 'failed', + skipped_label: 'skipped', + compact_message: null, + }, documentation: `

To obtain your own badge, you need to get 3 pieces of information: @@ -26,19 +39,7 @@ const commonAttrs = { Optionally, you can specify a named branch: https://img.shields.io/azure-devops/tests/ORGANIZATION/PROJECT/DEFINITION_ID/NAMED_BRANCH.svg.

-

- You may change the "passed", "failed" and "skipped" text on this badge by supplying query parameters &passed_label=, &failed_label= and &skipped_label= respectively. -
- There is also a &compact_message query parameter, which will default to displaying ✔, ✘ and ➟, separated by a horizontal bar |. -
- For example, if you want to use a different terminology: -
- /azure-devops/tests/ORGANIZATION/PROJECT/DEFINITION_ID.svg?passed_label=good&failed_label=bad&skipped_label=n%2Fa -
- Or, use symbols: -
- /azure-devops/tests/ORGANIZATION/PROJECT/DEFINITION_ID.svg?compact_message&passed_label=%F0%9F%8E%89&failed_label=%F0%9F%92%A2&skipped_label=%F0%9F%A4%B7 -

+${commonDocumentation} `, } @@ -71,29 +72,6 @@ export default class AzureDevOpsTests extends AzureDevOpsBase { static examples = [ { title: 'Azure DevOps tests', - pattern: ':organization/:project/:definitionId', - namedParams: { - organization: 'azuredevops-powershell', - project: 'azuredevops-powershell', - definitionId: '1', - }, - staticPreview: this.render({ - passed: 20, - failed: 1, - skipped: 1, - total: 22, - }), - ...commonAttrs, - }, - { - title: 'Azure DevOps tests (branch)', - pattern: ':organization/:project/:definitionId/:branch', - namedParams: { - organization: 'azuredevops-powershell', - project: 'azuredevops-powershell', - definitionId: '1', - branch: 'master', - }, staticPreview: this.render({ passed: 20, failed: 1, @@ -104,15 +82,6 @@ export default class AzureDevOpsTests extends AzureDevOpsBase { }, { title: 'Azure DevOps tests (compact)', - pattern: ':organization/:project/:definitionId', - namedParams: { - organization: 'azuredevops-powershell', - project: 'azuredevops-powershell', - definitionId: '1', - }, - queryParams: { - compact_message: null, - }, staticPreview: this.render({ passed: 20, failed: 1, @@ -124,16 +93,11 @@ export default class AzureDevOpsTests extends AzureDevOpsBase { }, { title: 'Azure DevOps tests with custom labels', - pattern: ':organization/:project/:definitionId', - namedParams: { - organization: 'azuredevops-powershell', - project: 'azuredevops-powershell', - definitionId: '1', - }, queryParams: { passed_label: 'good', failed_label: 'bad', skipped_label: 'n/a', + compact_message: null, }, staticPreview: this.render({ passed: 20, @@ -172,15 +136,16 @@ export default class AzureDevOpsTests extends AzureDevOpsBase { }) } - async handle( - { organization, project, definitionId, branch }, - { - compact_message: compactMessage, - passed_label: passedLabel, - failed_label: failedLabel, - skipped_label: skippedLabel, - } - ) { + static transform({ aggregatedResultsAnalysis }) { + const { totalTests: total, resultsByOutcome } = aggregatedResultsAnalysis + const passed = resultsByOutcome.Passed ? resultsByOutcome.Passed.count : 0 + const failed = resultsByOutcome.Failed ? resultsByOutcome.Failed.count : 0 + // assume the rest has been skipped + const skipped = total - passed - failed + return { passed, failed, skipped, total } + } + + async fetchTestResults({ organization, project, definitionId, branch }) { const errorMessages = { 404: 'build pipeline or test result summary not found', } @@ -193,8 +158,7 @@ export default class AzureDevOpsTests extends AzureDevOpsBase { ) // https://dev.azure.com/azuredevops-powershell/azuredevops-powershell/_apis/test/ResultSummaryByBuild?buildId=20 - - const json = await this.fetch({ + return await this.fetch({ url: `https://dev.azure.com/${organization}/${project}/_apis/test/ResultSummaryByBuild`, options: { qs: { buildId }, @@ -202,24 +166,24 @@ export default class AzureDevOpsTests extends AzureDevOpsBase { schema: buildTestResultSummarySchema, errorMessages, }) + } - const total = json.aggregatedResultsAnalysis.totalTests - - let passed = 0 - const passedTests = json.aggregatedResultsAnalysis.resultsByOutcome.Passed - if (passedTests) { - passed = passedTests.count - } - - let failed = 0 - const failedTests = json.aggregatedResultsAnalysis.resultsByOutcome.Failed - if (failedTests) { - failed = failedTests.count + async handle( + { organization, project, definitionId, branch }, + { + compact_message: compactMessage, + passed_label: passedLabel, + failed_label: failedLabel, + skipped_label: skippedLabel, } - - // assume the rest has been skipped - const skipped = total - passed - failed - const isCompact = compactMessage !== undefined + ) { + const json = await this.fetchTestResults({ + organization, + project, + definitionId, + branch, + }) + const { passed, failed, skipped, total } = this.constructor.transform(json) return this.constructor.render({ passed, failed, @@ -228,7 +192,7 @@ export default class AzureDevOpsTests extends AzureDevOpsBase { passedLabel, failedLabel, skippedLabel, - isCompact, + isCompact: compactMessage !== undefined, }) } } diff --git a/services/azure-devops/azure-devops-tests.tester.js b/services/azure-devops/azure-devops-tests.tester.js index d708183ac8fa5..000720328cd07 100644 --- a/services/azure-devops/azure-devops-tests.tester.js +++ b/services/azure-devops/azure-devops-tests.tester.js @@ -1,149 +1,48 @@ -import Joi from 'joi' +import { + isDefaultTestTotals, + isDefaultCompactTestTotals, + isCustomTestTotals, + isCustomCompactTestTotals, +} from '../test-validators.js' import { createServiceTester } from '../tester.js' export const t = await createServiceTester() -const org = 'azuredevops-powershell' -const project = 'azuredevops-powershell' -const definitionId = 1 -const nonExistentDefinitionId = 9999 -const buildId = 20 -const uriPrefix = `/${org}/${project}` -const azureDevOpsApiBaseUri = `https://dev.azure.com/${org}/${project}/_apis` -const mockBadgeUriPath = `${uriPrefix}/${definitionId}` -const mockBadgeUri = `${mockBadgeUriPath}.json` -const mockBranchBadgeUri = `${mockBadgeUriPath}/master.json` -const mockLatestBuildApiUriPath = `/build/builds?definitions=${definitionId}&%24top=1&statusFilter=completed&api-version=5.0-preview.4` -const mockLatestBranchBuildApiUriPath = `/build/builds?definitions=${definitionId}&%24top=1&statusFilter=completed&api-version=5.0-preview.4&branchName=refs%2Fheads%2Fmaster` -const mockNonExistentBuildApiUriPath = `/build/builds?definitions=${nonExistentDefinitionId}&%24top=1&statusFilter=completed&api-version=5.0-preview.4` -const mockTestResultSummaryApiUriPath = `/test/ResultSummaryByBuild?buildId=${buildId}` -const latestBuildResponse = { - count: 1, - value: [{ id: buildId }], -} -const mockEmptyTestResultSummaryResponse = { - aggregatedResultsAnalysis: { - totalTests: 0, - resultsByOutcome: {}, - }, -} -const mockTestResultSummaryResponse = { - aggregatedResultsAnalysis: { - totalTests: 3, - resultsByOutcome: { - Passed: { - count: 1, - }, - Failed: { - count: 1, - }, - Skipped: { - count: 1, - }, - }, - }, -} -const mockTestResultSummarySetup = nock => - nock(azureDevOpsApiBaseUri) - .get(mockLatestBuildApiUriPath) - .reply(200, latestBuildResponse) - .get(mockTestResultSummaryApiUriPath) - .reply(200, mockTestResultSummaryResponse) -const mockBranchTestResultSummarySetup = nock => - nock(azureDevOpsApiBaseUri) - .get(mockLatestBranchBuildApiUriPath) - .reply(200, latestBuildResponse) - .get(mockTestResultSummaryApiUriPath) - .reply(200, mockTestResultSummaryResponse) - -const expectedDefaultAzureDevOpsTestTotals = '1 passed, 1 failed, 1 skipped' -const expectedCompactAzureDevOpsTestTotals = '✔ 1 | ✘ 1 | ➟ 1' -const expectedCustomAzureDevOpsTestTotals = '1 good, 1 bad, 1 n/a' -const expectedCompactCustomAzureDevOpsTestTotals = '💃 1 | 🤦‍♀️ 1 | 🤷 1' - -function getLabelRegex(label, isCompact) { - return isCompact ? `(?:${label} [0-9]*)` : `(?:[0-9]* ${label})` -} - -function isAzureDevOpsTestTotals( - passedLabel, - failedLabel, - skippedLabel, - isCompact -) { - const passedRegex = getLabelRegex(passedLabel, isCompact) - const failedRegex = getLabelRegex(failedLabel, isCompact) - const skippedRegex = getLabelRegex(skippedLabel, isCompact) - const separator = isCompact ? ' | ' : ', ' - const regexStrings = [ - `^${passedRegex}$`, - `^${failedRegex}$`, - `^${skippedRegex}$`, - `^${passedRegex}${separator}${failedRegex}$`, - `^${failedRegex}${separator}${skippedRegex}$`, - `^${passedRegex}${separator}${skippedRegex}$`, - `^${passedRegex}${separator}${failedRegex}${separator}${skippedRegex}$`, - `^no tests$`, - ] - - return Joi.alternatives().try( - ...regexStrings.map(regexStr => Joi.string().regex(new RegExp(regexStr))) - ) -} - -const isDefaultAzureDevOpsTestTotals = isAzureDevOpsTestTotals( - 'passed', - 'failed', - 'skipped' -) -const isCompactAzureDevOpsTestTotals = isAzureDevOpsTestTotals( - '✔', - '✘', - '➟', - true -) -const isCustomAzureDevOpsTestTotals = isAzureDevOpsTestTotals( - 'good', - 'bad', - 'n\\/a' -) -const isCompactCustomAzureDevOpsTestTotals = isAzureDevOpsTestTotals( - '💃', - '🤦‍♀️', - '🤷', - true -) - t.create('unknown build definition') - .get(`${uriPrefix}/${nonExistentDefinitionId}.json`) + .get(`/swellaby/opensource/99999999.json`) .expectBadge({ label: 'tests', message: 'build pipeline not found' }) t.create('404 latest build error response') - .get(mockBadgeUri) + .get('/swellaby/fake/14.json') .intercept(nock => - nock(azureDevOpsApiBaseUri).get(mockLatestBuildApiUriPath).reply(404) + nock('https://dev.azure.com/swellaby/fake/_apis') + .get('/build/builds') + .query({ + definitions: 14, + $top: 1, + statusFilter: 'completed', + 'api-version': '5.0-preview.4', + }) + .reply(404) ) .expectBadge({ label: 'tests', message: 'build pipeline or test result summary not found', }) -t.create('no build response') - .get(`${uriPrefix}/${nonExistentDefinitionId}.json`) - .intercept(nock => - nock(azureDevOpsApiBaseUri).get(mockNonExistentBuildApiUriPath).reply(200, { - count: 0, - value: [], - }) - ) - .expectBadge({ label: 'tests', message: 'build pipeline not found' }) - t.create('no test result summary response') - .get(mockBadgeUri) + .get('/swellaby/fake/14.json') .intercept(nock => - nock(azureDevOpsApiBaseUri) - .get(mockLatestBuildApiUriPath) - .reply(200, latestBuildResponse) - .get(mockTestResultSummaryApiUriPath) + nock('https://dev.azure.com/swellaby/fake/_apis') + .get('/build/builds') + .query({ + definitions: 14, + $top: 1, + statusFilter: 'completed', + 'api-version': '5.0-preview.4', + }) + .reply(200, { count: 1, value: [{ id: 1234 }] }) + .get('/test/ResultSummaryByBuild') + .query({ buildId: 1234 }) .reply(404) ) .expectBadge({ @@ -151,113 +50,52 @@ t.create('no test result summary response') message: 'build pipeline or test result summary not found', }) -t.create('invalid test result summary response') - .get(mockBadgeUri) - .intercept(nock => - nock(azureDevOpsApiBaseUri) - .get(mockLatestBuildApiUriPath) - .reply(200, latestBuildResponse) - .get(mockTestResultSummaryApiUriPath) - .reply(200, {}) - ) - .expectBadge({ label: 'tests', message: 'invalid response data' }) +t.create('no build response') + .get(`/swellaby/opensource/174.json`) + .expectBadge({ label: 'tests', message: 'build pipeline not found' }) t.create('no tests in test result summary response') - .get(mockBadgeUri) - .intercept(nock => - nock(azureDevOpsApiBaseUri) - .get(mockLatestBuildApiUriPath) - .reply(200, latestBuildResponse) - .get(mockTestResultSummaryApiUriPath) - .reply(200, mockEmptyTestResultSummaryResponse) - ) + .get('/swellaby/opensource/14.json') .expectBadge({ label: 'tests', message: 'no tests' }) -t.create('test status') - .get(mockBadgeUri) - .intercept(mockTestResultSummarySetup) - .expectBadge({ - label: 'tests', - message: expectedDefaultAzureDevOpsTestTotals, - }) +t.create('test status').get('/swellaby/opensource/25.json').expectBadge({ + label: 'tests', + message: isDefaultTestTotals, +}) t.create('test status on branch') - .get(mockBranchBadgeUri) - .intercept(mockBranchTestResultSummarySetup) + .get('/swellaby/opensource/25/master.json') .expectBadge({ label: 'tests', - message: expectedDefaultAzureDevOpsTestTotals, + message: isDefaultTestTotals, }) t.create('test status with compact message') - .get(mockBadgeUri, { + .get('/swellaby/opensource/25.json', { qs: { compact_message: null, }, }) - .intercept(mockTestResultSummarySetup) .expectBadge({ label: 'tests', - message: expectedCompactAzureDevOpsTestTotals, + message: isDefaultCompactTestTotals, }) t.create('test status with custom labels') - .get(mockBadgeUri, { + .get('/swellaby/opensource/25.json', { qs: { passed_label: 'good', failed_label: 'bad', skipped_label: 'n/a', }, }) - .intercept(mockTestResultSummarySetup) .expectBadge({ label: 'tests', - message: expectedCustomAzureDevOpsTestTotals, + message: isCustomTestTotals, }) t.create('test status with compact message and custom labels') - .get(mockBadgeUri, { - qs: { - compact_message: null, - passed_label: '💃', - failed_label: '🤦‍♀️', - skipped_label: '🤷', - }, - }) - .intercept(mockTestResultSummarySetup) - .expectBadge({ - label: 'tests', - message: expectedCompactCustomAzureDevOpsTestTotals, - }) - -t.create('live test status') - .get(mockBadgeUri) - .expectBadge({ label: 'tests', message: isDefaultAzureDevOpsTestTotals }) - -t.create('live test status on branch') - .get(mockBranchBadgeUri) - .expectBadge({ label: 'tests', message: isDefaultAzureDevOpsTestTotals }) - -t.create('live test status with compact message') - .get(mockBadgeUri, { - qs: { - compact_message: null, - }, - }) - .expectBadge({ label: 'tests', message: isCompactAzureDevOpsTestTotals }) - -t.create('live test status with custom labels') - .get(mockBadgeUri, { - qs: { - passed_label: 'good', - failed_label: 'bad', - skipped_label: 'n/a', - }, - }) - .expectBadge({ label: 'tests', message: isCustomAzureDevOpsTestTotals }) - -t.create('live test status with compact message and custom labels') - .get(mockBadgeUri, { + .get('/swellaby/opensource/25.json', { qs: { compact_message: null, passed_label: '💃', @@ -267,5 +105,5 @@ t.create('live test status with compact message and custom labels') }) .expectBadge({ label: 'tests', - message: isCompactCustomAzureDevOpsTestTotals, + message: isCustomCompactTestTotals, }) diff --git a/services/clearlydefined/clearlydefined-score.service.js b/services/clearlydefined/clearlydefined-score.service.js new file mode 100644 index 0000000000000..f480581af6479 --- /dev/null +++ b/services/clearlydefined/clearlydefined-score.service.js @@ -0,0 +1,74 @@ +import Joi from 'joi' +import { + nonNegativeInteger, + optionalNonNegativeInteger, +} from '../validators.js' +import { floorCount as floorCountColor } from '../color-formatters.js' +import { BaseJsonService, NotFound } from '../index.js' + +const schema = Joi.object({ + scores: Joi.object({ + effective: nonNegativeInteger, + }).required(), + described: Joi.object({ + files: optionalNonNegativeInteger, + }), +}).required() + +// This service based on the REST API for clearlydefined.io +// https://api.clearlydefined.io/api-docs/ +export default class ClearlyDefinedService extends BaseJsonService { + static category = 'analysis' + static route = { + base: 'clearlydefined', + pattern: 'score/:type/:provider/:namespace/:name/:revision', + } + + static examples = [ + { + title: 'ClearlyDefined Score', + namedParams: { + type: 'npm', + provider: 'npmjs', + namespace: '-', + name: 'jquery', + revision: '3.4.1', + }, + staticPreview: this.render({ score: 88 }), + }, + ] + + static defaultBadgeData = { label: 'score' } + + static render({ score }) { + score = Math.round(score) + return { + label: 'score', + message: `${score}/100`, + color: floorCountColor(score, 40, 60, 100), + } + } + + async fetch({ type, provider, namespace, name, revision }) { + return this._requestJson({ + schema, + url: `https://api.clearlydefined.io/definitions/${type}/${provider}/${namespace}/${name}/${revision}`, + errorMessages: { + 500: 'unknown type, provider, or upstream issue', + }, + }) + } + + async handle({ type, provider, namespace, name, revision }) { + const data = await this.fetch({ type, provider, namespace, name, revision }) + // Return score only if definition contains some files, + // else it was an incomplete response due to unknown coordinates + if (data.described.files > 0) { + return this.constructor.render({ score: data.scores.effective }) + } else { + throw new NotFound({ + prettyMessage: 'unknown namespace, name, or revision', + }) + } + } +} diff --git a/services/clearlydefined/clearlydefined-score.tester.js b/services/clearlydefined/clearlydefined-score.tester.js new file mode 100644 index 0000000000000..6d635e814fd24 --- /dev/null +++ b/services/clearlydefined/clearlydefined-score.tester.js @@ -0,0 +1,24 @@ +import Joi from 'joi' +import { createServiceTester } from '../tester.js' +export const t = await createServiceTester() + +t.create('ClearlyDefined Score') + .get('/score/npm/npmjs/-/jquery/3.4.1.json') + .expectBadge({ + label: 'score', + message: Joi.string().regex(/^\d+\/\d+$/), + }) + +t.create('ClearlyDefined Score (name not found)') + .get('/score/npm/npmjs/-/not-a-real-package/0.0.0.json') + .expectBadge({ + label: 'score', + message: 'unknown namespace, name, or revision', + }) + +t.create('ClearlyDefined Score (type not found)') + .get('/score/abc/xyz/-/not-a-real-package/0.0.0.json') + .expectBadge({ + label: 'score', + message: 'unknown type, provider, or upstream issue', + }) diff --git a/services/crates/crates-base.js b/services/crates/crates-base.js index e87fe5cea875f..63699a581e44d 100644 --- a/services/crates/crates-base.js +++ b/services/crates/crates-base.js @@ -14,7 +14,7 @@ const crateSchema = Joi.object({ .items( Joi.object({ downloads: nonNegativeInteger, - license: Joi.string().required(), + license: Joi.string().required().allow(null), }) ) .min(1) @@ -25,7 +25,7 @@ const versionSchema = Joi.object({ version: Joi.object({ downloads: nonNegativeInteger, num: Joi.string().required(), - license: Joi.string().required(), + license: Joi.string().required().allow(null), }).required(), }).required() diff --git a/services/crates/crates-downloads.tester.js b/services/crates/crates-downloads.tester.js index 9e2e13ccf47aa..629cd05ed0033 100644 --- a/services/crates/crates-downloads.tester.js +++ b/services/crates/crates-downloads.tester.js @@ -1,11 +1,6 @@ -import { ServiceTester } from '../tester.js' import { isMetric } from '../test-validators.js' - -export const t = new ServiceTester({ - id: 'crates', - title: 'crates.io', - pathPrefix: '/crates', -}) +import { createServiceTester } from '../tester.js' +export const t = await createServiceTester() t.create('total downloads') .get('/d/libc.json') diff --git a/services/crates/crates-license.service.js b/services/crates/crates-license.service.js index c32ab9517bd8f..562f44841cabe 100644 --- a/services/crates/crates-license.service.js +++ b/services/crates/crates-license.service.js @@ -1,3 +1,4 @@ +import { InvalidResponse } from '../index.js' import { BaseCratesService, keywords } from './crates-base.js' export default class CratesLicense extends BaseCratesService { @@ -21,28 +22,30 @@ export default class CratesLicense extends BaseCratesService { }, ] - static render({ license }) { - return { - label: 'license', - message: license, - color: 'blue', - } + static defaultBadgeData = { label: 'license', color: 'blue' } + + static render({ license: message }) { + return { message } } - async handle({ crate, version }) { - const json = await this.fetch({ crate, version }) + static transform({ errors, version, versions }) { + // crates.io returns a 200 response with an errors object in + // error scenarios, e.g. https://crates.io/api/v1/crates/libc/0.1 + if (errors) { + throw new InvalidResponse({ prettyMessage: errors[0].detail }) + } - if (json.errors) { - /* a call like - https://crates.io/api/v1/crates/libc/0.1 - or - https://crates.io/api/v1/crates/libc/0.1.76 - returns a 200 OK with an errors object */ - return { message: json.errors[0].detail } + const license = version ? version.license : versions[0].license + if (!license) { + throw new InvalidResponse({ prettyMessage: 'invalid null license' }) } - return this.constructor.render({ - license: json.version ? json.version.license : json.versions[0].license, - }) + return { license } + } + + async handle({ crate, version }) { + const json = await this.fetch({ crate, version }) + const { license } = this.constructor.transform(json) + return this.constructor.render({ license }) } } diff --git a/services/crates/crates-license.spec.js b/services/crates/crates-license.spec.js new file mode 100644 index 0000000000000..f6454094dc3d2 --- /dev/null +++ b/services/crates/crates-license.spec.js @@ -0,0 +1,38 @@ +import { expect } from 'chai' +import { test, given } from 'sazerac' +import { InvalidResponse } from '../index.js' +import CratesLicense from './crates-license.service.js' + +describe('CratesLicense', function () { + test(CratesLicense.transform, () => { + given({ + version: { num: '1.0.0', license: 'MIT' }, + versions: [{ license: 'MIT/Apache 2.0' }], + }).expect({ license: 'MIT' }) + given({ + versions: [{ license: 'MIT/Apache 2.0' }], + }).expect({ license: 'MIT/Apache 2.0' }) + }) + + it('throws InvalidResponse on error response', function () { + expect(() => + CratesLicense.transform({ errors: [{ detail: 'invalid semver' }] }) + ) + .to.throw(InvalidResponse) + .with.property('prettyMessage', 'invalid semver') + }) + + it('throws InvalidResponse on null license with specific version', function () { + expect(() => + CratesLicense.transform({ version: { num: '1.2.3', license: null } }) + ) + .to.throw(InvalidResponse) + .with.property('prettyMessage', 'invalid null license') + }) + + it('throws InvalidResponse on null license with latest version', function () { + expect(() => CratesLicense.transform({ versions: [{ license: null }] })) + .to.throw(InvalidResponse) + .with.property('prettyMessage', 'invalid null license') + }) +}) diff --git a/services/crates/crates-license.tester.js b/services/crates/crates-license.tester.js index 390295433b0bd..6351c14f85635 100644 --- a/services/crates/crates-license.tester.js +++ b/services/crates/crates-license.tester.js @@ -1,10 +1,5 @@ -import { ServiceTester } from '../tester.js' - -export const t = new ServiceTester({ - id: 'crates', - title: 'crates.io', - pathPrefix: '/crates/l', -}) +import { createServiceTester } from '../tester.js' +export const t = await createServiceTester() t.create('license') .get('/libc.json') @@ -16,4 +11,13 @@ t.create('license (with version)') t.create('license (not found)') .get('/not-a-real-package.json') - .expectBadge({ label: 'crates.io', message: 'not found' }) + .expectBadge({ label: 'license', message: 'not found' }) + +// https://github.com/badges/shields/issues/7073 +t.create('license (null licenses in history)') + .get('/stun.json') + .expectBadge({ label: 'license', message: 'MIT/Apache-2.0' }) + +t.create('license (version with null license)') + .get('/stun/0.0.1.json') + .expectBadge({ label: 'license', message: 'invalid null license' }) diff --git a/services/david/david.service.js b/services/david/david.service.js index 67e171d93b08e..6a2b47d8010ca 100644 --- a/services/david/david.service.js +++ b/services/david/david.service.js @@ -71,22 +71,19 @@ export default class David extends BaseJsonService { } async fetch({ kind, user, repo, path }) { - const url = `https://david-dm.org/${user}/${repo}/${ - kind ? `${kind}-` : '' - }info.json` + // Note: David does not return canonical 404 response codes for 'not found' + // cases, but will instead return various 50x errors. Accordingly we account + // for both 'not found' as well as typical/real internal server errors. + const notFoundError = 'repo or path not found or david internal error' return this._requestJson({ schema, - url, - options: { qs: { path } }, + url: `https://status.david-dm.org/gh/${user}/${repo}`, + options: { qs: { path, type: kind } }, errorMessages: { - /* note: - david returns a 504 response for 'not found' - e.g: https://david-dm.org/foo/barbaz/info.json - not a 404 so we can't handle 'not found' cleanly - because this might also be some other error. - */ - 504: 'repo or path not found or david internal error', + 502: notFoundError, + 503: notFoundError, + 504: notFoundError, }, }) } diff --git a/services/dynamic/dynamic-json.tester.js b/services/dynamic/dynamic-json.tester.js index 7d34bdc1db3d5..40c91376e73dc 100644 --- a/services/dynamic/dynamic-json.tester.js +++ b/services/dynamic/dynamic-json.tester.js @@ -27,7 +27,7 @@ t.create('Malformed url') ) .expectBadge({ label: 'Package Name', - message: 'inaccessible', + message: 'invalid', color: 'lightgrey', }) @@ -136,7 +136,8 @@ t.create('request should set Accept header') ) .expectBadge({ label: 'custom badge', message: 'test' }) .after(() => { - expect(headers).to.have.property('accept', 'application/json') + expect(headers).to.have.property('accept') + expect(headers.accept).to.deep.equal(['application/json']) }) t.create('query with lexical error') diff --git a/services/github/auth/admin.js b/services/github/auth/admin.js deleted file mode 100644 index 9ffea4d056415..0000000000000 --- a/services/github/auth/admin.js +++ /dev/null @@ -1,32 +0,0 @@ -import { makeSecretIsValid } from '../../../core/server/secret-is-valid.js' - -function setRoutes({ shieldsSecret }, { apiProvider, server }) { - const secretIsValid = makeSecretIsValid(shieldsSecret) - - // Allow the admin to obtain the tokens for operational and debugging - // purposes. This could be used to: - // - // - Ensure tokens have been propagated to all servers - // - Debug GitHub badge failures - // - // The admin can authenticate with HTTP Basic Auth, with an empty/any - // username and the shields secret in the password and an empty/any - // password. - // - // e.g. - // curl --insecure -u ':very-very-secret' 'https://img.shields.io/$github-auth/tokens' - server.ajax.on('github-auth/tokens', (json, end, ask) => { - if (!secretIsValid(ask.password)) { - // An unknown entity tries to connect. Let the connection linger for a minute. - return setTimeout(() => { - ask.res.statusCode = 401 - ask.res.setHeader('Cache-Control', 'private') - end('Invalid secret.') - }, 10000) - } - ask.res.setHeader('Cache-Control', 'private') - end(apiProvider.serializeDebugInfo({ sanitize: false })) - }) -} - -export { setRoutes } diff --git a/services/github/auth/admin.spec.js b/services/github/auth/admin.spec.js deleted file mode 100644 index fb751498e0270..0000000000000 --- a/services/github/auth/admin.spec.js +++ /dev/null @@ -1,71 +0,0 @@ -import { expect } from 'chai' -import Camp from '@shields_io/camp' -import portfinder from 'portfinder' -import got from '../../../core/got-test-client.js' -import GithubApiProvider from '../github-api-provider.js' -import { setRoutes } from './admin.js' - -describe('GitHub admin route', function () { - const shieldsSecret = '7'.repeat(40) - - let port, baseUrl - before(async function () { - port = await portfinder.getPortPromise() - baseUrl = `http://127.0.0.1:${port}` - }) - - let camp - before(async function () { - camp = Camp.start({ port, hostname: '::' }) - await new Promise(resolve => camp.on('listening', () => resolve())) - }) - after(async function () { - if (camp) { - await new Promise(resolve => camp.close(resolve)) - camp = undefined - } - }) - - before(function () { - const apiProvider = new GithubApiProvider({ withPooling: true }) - setRoutes({ shieldsSecret }, { apiProvider, server: camp }) - }) - - context('the password is correct', function () { - it('returns a valid JSON response', async function () { - const { statusCode, body, headers } = await got( - `${baseUrl}/$github-auth/tokens`, - { - username: '', - password: shieldsSecret, - responseType: 'json', - } - ) - expect(statusCode).to.equal(200) - expect(body).to.be.ok - expect(headers['cache-control']).to.equal('private') - }) - }) - - // Disabled because this code isn't modified often and the test is very - // slow. To run it, run `SLOW=true npm run test:core` - // - // I wasn't able to make this work with fake timers: - // https://github.com/sinonjs/sinon/issues/1739 - if (process.env.SLOW) { - context('the password is missing', function () { - it('returns the expected message', async function () { - this.timeout(11000) - const { statusCode, body, headers } = await got( - `${baseUrl}/$github-auth/tokens`, - { - throwHttpErrors: false, - } - ) - expect(statusCode).to.equal(401) - expect(body).to.equal('"Invalid secret."') - expect(headers['cache-control']).to.equal('private') - }) - }) - } -}) diff --git a/services/github/github-api-provider.js b/services/github/github-api-provider.js index bfb26c20abf77..59647fd7bb1fd 100644 --- a/services/github/github-api-provider.js +++ b/services/github/github-api-provider.js @@ -54,18 +54,6 @@ class GithubApiProvider { } } - serializeDebugInfo({ sanitize = true } = {}) { - if (this.withPooling) { - return { - standardTokens: this.standardTokens.serializeDebugInfo({ sanitize }), - searchTokens: this.searchTokens.serializeDebugInfo({ sanitize }), - graphqlTokens: this.graphqlTokens.serializeDebugInfo({ sanitize }), - } - } else { - return {} - } - } - addToken(tokenString) { if (this.withPooling) { this.standardTokens.add(tokenString) diff --git a/services/github/github-constellation.js b/services/github/github-constellation.js index e74114e7a46f9..429f8a9fde9b4 100644 --- a/services/github/github-constellation.js +++ b/services/github/github-constellation.js @@ -2,7 +2,6 @@ import { AuthHelper } from '../../core/base-service/auth-helper.js' import RedisTokenPersistence from '../../core/token-pooling/redis-token-persistence.js' import log from '../../core/server/log.js' import GithubApiProvider from './github-api-provider.js' -import { setRoutes as setAdminRoutes } from './auth/admin.js' import { setRoutes as setAcceptorRoutes } from './auth/acceptor.js' // Convenience class with all the stuff related to the Github API and its @@ -23,7 +22,6 @@ class GithubConstellation { constructor(config) { this._debugEnabled = config.service.debug.enabled this._debugIntervalSeconds = config.service.debug.intervalSeconds - this.shieldsSecret = config.private.shields_secret const { redis_url: redisUrl, gh_token: globalToken } = config.private if (redisUrl) { @@ -74,9 +72,6 @@ class GithubConstellation { this.apiProvider.addToken(tokenString) }) - const { shieldsSecret, apiProvider } = this - setAdminRoutes({ shieldsSecret }, { apiProvider, server }) - if (this.oauthHelper.isConfigured) { setAcceptorRoutes({ server, diff --git a/services/github/github-hacktoberfest.service.js b/services/github/github-hacktoberfest.service.js index bf8782c17a5bf..c78311f896318 100644 --- a/services/github/github-hacktoberfest.service.js +++ b/services/github/github-hacktoberfest.service.js @@ -60,7 +60,7 @@ export default class GithubHacktoberfestCombinedStatus extends GithubAuthV4Servi static category = 'issue-tracking' static route = { base: 'github/hacktoberfest', - pattern: ':year(2019|2020)/:user/:repo', + pattern: ':year(2019|2020|2021)/:user/:repo', queryParamSchema, } @@ -68,7 +68,7 @@ export default class GithubHacktoberfestCombinedStatus extends GithubAuthV4Servi { title: 'GitHub Hacktoberfest combined status', namedParams: { - year: '2020', + year: '2021', user: 'snyk', repo: 'snyk', }, @@ -82,7 +82,7 @@ export default class GithubHacktoberfestCombinedStatus extends GithubAuthV4Servi { title: 'GitHub Hacktoberfest combined status (suggestion label override)', namedParams: { - year: '2020', + year: '2021', user: 'tmrowco', repo: 'tmrowapp-contrib', }, @@ -90,7 +90,7 @@ export default class GithubHacktoberfestCombinedStatus extends GithubAuthV4Servi suggestion_label: 'help wanted', }, staticPreview: this.render({ - year: '2020', + year: '2021', suggestedIssueCount: 12, contributionCount: 8, daysLeft: 15, diff --git a/services/jenkins/jenkins-tests.service.js b/services/jenkins/jenkins-tests.service.js index 4dcfaac4c1c66..68ddaea389c28 100644 --- a/services/jenkins/jenkins-tests.service.js +++ b/services/jenkins/jenkins-tests.service.js @@ -51,7 +51,7 @@ export default class JenkinsTests extends JenkinsBase { passed_label: 'passed', failed_label: 'failed', skipped_label: 'skipped', - jobUrl: 'https://jenkins.sqlalchemy.org/job/alembic_coverage', + jobUrl: 'https://jenkins.sqlalchemy.org/job/alembic_gerrit', }, staticPreview: this.render({ passed: 477, diff --git a/services/jenkins/jenkins-tests.tester.js b/services/jenkins/jenkins-tests.tester.js index c2bdcbefa51c2..73a1c1b8257d7 100644 --- a/services/jenkins/jenkins-tests.tester.js +++ b/services/jenkins/jenkins-tests.tester.js @@ -13,43 +13,34 @@ export const t = await createServiceTester() // https://wiki.jenkins.io/pages/viewpage.action?pageId=58001258 t.create('Test status') - .get('/tests.json?jobUrl=https://jenkins.sqlalchemy.org/job/alembic_coverage') + .get('/tests.json?jobUrl=https://jenkins.sqlalchemy.org/job/alembic_gerrit') .expectBadge({ label: 'tests', message: isDefaultTestTotals }) t.create('Test status with compact message') - .get( - '/tests.json?jobUrl=https://jenkins.sqlalchemy.org/job/alembic_coverage', - { - qs: { compact_message: null }, - } - ) + .get('/tests.json?jobUrl=https://jenkins.sqlalchemy.org/job/alembic_gerrit', { + qs: { compact_message: null }, + }) .expectBadge({ label: 'tests', message: isDefaultCompactTestTotals }) t.create('Test status with custom labels') - .get( - '/tests.json?jobUrl=https://jenkins.sqlalchemy.org/job/alembic_coverage', - { - qs: { - passed_label: 'good', - failed_label: 'bad', - skipped_label: 'n/a', - }, - } - ) + .get('/tests.json?jobUrl=https://jenkins.sqlalchemy.org/job/alembic_gerrit', { + qs: { + passed_label: 'good', + failed_label: 'bad', + skipped_label: 'n/a', + }, + }) .expectBadge({ label: 'tests', message: isCustomTestTotals }) t.create('Test status with compact message and custom labels') - .get( - '/tests.json?jobUrl=https://jenkins.sqlalchemy.org/job/alembic_coverage', - { - qs: { - compact_message: null, - passed_label: '💃', - failed_label: '🤦‍♀️', - skipped_label: '🤷', - }, - } - ) + .get('/tests.json?jobUrl=https://jenkins.sqlalchemy.org/job/alembic_gerrit', { + qs: { + compact_message: null, + passed_label: '💃', + failed_label: '🤦‍♀️', + skipped_label: '🤷', + }, + }) .expectBadge({ label: 'tests', message: isCustomCompactTestTotals, diff --git a/services/modrinth/modrinth.service.js b/services/modrinth/modrinth.service.js new file mode 100644 index 0000000000000..25fdbdb9882ae --- /dev/null +++ b/services/modrinth/modrinth.service.js @@ -0,0 +1,47 @@ +import Joi from 'joi' +import { BaseJsonService } from '../index.js' +import { metric } from '../text-formatters.js' +import { downloadCount as downloadCountColor } from '../color-formatters.js' +import { nonNegativeInteger } from '../validators.js' + +const schema = Joi.object({ + downloads: nonNegativeInteger, +}).required() + +export default class Modrinth extends BaseJsonService { + static category = 'downloads' + + static route = { + base: 'modrinth/dt', + pattern: ':modId', + } + + static examples = [ + { + title: 'Modrinth', + namedParams: { modId: 'AANobbMI' }, + staticPreview: this.render({ downloads: 120000 }), + }, + ] + + static defaultBadgeData = { label: 'downloads' } + + static render({ downloads }) { + return { + message: metric(downloads), + color: downloadCountColor(downloads), + } + } + + async fetch({ modId }) { + return this._requestJson({ + schema, + url: `https://api.modrinth.com/api/v1/mod/${modId}`, + }) + } + + async handle({ modId }) { + const { downloads } = await this.fetch({ modId }) + return this.constructor.render({ downloads }) + } +} diff --git a/services/modrinth/modrinth.tester.js b/services/modrinth/modrinth.tester.js new file mode 100644 index 0000000000000..26ac709ab67fd --- /dev/null +++ b/services/modrinth/modrinth.tester.js @@ -0,0 +1,12 @@ +import { createServiceTester } from '../tester.js' +import { isMetric } from '../test-validators.js' + +export const t = await createServiceTester() + +t.create('Downloads') + .get('/AANobbMI.json') + .expectBadge({ label: 'downloads', message: isMetric }) + +t.create('Downloads (not found)') + .get('/not-existing.json') + .expectBadge({ label: 'downloads', message: 'not found', color: 'red' }) diff --git a/services/mozilla-observatory/mozilla-observatory.service.js b/services/mozilla-observatory/mozilla-observatory.service.js index 8f436056c2d0d..0b8ad060c9ebc 100644 --- a/services/mozilla-observatory/mozilla-observatory.service.js +++ b/services/mozilla-observatory/mozilla-observatory.service.js @@ -103,7 +103,7 @@ export default class MozillaObservatory extends BaseJsonService { options: { method: 'POST', qs: { host }, - form: { hidden: !publish }, + form: { hidden: (!publish).toString() }, }, }) } diff --git a/services/opm/opm-version.service.js b/services/opm/opm-version.service.js index 6d9f41c43880d..fa1a42ad779be 100644 --- a/services/opm/opm-version.service.js +++ b/services/opm/opm-version.service.js @@ -40,11 +40,10 @@ export default class OpmVersion extends BaseService { }) // TODO: set followRedirect to false and intercept 302 redirects - const location = res.request.redirects[0] - if (!location) { + if (!res.redirected) { throw new NotFound({ prettyMessage: 'module not found' }) } - const version = location.match(`${moduleName}-(.+).opm`)[1] + const version = res.url.match(`${moduleName}-(.+).opm`)[1] if (!version) { throw new InvalidResponse({ prettyMessage: 'version invalid' }) } diff --git a/services/requires/requires.tester.js b/services/requires/requires.tester.js index 566c5b34c11ec..b8b016411b906 100644 --- a/services/requires/requires.tester.js +++ b/services/requires/requires.tester.js @@ -6,15 +6,34 @@ const isRequireStatus = Joi.string().regex( /^(up to date|outdated|insecure|unknown)$/ ) -t.create('requirements (valid, without branch)') - .get('/github/zulip/zulip.json') +// Package targets can be found at https://requires.io/public +// However, there does seem to be some retention issues where +// results for projects are purged after some number of days. +// https://github.com/badges/shields/issues/7015 +// https://github.com/requires/api/issues/5 +t.create('requirements (valid GitHub, without branch)') + .get('/github/Hongbo-Miao/hongbomiao.com.json') .expectBadge({ label: 'requirements', message: isRequireStatus, }) -t.create('requirements (valid, with branch)') - .get('/github/zulip/zulip/master.json') +t.create('requirements (valid GitHub, with branch)') + .get('/github/Hongbo-Miao/hongbomiao.com/main.json') + .expectBadge({ + label: 'requirements', + message: isRequireStatus, + }) + +t.create('requirements (valid Bitbucket, without branch)') + .get('/bitbucket/code-orange/django-ispstack.json') + .expectBadge({ + label: 'requirements', + message: isRequireStatus, + }) + +t.create('requirements (valid Bitbucket, with branch)') + .get('/bitbucket/code-orange/django-ispstack/master.json') .expectBadge({ label: 'requirements', message: isRequireStatus, diff --git a/services/security-headers/security-headers.service.js b/services/security-headers/security-headers.service.js index 0b935a871eb45..45f8a2b751482 100644 --- a/services/security-headers/security-headers.service.js +++ b/services/security-headers/security-headers.service.js @@ -83,7 +83,7 @@ export default class SecurityHeaders extends BaseService { }, }) - const grade = res.headers['x-grade'] + const grade = res.headers.get('x-grade') if (!grade) { throw new NotFound({ prettyMessage: 'not available' }) diff --git a/services/test-helpers.js b/services/test-helpers.js index 876467ebed614..f66a38e76464e 100644 --- a/services/test-helpers.js +++ b/services/test-helpers.js @@ -1,7 +1,7 @@ import bytes from 'bytes' import nock from 'nock' import config from 'config' -import { fetchFactory } from '../core/base-service/got.js' +import { sendRequest } from '../core/base-service/node-fetch.js' const runnerConfig = config.util.toObject() function cleanUpNockAfterEach() { @@ -31,7 +31,10 @@ function noToken(serviceClass) { } } -const sendAndCacheRequest = fetchFactory(bytes(runnerConfig.public.fetchLimit)) +const sendAndCacheRequest = sendRequest.bind( + sendRequest, + bytes(runnerConfig.public.fetchLimit) +) const defaultContext = { sendAndCacheRequest } diff --git a/services/weblate/weblate-base.js b/services/weblate/weblate-base.js index 12aed7c901e9d..857344bf31cd7 100644 --- a/services/weblate/weblate-base.js +++ b/services/weblate/weblate-base.js @@ -15,7 +15,10 @@ export default class WeblateBase extends BaseJsonService { async fetch(requestParams) { return this._requestJson( - this.authHelper.withBearerAuthHeader(requestParams, 'Token') + this.authHelper.withBearerAuthHeader( + requestParams, + 'Token' // lgtm [js/hardcoded-credentials] + ) ) } }